radiant-reader-extension 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. data/.gitignore +2 -0
  2. data/README.md +89 -0
  3. data/Rakefile +140 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/admin/messages_controller.rb +20 -0
  6. data/app/controllers/admin/reader_settings_controller.rb +92 -0
  7. data/app/controllers/admin/readers_controller.rb +28 -0
  8. data/app/controllers/password_resets_controller.rb +64 -0
  9. data/app/controllers/reader_action_controller.rb +84 -0
  10. data/app/controllers/reader_activations_controller.rb +60 -0
  11. data/app/controllers/reader_sessions_controller.rb +56 -0
  12. data/app/controllers/readers_controller.rb +131 -0
  13. data/app/helpers/admin/reader_settings_helper.rb +36 -0
  14. data/app/models/message.rb +108 -0
  15. data/app/models/message_function.rb +37 -0
  16. data/app/models/message_reader.rb +13 -0
  17. data/app/models/reader.rb +146 -0
  18. data/app/models/reader_notifier.rb +34 -0
  19. data/app/models/reader_session.rb +3 -0
  20. data/app/views/admin/messages/_form.html.haml +29 -0
  21. data/app/views/admin/messages/_help.html.haml +41 -0
  22. data/app/views/admin/messages/_message_description.html.haml +3 -0
  23. data/app/views/admin/messages/edit.html.haml +16 -0
  24. data/app/views/admin/messages/new.html.haml +16 -0
  25. data/app/views/admin/reader_settings/_setting.html.haml +24 -0
  26. data/app/views/admin/reader_settings/edit.html.haml +10 -0
  27. data/app/views/admin/reader_settings/index.html.haml +35 -0
  28. data/app/views/admin/reader_settings/show.html.haml +1 -0
  29. data/app/views/admin/readers/_avatar.html.haml +3 -0
  30. data/app/views/admin/readers/_form.html.haml +50 -0
  31. data/app/views/admin/readers/_list_head.html.haml +9 -0
  32. data/app/views/admin/readers/_listed.html.haml +22 -0
  33. data/app/views/admin/readers/_password_fields.html.haml +18 -0
  34. data/app/views/admin/readers/edit.html.haml +8 -0
  35. data/app/views/admin/readers/index.html.haml +17 -0
  36. data/app/views/admin/readers/new.html.haml +7 -0
  37. data/app/views/admin/readers/remove.html.haml +18 -0
  38. data/app/views/admin/sites/_choose_reader_layout.html.haml +7 -0
  39. data/app/views/password_resets/create.html.haml +13 -0
  40. data/app/views/password_resets/edit.html.haml +71 -0
  41. data/app/views/password_resets/new.html.haml +31 -0
  42. data/app/views/reader_activations/_activation_required.html.haml +34 -0
  43. data/app/views/reader_activations/_on_activation.html.haml +4 -0
  44. data/app/views/reader_activations/show.html.haml +41 -0
  45. data/app/views/reader_notifier/message.html.haml +1 -0
  46. data/app/views/reader_sessions/_login_form.html.haml +59 -0
  47. data/app/views/reader_sessions/new.html.haml +38 -0
  48. data/app/views/readers/_contributions.html.haml +2 -0
  49. data/app/views/readers/_controls.html.haml +25 -0
  50. data/app/views/readers/_extra_controls.html.haml +0 -0
  51. data/app/views/readers/_flasher.html.haml +6 -0
  52. data/app/views/readers/_form.html.haml +73 -0
  53. data/app/views/readers/create.html.haml +28 -0
  54. data/app/views/readers/edit.html.haml +47 -0
  55. data/app/views/readers/index.html.haml +16 -0
  56. data/app/views/readers/login.html.haml +15 -0
  57. data/app/views/readers/new.html.haml +41 -0
  58. data/app/views/readers/permission_denied.html.haml +23 -0
  59. data/app/views/readers/show.html.haml +35 -0
  60. data/app/views/wrappers/_field_errors.html.haml +5 -0
  61. data/config/routes.rb +22 -0
  62. data/config/settings.rb +9 -0
  63. data/db/migrate/001_create_readers.rb +31 -0
  64. data/db/migrate/002_extend_sites.rb +17 -0
  65. data/db/migrate/003_reader_honorifics.rb +12 -0
  66. data/db/migrate/004_user_readers.rb +11 -0
  67. data/db/migrate/005_last_login.rb +15 -0
  68. data/db/migrate/007_adapt_for_authlogic.rb +27 -0
  69. data/db/migrate/20090921125653_reader_messages.rb +27 -0
  70. data/db/migrate/20090924164413_functional_messages.rb +9 -0
  71. data/db/migrate/20090925081225_standard_messages.rb +106 -0
  72. data/db/migrate/20091006102438_message_visibility.rb +9 -0
  73. data/db/migrate/20091010083503_registration_config.rb +10 -0
  74. data/db/migrate/20091019124021_message_functions.rb +9 -0
  75. data/db/migrate/20091020133533_forenames.rb +9 -0
  76. data/db/migrate/20091020135152_contacts.rb +23 -0
  77. data/db/migrate/20091111090819_ensure_functional_messages_visible.rb +9 -0
  78. data/db/migrate/20091119092936_messages_have_layout.rb +9 -0
  79. data/db/migrate/20100922152338_lock_versions.rb +9 -0
  80. data/db/migrate/20100927095703_default_settings.rb +14 -0
  81. data/db/migrate/20101004074945_unlock_version.rb +9 -0
  82. data/lib/config_extensions.rb +5 -0
  83. data/lib/controller_extensions.rb +77 -0
  84. data/lib/reader_admin_ui.rb +64 -0
  85. data/lib/reader_helper.rb +36 -0
  86. data/lib/reader_site.rb +10 -0
  87. data/lib/reader_tags.rb +297 -0
  88. data/lib/rfc822.rb +29 -0
  89. data/lib/tasks/reader_extension_tasks.rake +28 -0
  90. data/pkg/radiant-reader-extension-0.9.0.gem +0 -0
  91. data/public/images/admin/chk_off.png +0 -0
  92. data/public/images/admin/chk_on.png +0 -0
  93. data/public/images/admin/new-message.png +0 -0
  94. data/public/images/admin/new-reader.png +0 -0
  95. data/public/javascripts/admin/messages.js +13 -0
  96. data/public/stylesheets/sass/admin/reader.sass +95 -0
  97. data/radiant-reader-extension.gemspec +184 -0
  98. data/reader_extension.rb +55 -0
  99. data/spec/controllers/admin/messages_controller_spec.rb +38 -0
  100. data/spec/controllers/admin/readers_controller_spec.rb +14 -0
  101. data/spec/controllers/password_resets_controller_spec.rb +140 -0
  102. data/spec/controllers/reader_activations_controller_spec.rb +45 -0
  103. data/spec/controllers/readers_controller_spec.rb +193 -0
  104. data/spec/datasets/messages_dataset.rb +49 -0
  105. data/spec/datasets/reader_layouts_dataset.rb +26 -0
  106. data/spec/datasets/reader_sites_dataset.rb +10 -0
  107. data/spec/datasets/readers_dataset.rb +51 -0
  108. data/spec/lib/reader_admin_ui_spec.rb +35 -0
  109. data/spec/lib/reader_site_spec.rb +18 -0
  110. data/spec/matchers/reader_login_system_matcher.rb +35 -0
  111. data/spec/models/message_spec.rb +109 -0
  112. data/spec/models/reader_notifier_spec.rb +34 -0
  113. data/spec/models/reader_spec.rb +155 -0
  114. data/spec/spec.opts +5 -0
  115. data/spec/spec_helper.rb +48 -0
  116. metadata +267 -0
@@ -0,0 +1,27 @@
1
+ class ReaderMessages < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :messages do |t|
4
+ t.column :site_id, :integer
5
+ t.column :subject, :string
6
+ t.column :body, :text
7
+ t.column :filter_id, :text
8
+ t.column :created_at, :datetime
9
+ t.column :updated_at, :datetime
10
+ t.column :created_by_id, :integer
11
+ t.column :updated_by_id, :integer
12
+ t.column :lock_version, :integer
13
+ end
14
+
15
+ create_table :message_readers do |t|
16
+ t.column :site_id, :integer
17
+ t.column :message_id, :integer
18
+ t.column :reader_id, :integer
19
+ t.column :sent_at, :datetime
20
+ end
21
+ end
22
+
23
+ def self.down
24
+ drop_table :messages
25
+ drop_table :message_readers
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ class FunctionalMessages < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :messages, :function, :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column :messages, :function
8
+ end
9
+ end
@@ -0,0 +1,106 @@
1
+ class StandardMessages < ActiveRecord::Migration
2
+ def self.up
3
+ Message.reset_column_information
4
+ messages = []
5
+
6
+ messages.push(Message.create(
7
+ :subject => 'Welcome!',
8
+ :function => 'welcome',
9
+ :filter_id => nil,
10
+ :body => %{
11
+ <p>Hello <r:recipient:name />.</p>
12
+
13
+ <p>Welcome to the <strong><a href="<r:site:url />"><r:site:name /></a></strong> site, and thank you for persevering with the registration process. Your account is now active and you will have been logged in automatically.</p>
14
+
15
+ <p>You can put in a bit more information about yourself at any time by visiting <a href="<r:recipient:edit_url />">your preferences page</a>.</p>
16
+
17
+ <p>Next time you visit, you will need to log in. Here's another reminder before we discard the plain text version of your password:</p>
18
+
19
+ <ul>
20
+ <li>username: <strong><r:recipient:login /></strong></li>
21
+ <li>password: <strong><r:recipient:password /></strong></li>
22
+ </ul>
23
+
24
+ <p>Best wishes,</p>
25
+
26
+ <p><r:sender:name /></p>
27
+ }
28
+ ))
29
+
30
+ messages.push(Message.create(
31
+ :subject => 'Please activate your account',
32
+ :function => 'activation',
33
+ :filter_id => nil,
34
+ :body => %{
35
+ <p>Hello <r:recipient:name />.</p>
36
+
37
+ <p>Welcome! Your account has been created at the <strong><r:site:name /></strong> site. To activate it, all you have to do is <strong><a href="<r:recipient:activation_url />">click on this link</a></strong>.</p>
38
+
39
+ <p>On this first visit you'll be logged in automatically, but next time you'll need to know your username and password:</p>
40
+
41
+ <ul>
42
+ <li>username: <strong><r:recipient:login /></strong></li>
43
+ <li>password: <strong><r:recipient:password /></strong></li>
44
+ </ul>
45
+
46
+ <p>To see yourself as others might see you, have a look at <a href="<r:recipient:url />">your page</a>. You can change that listing in your <a href="<r:recipient:edit_url />">preferences</a> and if you'd like a picture to appear, you need a <a href="http://www.gravatar.com/signup">gravatar</a>.</p>
47
+
48
+ <p>We're about to forget your password, so we won't be able to remind you what it is, but if you get stuck you can always make a new one by clicking on the 'forgot my password' link on the login page.</p>
49
+
50
+ <p>Best wishes,</p>
51
+
52
+ <p><r:sender:name /></p>
53
+ }
54
+ ))
55
+
56
+ messages.push(Message.create(
57
+ :subject => 'You are invited!',
58
+ :function => 'invitation',
59
+ :filter_id => nil,
60
+ :body => %{
61
+ <p>Hello <r:recipient:name />.</p>
62
+
63
+ <p>You are invited to join the <strong><r:site:name /></strong> site. To accept the invitation, all you have to do is <strong><a href="<r:recipient:activation_url />">click on this link</a></strong>.</p>
64
+
65
+ <p>On this first visit you'll be logged in automatically, but next time you'll need to know your username and password. Most of this has been generated automatically:</p>
66
+
67
+ <ul>
68
+ <li>username: <strong><r:recipient:login /></strong></li>
69
+ <li>password: <strong><r:recipient:password /></strong></li>
70
+ </ul>
71
+
72
+ So you will want to change it in your <a href="<r:recipient:edit_url />">preferences</a>, where you can also edit the text that will appear on your <a href="<r:recipient:url />">listing page</a> whenever someone follows a link from one of your contributions to the site.</p>
73
+
74
+ <p>Once you've logged in we'll forget your password, so we won't be able to remind you what it is. If you get stuck you can always make a new one by clicking on the 'forgot my password' link on the login page.</p>
75
+
76
+ <p>Best wishes,</p>
77
+
78
+ <p><r:sender:name /></p>
79
+ }
80
+ ))
81
+
82
+ messages.push(Message.create(
83
+ :subject => 'Reset your password',
84
+ :function => 'password_reset',
85
+ :filter_id => nil,
86
+ :body => %{
87
+ <p>Hello <r:recipient:name />.</p>
88
+
89
+ <p>Someone has requested that a new password be generated for your account at the <strong><a href="<r:site:url />"><r:site:name /></a></strong> site. If that person wasn't you, please don't be concerned: you are seeing this message, not they, and your password hasn't changed. You can safely delete this message and forget about it.</p>
90
+
91
+ <p>If that person was you, please <strong><a href="<r:recipient:repassword_url />">click here to enter a new password</a></strong>. Nothing will actually change until you submit the password-reset form.</p>
92
+
93
+ <p>If you have remembered your current password and all you want to do is change it, you can skip this step and go straight to your <a href="<r:recipient:edit_url />">preferences</a>.</p>
94
+ }
95
+ ))
96
+
97
+ if admin = User.find_by_admin(true)
98
+ messages.each do |message|
99
+ message.update_attribute(:created_by_id, admin.id)
100
+ end
101
+ end
102
+ end
103
+
104
+ def self.down
105
+ end
106
+ end
@@ -0,0 +1,9 @@
1
+ class MessageVisibility < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :messages, :status_id, :integer, :default => 1
4
+ end
5
+
6
+ def self.down
7
+ remove_column :messages, :status_id
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class RegistrationConfig < ActiveRecord::Migration
2
+ def self.up
3
+ if Radiant::Config['reader.allow_registration?'].nil?
4
+ Radiant::Config['reader.allow_registration?'] = true
5
+ end
6
+ end
7
+
8
+ def self.down
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ class MessageFunctions < ActiveRecord::Migration
2
+ def self.up
3
+ rename_column :messages, :function, :function_id
4
+ end
5
+
6
+ def self.down
7
+ rename_column :messages, :function_id, :function
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Forenames < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :readers, :forename, :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column :readers, :forename
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ class Contacts < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :readers, :phone, :string
4
+ add_column :readers, :organisation, :string
5
+ add_column :readers, :post_building, :string
6
+ add_column :readers, :post_street, :string
7
+ add_column :readers, :post_place, :string
8
+ add_column :readers, :post_town, :string
9
+ add_column :readers, :post_county, :string
10
+ add_column :readers, :postcode, :string
11
+ end
12
+
13
+ def self.down
14
+ remove_column :readers, :phone
15
+ remove_column :readers, :organisation
16
+ remove_column :readers, :post_building
17
+ remove_column :readers, :post_street
18
+ remove_column :readers, :post_place
19
+ remove_column :readers, :post_town
20
+ remove_column :readers, :post_county
21
+ remove_column :readers, :postcode
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ class EnsureFunctionalMessagesVisible < ActiveRecord::Migration
2
+ def self.up
3
+ Message.reset_column_information
4
+ Message.administrative.each {|m| m.update_attribute(:status_id, 100)}
5
+ end
6
+
7
+ def self.down
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class MessagesHaveLayout < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :messages, :layout_id, :integer
4
+ end
5
+
6
+ def self.down
7
+ remove_column :messages, :layout_id
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class LockVersions < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :readers, :lock_version, :integer, :default => 0
4
+ end
5
+
6
+ def self.down
7
+ remove_column :readers, :lock_version
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ class DefaultSettings < ActiveRecord::Migration
2
+ def self.up
3
+ Radiant::Config['reader.allow_registration?'] ||= true
4
+ Radiant::Config['reader.require_confirmation?'] ||= true
5
+ Radiant::Config['site.url'] ||= 'www.example.com'
6
+ Radiant::Config['site.title'] ||= 'Your site name here'
7
+ Radiant::Config['reader.mail_from_name'] ||= "Administrator"
8
+ Radiant::Config['reader.mail_from_address'] ||= "admin@example.com"
9
+ Radiant::Config['reader.layout'] ||= 'undefined'
10
+ end
11
+
12
+ def self.down
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ class UnlockVersion < ActiveRecord::Migration
2
+ def self.up
3
+ remove_column :readers, :lock_version
4
+ end
5
+
6
+ def self.down
7
+ add_column :readers, :lock_version, :integer, :default => 0
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module ConfigExtensions # for inclusion into Radiant::Config
2
+ def boolean?
3
+ key.ends_with? "?"
4
+ end
5
+ end
@@ -0,0 +1,77 @@
1
+ module ControllerExtensions # for inclusion into ApplicationController
2
+
3
+ def self.included(base)
4
+
5
+ base.class_eval do
6
+ before_filter :set_reader_for_user
7
+ before_filter :set_reader
8
+ helper_method :current_reader_session, :current_reader, :current_reader=
9
+ end
10
+
11
+ protected
12
+
13
+ def current_reader_session
14
+ return @current_reader_session if @current_reader_session.is_a?(ReaderSession)
15
+ @current_reader_session = ReaderSession.find
16
+ Reader.current = @current_reader_session.record if @current_reader_session
17
+ @current_reader_session
18
+ end
19
+
20
+ def current_reader_session=(reader_session)
21
+ @current_reader_session = reader_session
22
+ end
23
+
24
+ def current_reader
25
+ current_reader_session.record if current_reader_session
26
+ end
27
+
28
+ def current_reader=(reader)
29
+ if reader && reader.is_a?(Reader)
30
+ current_reader_session = ReaderSession.create!(reader)
31
+ else
32
+ current_reader_session.destroy
33
+ end
34
+ end
35
+
36
+ def set_reader_for_user
37
+ if current_user
38
+ current_reader_session = ReaderSession.create!(Reader.find_or_create_for_user(current_user))
39
+ end
40
+ end
41
+
42
+ def set_reader
43
+ Reader.current = current_reader
44
+ end
45
+
46
+ def store_location(location = request.request_uri)
47
+ session[:return_to] = location
48
+ end
49
+
50
+ def redirect_back_or_to(default)
51
+ redirect_to(session[:return_to] || default)
52
+ session[:return_to] = nil
53
+ end
54
+
55
+ def redirect_back_with_format(format = 'html')
56
+ address = session[:return_to]
57
+ raise StandardError, "Can't add format to an already formatted url: #{address}" unless File.extname(address).blank?
58
+ redirect_to address + ".#{format}" # nasty! but necessary for inline login.
59
+ end
60
+
61
+ def render_page_or_feed(template_name = action_name)
62
+ respond_to do |format|
63
+ format.html { render :action => template_name }
64
+ format.rss { render :action => template_name, :layout => 'feed' }
65
+ format.js { render :action => template_name, :layout => false }
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+
72
+
73
+
74
+
75
+
76
+
77
+
@@ -0,0 +1,64 @@
1
+ module ReaderAdminUI
2
+
3
+ def self.included(base)
4
+ base.class_eval do
5
+
6
+ attr_accessor :reader, :message, :reader_setting
7
+ alias_method :readers, :reader
8
+ alias_method :messages, :message
9
+ alias_method :reader_settings, :reader_setting
10
+
11
+ def load_reader_extension_regions
12
+ reader = load_default_reader_regions
13
+ message = load_default_message_regions
14
+ reader_setting = load_default_reader_setting_regions
15
+ end
16
+
17
+ def load_default_regions_with_reader
18
+ load_default_regions_without_reader
19
+ load_reader_extension_regions
20
+ end
21
+ alias_method_chain :load_default_regions, :reader
22
+
23
+ protected
24
+
25
+ def load_default_reader_regions
26
+ returning OpenStruct.new do |reader|
27
+ reader.edit = Radiant::AdminUI::RegionSet.new do |edit|
28
+ edit.main.concat %w{edit_header edit_form}
29
+ edit.form.concat %w{edit_name edit_email edit_username edit_password edit_description edit_notes}
30
+ edit.form_bottom.concat %w{edit_timestamp edit_buttons}
31
+ end
32
+ reader.index = Radiant::AdminUI::RegionSet.new do |index|
33
+ index.thead.concat %w{title_header description_header modify_header}
34
+ index.tbody.concat %w{title_cell description_cell modify_cell}
35
+ index.bottom.concat %w{buttons}
36
+ end
37
+ reader.remove = reader.index
38
+ reader.new = reader.edit
39
+ end
40
+ end
41
+
42
+ def load_default_reader_setting_regions
43
+ returning OpenStruct.new do |reader_settings|
44
+ reader_settings.index = Radiant::AdminUI::RegionSet.new do |index|
45
+ index.settings.concat %w{registration site sender}
46
+ index.messages.concat %w{administration}
47
+ end
48
+ end
49
+ end
50
+
51
+ def load_default_message_regions
52
+ returning OpenStruct.new do |message|
53
+ message.edit = Radiant::AdminUI::RegionSet.new do |edit|
54
+ edit.main.concat %w{edit_header edit_form edit_footer}
55
+ edit.form.concat %w{edit_subject edit_body}
56
+ edit.form_bottom.concat %w{edit_timestamp edit_buttons}
57
+ end
58
+ message.new = message.edit
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,36 @@
1
+ require 'sanitize'
2
+ module ReaderHelper
3
+ def self.included(base)
4
+
5
+ base.module_eval do
6
+
7
+ # wraps the block in a p with the right class and shows the errors nicely, if there are any
8
+
9
+ def with_error_report(errors, &block)
10
+ render({:layout => 'wrappers/field_errors', :locals => {:errors => errors}}, {}, &block)
11
+ end
12
+
13
+ def clean_textilize(text)
14
+ Sanitize.clean(textilize(text), Sanitize::Config::RELAXED)
15
+ end
16
+
17
+ def clean_textilize_without_paragraph(text)
18
+ textiled = clean_textilize(text)
19
+ if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
20
+ if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end
21
+ return textiled
22
+ end
23
+
24
+ def truncate_words(text='', length=64, omission="...")
25
+ return '' if text.blank?
26
+ words = text.split
27
+ omission = '' unless words.size > length
28
+ words[0..(length-1)].join(" ") + omission
29
+ end
30
+
31
+ def truncate_and_textilize(text, length=64)
32
+ clean_textilize( truncate_words(text, length) )
33
+ end
34
+ end
35
+ end
36
+ end