radiant-reader-extension 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ spec/spec_report.html
2
+ .DS_Store
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # Reader
2
+
3
+ This is a framework that takes care of all the dull bits of registering, activating, reminding, logging in and editing preferences for your site visitors.
4
+
5
+ It uses authlogic to handle sessions and provides complete interfaces both for the administrator and the visitor. The admin interface is basic and fits in with radiant. The visitor interface is more friendly (and incidentally includes a trick email field - so-called inverse captcha - that should prevent spam signups).
6
+
7
+ The visitors are referred to as 'readers' here. Readers never see the admin interface, but your site authors and admins are automatically given reader status.
8
+
9
+ The purpose of this extension is to provide a common core that supports other visitor-facing machinery. See for example our [forum extension](http://github.com/spanner/radiant-forum-extension) for discussions and page/blog comments, [reader groups](http://github.com/spanner/radiant-reader_group-extension) for proper page-access control and [downloads extension](http://github.com/spanner/radiant-downloads-extension) for secure access-controlled file downloads. More will follow and I hope other people will make use of this too.
10
+
11
+ ## Latest
12
+
13
+ * New configuration interface
14
+
15
+ * Provisionally updated for 0.9, but still being tweaked and tested: not definitely stable yet
16
+
17
+ * I'm about to start cleaning out the messaging interface. Some of its extra clutter will be moved into a newsletter extension so that here we can concentrate on making administrative messages easy to edit.
18
+
19
+ ## Status
20
+
21
+ Compatible with radiant 0.9 but currently undergoing some renovation.
22
+
23
+ Tests are thorough. A lot of our work relies on this extension.
24
+
25
+ ## Requirements
26
+
27
+ Radiant 0.8.1 (we need the new config machinery) or 0.9. [share_layouts](http://github.com/spanner/radiant-share-layouts-extension) (currently you need our version, which works with ActionMailer too). If you're on 0.8.1 you will probably want the [submenu](https://github.com/spanner/radiant-submenu-extension/tree) extension too.
28
+
29
+ You also need three gems (in addition to those that radiant requires): authlogic, gravtastic and sanitize. They're declared in the extension so you should be able just to run
30
+
31
+ sudo rake gems:install
32
+
33
+ Sanitize uses nokogiri, which needs libxml2 and libxslt: you may need to go off and install those first. You will also need to put
34
+
35
+ gem 'authlogic'
36
+
37
+ in your environment.rb before you can migrate anything. Authlogic has to load before anything else calls `require ApplicationController`.
38
+
39
+ ## Installation
40
+
41
+ git submodule add git://github.com/spanner/radiant-reader-extension.git vendor/extensions/reader
42
+ rake radiant:extensions:reader:migrate
43
+ rake radiant:extensions:reader:update
44
+
45
+ The update task will install a /stylesheets/admin/reader.css that you can leave alone and a /stylesheets/reader.css that you should call from your reader layout (see below) and will want to improve upon. There is also a very thin /javascripts/reader.js: all it does is fade notifications. The forum extension has a lot more javascripts for you to deplore.
46
+
47
+ ## Configuration
48
+
49
+ If you want to allow public registration, set `reader.allow_registration?` to true in your configuration. If it is false, then reader accounts can only be created by the administrator.
50
+
51
+ Under multi_site Reader adds a `reader_layout` column to the site table and a layout-chooser to the site-edit view. In a single-site installation you will also need these configuration entries:
52
+
53
+ * reader.layout (should be the name of a radiant layout)
54
+ * site.name
55
+ * site.url
56
+
57
+ The latter two are used in email notifications.
58
+
59
+ ## Layouts
60
+
61
+ We use the share_layouts extension to wrap the layout of your public site around the pages produced by the reader extension. You can designate any layout as the 'reader layout': in a single-site installation put the name of the layout in a `reader.layout` config entry. In a multi-site installation you'll find a 'reader layout' dropdown on the 'edit site' page. Choose the one you want to use for each site.
62
+
63
+ The layout of the layout is up to you: from our point of view all it has to do is call `<r:content />` at some point. Ideally it will call `<r:content part="pagetitle" />` too. There is also a `breadcrumbs` part if that's required. In many cases you can just use your existing site layout and the various forms and pages will drop into its usual compartments.
64
+
65
+ ## Using readers in other extensions
66
+
67
+ The reader admin pages are properly registered with the AdminUI as collections of parts, so you can override them in the same way as the other admin pages.
68
+
69
+ Most of your reader-facing controllers will want to inherit from `ReaderActionController`.
70
+
71
+ Marking a reader as untrusted does nothing here apart from making them go red, but we assume that in other extensions it will have some limiting effect.
72
+
73
+ ## See also
74
+
75
+ * [reader_group](http://github.com/spanner/radiant-reader_group-extension)
76
+ * [downloads](http://github.com/spanner/radiant-downloads-extension)
77
+ * [forum](http://github.com/spanner/radiant-forum-extension)
78
+ * [group_forum](http://github.com/spanner/radiant-group_forum-extension)
79
+
80
+ ## Bugs and comments
81
+
82
+ [Github issues](http://github.com/spanner/radiant-reader-extension/issues), please, or for little things an email or github message is fine.
83
+
84
+ ## Author and copyright
85
+
86
+ * Copyright spanner ltd 2007-9.
87
+ * Released under the same terms as Rails and/or Radiant.
88
+ * Contact will at spanner.org
89
+
data/Rakefile ADDED
@@ -0,0 +1,140 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "radiant-reader-extension"
5
+ gem.summary = %Q{User-services extension for Radiant CMS}
6
+ gem.description = %Q{Centralises reader/member/user registration and management tasks for the benefit of other extensions}
7
+ gem.email = "will@spanner.org"
8
+ gem.homepage = "http://github.com/spanner/radiant-reader-extension"
9
+ gem.authors = ["spanner"]
10
+ gem.add_dependency "radiant", ">= 0.9.0"
11
+ gem.add_dependency 'radiant-layouts-extension'
12
+ gem.add_dependency 'radiant-mailer_layouts-extension'
13
+ gem.add_dependency 'authlogic'
14
+ gem.add_dependency 'sanitize'
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. This is only required if you plan to package reader as a gem."
18
+ end
19
+
20
+ # In rails 1.2, plugins aren't available in the path until they're loaded.
21
+ # Check to see if the rspec plugin is installed first and require
22
+ # it if it is. If not, use the gem version.
23
+
24
+ # Determine where the RSpec plugin is by loading the boot
25
+ unless defined? RADIANT_ROOT
26
+ ENV["RAILS_ENV"] = "test"
27
+ case
28
+ when ENV["RADIANT_ENV_FILE"]
29
+ require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
30
+ when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
31
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
32
+ else
33
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
34
+ end
35
+ end
36
+
37
+ require 'rake'
38
+ require 'rake/rdoctask'
39
+ require 'rake/testtask'
40
+
41
+ rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
42
+ $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
43
+ require 'spec/rake/spectask'
44
+ require 'cucumber'
45
+ require 'cucumber/rake/task'
46
+
47
+ # Cleanup the RADIANT_ROOT constant so specs will load the environment
48
+ Object.send(:remove_const, :RADIANT_ROOT)
49
+
50
+ extension_root = File.expand_path(File.dirname(__FILE__))
51
+
52
+ task :default => :spec
53
+ task :stats => "spec:statsetup"
54
+
55
+ desc "Run all specs in spec directory"
56
+ Spec::Rake::SpecTask.new(:spec) do |t|
57
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
58
+ t.spec_files = FileList['spec/**/*_spec.rb']
59
+ end
60
+
61
+ task :features => 'spec:integration'
62
+
63
+ namespace :spec do
64
+ desc "Run all specs in spec directory with RCov"
65
+ Spec::Rake::SpecTask.new(:rcov) do |t|
66
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
67
+ t.spec_files = FileList['spec/**/*_spec.rb']
68
+ t.rcov = true
69
+ t.rcov_opts = ['--exclude', 'spec', '--rails']
70
+ end
71
+
72
+ desc "Print Specdoc for all specs"
73
+ Spec::Rake::SpecTask.new(:doc) do |t|
74
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
75
+ t.spec_files = FileList['spec/**/*_spec.rb']
76
+ end
77
+
78
+ [:models, :controllers, :views, :helpers].each do |sub|
79
+ desc "Run the specs under spec/#{sub}"
80
+ Spec::Rake::SpecTask.new(sub) do |t|
81
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
82
+ t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
83
+ end
84
+ end
85
+
86
+ desc "Run the Cucumber features"
87
+ Cucumber::Rake::Task.new(:integration) do |t|
88
+ t.fork = true
89
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
90
+ # t.feature_pattern = "#{extension_root}/features/**/*.feature"
91
+ t.profile = "default"
92
+ end
93
+
94
+ # Setup specs for stats
95
+ task :statsetup do
96
+ require 'code_statistics'
97
+ ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
98
+ ::STATS_DIRECTORIES << %w(View\ specs spec/views)
99
+ ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
100
+ ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
101
+ ::CodeStatistics::TEST_TYPES << "Model specs"
102
+ ::CodeStatistics::TEST_TYPES << "View specs"
103
+ ::CodeStatistics::TEST_TYPES << "Controller specs"
104
+ ::CodeStatistics::TEST_TYPES << "Helper specs"
105
+ ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
106
+ end
107
+
108
+ namespace :db do
109
+ namespace :fixtures do
110
+ desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
111
+ task :load => :environment do
112
+ require 'active_record/fixtures'
113
+ ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
114
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
115
+ Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ desc 'Generate documentation for the reader extension.'
123
+ Rake::RDocTask.new(:rdoc) do |rdoc|
124
+ rdoc.rdoc_dir = 'rdoc'
125
+ rdoc.title = 'ReaderExtension'
126
+ rdoc.options << '--line-numbers' << '--inline-source'
127
+ rdoc.rdoc_files.include('README')
128
+ rdoc.rdoc_files.include('lib/**/*.rb')
129
+ end
130
+
131
+ # For extensions that are in transition
132
+ desc 'Test the reader extension.'
133
+ Rake::TestTask.new(:test) do |t|
134
+ t.libs << 'lib'
135
+ t.pattern = 'test/**/*_test.rb'
136
+ t.verbose = true
137
+ end
138
+
139
+ # Load any custom rakefiles for extension
140
+ Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.9.2
@@ -0,0 +1,20 @@
1
+ class Admin::MessagesController < Admin::ResourceController
2
+ before_filter :set_function, :only => :new
3
+
4
+ def index
5
+ redirect_to admin_reader_settings_url
6
+ end
7
+
8
+ protected
9
+
10
+ def continue_url(options)
11
+ admin_reader_settings_url
12
+ end
13
+
14
+ def set_function
15
+ if params[:function]
16
+ @message.function_id = params[:function]
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,92 @@
1
+ class Admin::ReaderSettingsController < ApplicationController
2
+ only_allow_access_to :show, :edit, :update,
3
+ :when => [:admin],
4
+ :denied_url => { :controller => 'admin/reader_settings', :action => 'index' },
5
+ :denied_message => 'You must have admin privileges to edit reader settings.'
6
+
7
+ before_filter :default_settings
8
+ before_filter :get_setting, :only => [:show, :edit, :update]
9
+
10
+ cattr_accessor :settable
11
+ # this will need to be extensible
12
+ @@settable = {
13
+ 'reader.allow_registration?' => true,
14
+ 'reader.require_confirmation?' => true,
15
+ 'reader.layout' => 'unset',
16
+ 'site.title' => 'Site Title',
17
+ 'site.url' => 'Site URL',
18
+ 'reader.mail_from_name' => 'Sender',
19
+ 'reader.mail_from_address' => 'sender@example.com'
20
+ }
21
+
22
+ def self.make_settable(settings)
23
+ @@settable.merge! settings
24
+ end
25
+
26
+ def index
27
+
28
+ end
29
+
30
+ def show
31
+ respond_to do |format|
32
+ format.html { }
33
+ format.js { render :layout => false }
34
+ end
35
+ end
36
+
37
+ def edit
38
+ respond_to do |format|
39
+ format.html { }
40
+ format.js { render :layout => false }
41
+ end
42
+ end
43
+
44
+ def update
45
+ Rails.logger.warn "<< #{@setting.key} is #{@setting.value.inspect}"
46
+
47
+ value = params[:value] || params[:radiant_config][:value]
48
+
49
+ if @setting.boolean?
50
+ @setting.value = (value == 'false' ? false : true)
51
+ else
52
+ @setting.value = value
53
+ end
54
+
55
+ Rails.logger.warn ">> and now #{@setting.key} is #{@setting.value.inspect}"
56
+
57
+ @setting.save!
58
+ respond_to do |format|
59
+ format.html { render :action => 'show' }
60
+ format.js { render :layout => false, :action => 'show' }
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def settable?(key)
67
+ self.class.settable.keys.include?(key)
68
+ end
69
+
70
+ # temporarily while I do this properly in radiant
71
+
72
+ def default_settings
73
+ self.class.settable.each do |k, v|
74
+ Radiant::Config[k] = v if Radiant::Config[k].nil?
75
+ end
76
+ end
77
+
78
+ def get_setting
79
+ @setting = Radiant::Config.find(params[:id])
80
+ unless settable?(@setting.key)
81
+ respond_to do |format|
82
+ format.html {
83
+ flash['error'] = "Not settable"
84
+ redirect_to :action => 'index'
85
+ }
86
+ format.js { render :status => 403, :text => 'Not settable' }
87
+ end
88
+ return false
89
+ end
90
+ end
91
+
92
+ end
@@ -0,0 +1,28 @@
1
+ class Admin::ReadersController < Admin::ResourceController
2
+ paginate_models
3
+ before_filter :redirect_to_user, :only => :edit
4
+
5
+ only_allow_access_to :new, :create, :edit, :update, :remove, :destroy, :settings,
6
+ :when => :admin,
7
+ :denied_url => { :controller => 'pages', :action => 'index' },
8
+ :denied_message => 'You must be an administrator to add or modify readers'
9
+
10
+ def create
11
+ model.update_attributes!(params[:reader])
12
+ model.clear_password = params[:reader][:password] if params[:reader] && params[:reader][:password] # condition is so that radiant tests pass
13
+ model.send_invitation_message
14
+ announce_saved
15
+ response_for :create
16
+ end
17
+
18
+ private
19
+
20
+ def redirect_to_user
21
+ if model.is_user?
22
+ redirect_to edit_admin_user_url(model.user)
23
+ return false
24
+ end
25
+ true
26
+ end
27
+
28
+ end
@@ -0,0 +1,64 @@
1
+ class PasswordResetsController < ApplicationController
2
+
3
+ # rest gone mad! but it works, and keeps the processes well-defined.
4
+
5
+ no_login_required
6
+ before_filter :get_reader, :only => [:edit, :update]
7
+ radiant_layout { |controller| Radiant::Config['reader.layout'] }
8
+
9
+ def new
10
+ render
11
+ end
12
+
13
+ def create
14
+ @reader = Reader.find_by_email(params[:email])
15
+ if @reader
16
+ if @reader.activated?
17
+ @reader.send_password_reset_message
18
+ flash[:notice] = "Password reset instructions have been emailed to you."
19
+ render
20
+ else
21
+ @reader.send_activation_message
22
+ flash[:notice] = "Account activation instructions have been emailed to you."
23
+ redirect_to new_reader_activation_url
24
+ end
25
+ else
26
+ @error = flash[:error] = "Sorry. That email address is not known here."
27
+ render :action => :new
28
+ end
29
+ end
30
+
31
+ def edit
32
+ if @reader
33
+ flash[:notice] = "Thank you. Please enter and confirm a new password."
34
+ else
35
+ flash[:error] = "Sorry: can't find you."
36
+ end
37
+ render
38
+ end
39
+
40
+ def update
41
+ if @reader
42
+ @reader.password = params[:reader][:password]
43
+ @reader.password_confirmation = params[:reader][:password_confirmation]
44
+ if @reader.save
45
+ self.current_reader = @reader
46
+ flash[:notice] = "Thank you. Your password has been updated and you are now logged in."
47
+ redirect_to url_for(@reader)
48
+ else
49
+ flash[:error] = "Passwords don't match! Please try again."
50
+ render :action => :edit
51
+ end
52
+ else
53
+ flash[:error] = "Sorry: can't find you."
54
+ render :action => :edit # without @reader, this will take us back to the enter-your-code form
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def get_reader
61
+ @reader = Reader.find_by_id_and_perishable_token(params[:id], params[:confirmation_code])
62
+ end
63
+
64
+ end