Commit e4d58d00eb943e89199ae20b47dde2b173d186c9

merge with remote files
  
11ActionController::Routing::Routes.draw do |map|
2<<<<<<< HEAD:config/routes.rb
3 map.resources :users
4=======
2 map.resources :users, :as => 'usuarios'
3
54 map.resources :scheduled_debts, :as => 'debitos_agendados' do |sd|
65 sd.resources :realizations, :as => 'confirmacoes' do |r|
76 r.resource :movement, :as => 'movimento'
1616 r.resource :movement, :as => 'movimento'
1717 end
1818 end
19>>>>>>> 9234dba8671ed1874ebc3a25e1677963cf81621b:config/routes.rb
19 map.resource :session, :as => 'sessoes'
2020
21<<<<<<< HEAD:config/routes.rb
22 map.resource :session
23
24 map.resources :scheduled_debts
25 map.resources :realizations
26 map.resources :scheduled_profits
27 map.resources :movements
28=======
2921 map.resources :movements, :as => 'movimentos' do |m|
3022 m.resource :realization, :as => 'confirmacao'
3123 end
32>>>>>>> 9234dba8671ed1874ebc3a25e1677963cf81621b:config/routes.rb
3324
3425 # The priority is based upon order of creation: first created -> highest priority.
3526
  
1require 'rake'
2require 'rake/testtask'
3require 'rake/rdoctask'
4
5desc 'Default: run unit tests.'
6task :default => :test
7
8desc 'Test the restful_authentication plugin.'
9Rake::TestTask.new(:test) do |t|
10 t.libs << 'lib'
11 t.pattern = 'test/**/*_test.rb'
12 t.verbose = true
13end
14
15desc 'Generate documentation for the restful_authentication plugin.'
16Rake::RDocTask.new(:rdoc) do |rdoc|
17 rdoc.rdoc_dir = 'rdoc'
18 rdoc.title = 'RestfulAuthentication'
19 rdoc.options << '--line-numbers' << '--inline-source'
20 rdoc.rdoc_files.include('README')
21 rdoc.rdoc_files.include('lib/**/*.rb')
22end
  
1./script/generate authenticated USERMODEL CONTROLLERNAME
  
1require 'restful_authentication/rails_commands'
2class AuthenticatedGenerator < Rails::Generator::NamedBase
3 default_options :skip_migration => false,
4 :include_activation => false
5
6 attr_reader :controller_name,
7 :controller_class_path,
8 :controller_file_path,
9 :controller_class_nesting,
10 :controller_class_nesting_depth,
11 :controller_class_name,
12 :controller_singular_name,
13 :controller_plural_name,
14 :controller_file_name
15 alias_method :controller_table_name, :controller_plural_name
16 attr_reader :model_controller_name,
17 :model_controller_class_path,
18 :model_controller_file_path,
19 :model_controller_class_nesting,
20 :model_controller_class_nesting_depth,
21 :model_controller_class_name,
22 :model_controller_singular_name,
23 :model_controller_plural_name
24 alias_method :model_controller_file_name, :model_controller_singular_name
25 alias_method :model_controller_table_name, :model_controller_plural_name
26
27 def initialize(runtime_args, runtime_options = {})
28 super
29
30 @rspec = has_rspec?
31
32 @controller_name = args.shift || 'sessions'
33 @model_controller_name = @name.pluralize
34
35 # sessions controller
36 base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
37 @controller_class_name_without_nesting, @controller_file_name, @controller_plural_name = inflect_names(base_name)
38 @controller_singular_name = @controller_file_name.singularize
39
40 if @controller_class_nesting.empty?
41 @controller_class_name = @controller_class_name_without_nesting
42 else
43 @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
44 end
45
46 # model controller
47 base_name, @model_controller_class_path, @model_controller_file_path, @model_controller_class_nesting, @model_controller_class_nesting_depth = extract_modules(@model_controller_name)
48 @model_controller_class_name_without_nesting, @model_controller_singular_name, @model_controller_plural_name = inflect_names(base_name)
49
50 if @model_controller_class_nesting.empty?
51 @model_controller_class_name = @model_controller_class_name_without_nesting
52 else
53 @model_controller_class_name = "#{@model_controller_class_nesting}::#{@model_controller_class_name_without_nesting}"
54 end
55 end
56
57 def manifest
58 recorded_session = record do |m|
59 # Check for class naming collisions.
60 m.class_collisions controller_class_path, "#{controller_class_name}Controller", # Sessions Controller
61 "#{controller_class_name}Helper"
62 m.class_collisions model_controller_class_path, "#{model_controller_class_name}Controller", # Model Controller
63 "#{model_controller_class_name}Helper"
64 m.class_collisions class_path, "#{class_name}", "#{class_name}Mailer", "#{class_name}MailerTest", "#{class_name}Observer"
65 m.class_collisions [], 'AuthenticatedSystem', 'AuthenticatedTestHelper'
66
67 # Controller, helper, views, and test directories.
68 m.directory File.join('app/models', class_path)
69 m.directory File.join('app/controllers', controller_class_path)
70 m.directory File.join('app/controllers', model_controller_class_path)
71 m.directory File.join('app/helpers', controller_class_path)
72 m.directory File.join('app/views', controller_class_path, controller_file_name)
73 m.directory File.join('app/views', class_path, "#{file_name}_mailer") if options[:include_activation]
74
75 m.directory File.join('app/controllers', model_controller_class_path)
76 m.directory File.join('app/helpers', model_controller_class_path)
77 m.directory File.join('app/views', model_controller_class_path, model_controller_file_name)
78
79 if @rspec
80 m.directory File.join('spec/controllers', controller_class_path)
81 m.directory File.join('spec/controllers', model_controller_class_path)
82 m.directory File.join('spec/models', class_path)
83 m.directory File.join('spec/fixtures', class_path)
84 else
85 m.directory File.join('test/functional', controller_class_path)
86 m.directory File.join('test/functional', model_controller_class_path)
87 m.directory File.join('test/unit', class_path)
88 end
89
90 m.template 'model.rb',
91 File.join('app/models',
92 class_path,
93 "#{file_name}.rb")
94
95 if options[:include_activation]
96 %w( mailer observer ).each do |model_type|
97 m.template "#{model_type}.rb", File.join('app/models',
98 class_path,
99 "#{file_name}_#{model_type}.rb")
100 end
101 end
102
103 m.template 'controller.rb',
104 File.join('app/controllers',
105 controller_class_path,
106 "#{controller_file_name}_controller.rb")
107
108 m.template 'model_controller.rb',
109 File.join('app/controllers',
110 model_controller_class_path,
111 "#{model_controller_file_name}_controller.rb")
112
113 m.template 'authenticated_system.rb',
114 File.join('lib', 'authenticated_system.rb')
115
116 m.template 'authenticated_test_helper.rb',
117 File.join('lib', 'authenticated_test_helper.rb')
118
119 if @rspec
120 m.template 'functional_spec.rb',
121 File.join('spec/controllers',
122 controller_class_path,
123 "#{controller_file_name}_controller_spec.rb")
124 m.template 'model_functional_spec.rb',
125 File.join('spec/controllers',
126 model_controller_class_path,
127 "#{model_controller_file_name}_controller_spec.rb")
128 m.template 'unit_spec.rb',
129 File.join('spec/models',
130 class_path,
131 "#{file_name}_spec.rb")
132 m.template 'fixtures.yml',
133 File.join('spec/fixtures',
134 "#{table_name}.yml")
135 else
136 m.template 'functional_test.rb',
137 File.join('test/functional',
138 controller_class_path,
139 "#{controller_file_name}_controller_test.rb")
140 m.template 'model_functional_test.rb',
141 File.join('test/functional',
142 model_controller_class_path,
143 "#{model_controller_file_name}_controller_test.rb")
144 m.template 'unit_test.rb',
145 File.join('test/unit',
146 class_path,
147 "#{file_name}_test.rb")
148 if options[:include_activation]
149 m.template 'mailer_test.rb', File.join('test/unit', class_path, "#{file_name}_mailer_test.rb")
150 end
151 m.template 'fixtures.yml',
152 File.join('test/fixtures',
153 "#{table_name}.yml")
154 end
155
156 m.template 'helper.rb',
157 File.join('app/helpers',
158 controller_class_path,
159 "#{controller_file_name}_helper.rb")
160
161 m.template 'model_helper.rb',
162 File.join('app/helpers',
163 model_controller_class_path,
164 "#{model_controller_file_name}_helper.rb")
165
166
167 # Controller templates
168 m.template 'login.html.erb', File.join('app/views', controller_class_path, controller_file_name, "new.html.erb")
169 m.template 'signup.html.erb', File.join('app/views', model_controller_class_path, model_controller_file_name, "new.html.erb")
170
171 if options[:include_activation]
172 # Mailer templates
173 %w( activation signup_notification ).each do |action|
174 m.template "#{action}.html.erb",
175 File.join('app/views', "#{file_name}_mailer", "#{action}.html.erb")
176 end
177 end
178
179 unless options[:skip_migration]
180 m.migration_template 'migration.rb', 'db/migrate', :assigns => {
181 :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
182 }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
183 end
184
185 m.route_resource controller_singular_name
186 m.route_resources model_controller_plural_name
187 end
188
189 action = nil
190 action = $0.split("/")[1]
191 case action
192 when "generate"
193 puts
194 puts ("-" * 70)
195 puts "Don't forget to:"
196 puts
197 if options[:include_activation]
198 puts " map.activate '/activate/:activation_code', :controller => '#{model_controller_file_name}', :action => 'activate'"
199 puts
200 puts " - add an observer to config/environment.rb"
201 puts " config.active_record.observers = :#{file_name}_observer"
202 puts
203 end
204 if options[:stateful]
205 puts "Also, don't forget to install the acts_as_state_machine plugin and set your resource:"
206 puts
207 puts " svn co http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk vendor/plugins/acts_as_state_machine"
208 puts
209 puts %w(map.resources :#{model_controller_file_name}, :member => { :suspend => :put, :unsuspend => :put, :purge => :delete })
210 puts
211 end
212 puts "Try these for some familiar login URLs if you like:"
213 puts
214 puts %(map.activate '/activate/:activation_code', :controller => '#{model_controller_file_name}', :action => 'activate', :activation_code => nil)
215 puts %(map.signup '/signup', :controller => '#{model_controller_file_name}', :action => 'new')
216 puts %(map.login '/login', :controller => '#{controller_file_name}', :action => 'new')
217 puts %(map.logout '/logout', :controller => '#{controller_file_name}', :action => 'destroy')
218 puts
219 puts ("-" * 70)
220 puts
221 when "destroy"
222 puts
223 puts ("-" * 70)
224 puts
225 puts "Thanks for using restful_authentication"
226 puts
227 puts "Don't forget to comment out the observer line in environment.rb"
228 puts " (This was optional so it may not even be there)"
229 puts " # config.active_record.observers = :#{file_name}_observer"
230 puts
231 puts ("-" * 70)
232 puts
233 else
234 puts
235 end
236
237 recorded_session
238 end
239
240 def has_rspec?
241 options[:rspec] || (File.exist?('spec') && File.directory?('spec'))
242 end
243
244 protected
245 # Override with your own usage banner.
246 def banner
247 "Usage: #{$0} authenticated ModelName [ControllerName]"
248 end
249
250 def add_options!(opt)
251 opt.separator ''
252 opt.separator 'Options:'
253 opt.on("--skip-migration",
254 "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
255 opt.on("--include-activation",
256 "Generate signup 'activation code' confirmation via email") { |v| options[:include_activation] = true }
257 opt.on("--stateful",
258 "Use acts_as_state_machine. Assumes --include-activation") { |v| options[:include_activation] = options[:stateful] = true }
259 opt.on("--rspec",
260 "Force rspec mode (checks for RAILS_ROOT/spec by default)") { |v| options[:rspec] = true }
261 end
262end
  
1<%%= @<%= file_name %>.login %>, your account has been activated. You may now start adding your plugins:
2
3 <%%= @url %>
  
1module AuthenticatedSystem
2 protected
3 # Returns true or false if the <%= file_name %> is logged in.
4 # Preloads @current_<%= file_name %> with the <%= file_name %> model if they're logged in.
5 def logged_in?
6 current_<%= file_name %> != :false
7 end
8
9 # Accesses the current <%= file_name %> from the session. Set it to :false if login fails
10 # so that future calls do not hit the database.
11 def current_<%= file_name %>
12 @current_<%= file_name %> ||= (login_from_session || login_from_basic_auth || login_from_cookie || :false)
13 end
14
15 # Store the given <%= file_name %> id in the session.
16 def current_<%= file_name %>=(new_<%= file_name %>)
17 session[:<%= file_name %>_id] = (new_<%= file_name %>.nil? || new_<%= file_name %>.is_a?(Symbol)) ? nil : new_<%= file_name %>.id
18 @current_<%= file_name %> = new_<%= file_name %> || :false
19 end
20
21 # Check if the <%= file_name %> is authorized
22 #
23 # Override this method in your controllers if you want to restrict access
24 # to only a few actions or if you want to check if the <%= file_name %>
25 # has the correct rights.
26 #
27 # Example:
28 #
29 # # only allow nonbobs
30 # def authorized?
31 # current_<%= file_name %>.login != "bob"
32 # end
33 def authorized?
34 logged_in?
35 end
36
37 # Filter method to enforce a login requirement.
38 #
39 # To require logins for all actions, use this in your controllers:
40 #
41 # before_filter :login_required
42 #
43 # To require logins for specific actions, use this in your controllers:
44 #
45 # before_filter :login_required, :only => [ :edit, :update ]
46 #
47 # To skip this in a subclassed controller:
48 #
49 # skip_before_filter :login_required
50 #
51 def login_required
52 authorized? || access_denied
53 end
54
55 # Redirect as appropriate when an access request fails.
56 #
57 # The default action is to redirect to the login screen.
58 #
59 # Override this method in your controllers if you want to have special
60 # behavior in case the <%= file_name %> is not authorized
61 # to access the requested action. For example, a popup window might
62 # simply close itself.
63 def access_denied
64 respond_to do |format|
65 format.html do
66 store_location
67 redirect_to new_<%= controller_singular_name %>_path
68 end
69 format.any do
70 request_http_basic_authentication 'Web Password'
71 end
72 end
73 end
74
75 # Store the URI of the current request in the session.
76 #
77 # We can return to this location by calling #redirect_back_or_default.
78 def store_location
79 session[:return_to] = request.request_uri
80 end
81
82 # Redirect to the URI stored by the most recent store_location call or
83 # to the passed default.
84 def redirect_back_or_default(default)
85 redirect_to(session[:return_to] || default)
86 session[:return_to] = nil
87 end
88
89 # Inclusion hook to make #current_<%= file_name %> and #logged_in?
90 # available as ActionView helper methods.
91 def self.included(base)
92 base.send :helper_method, :current_<%= file_name %>, :logged_in?
93 end
94
95 # Called from #current_<%= file_name %>. First attempt to login by the <%= file_name %> id stored in the session.
96 def login_from_session
97 self.current_<%= file_name %> = <%= class_name %>.find(session[:<%= file_name %>_id]) if session[:<%= file_name %>_id]
98 end
99
100 # Called from #current_<%= file_name %>. Now, attempt to login by basic authentication information.
101 def login_from_basic_auth
102 authenticate_with_http_basic do |username, password|
103 self.current_<%= file_name %> = <%= class_name %>.authenticate(username, password)
104 end
105 end
106
107 # Called from #current_<%= file_name %>. Finaly, attempt to login by an expiring token in the cookie.
108 def login_from_cookie
109 <%= file_name %> = cookies[:auth_token] && <%= class_name %>.find_by_remember_token(cookies[:auth_token])
110 if <%= file_name %> && <%= file_name %>.remember_token?
111 <%= file_name %>.remember_me
112 cookies[:auth_token] = { :value => <%= file_name %>.remember_token, :expires => <%= file_name %>.remember_token_expires_at }
113 self.current_<%= file_name %> = <%= file_name %>
114 end
115 end
116end
  
1module AuthenticatedTestHelper
2 # Sets the current <%= file_name %> in the session from the <%= file_name %> fixtures.
3 def login_as(<%= file_name %>)
4 @request.session[:<%= file_name %>_id] = <%= file_name %> ? <%= table_name %>(<%= file_name %>).id : nil
5 end
6
7 def authorize_as(user)
8 @request.env["HTTP_AUTHORIZATION"] = user ? ActionController::HttpAuthentication::Basic.encode_credentials(users(user).login, 'test') : nil
9 end
10end
  
1# This controller handles the login/logout function of the site.
2class <%= controller_class_name %>Controller < ApplicationController
3 # Be sure to include AuthenticationSystem in Application Controller instead
4 include AuthenticatedSystem
5
6 # render new.rhtml
7 def new
8 end
9
10 def create
11 self.current_<%= file_name %> = <%= class_name %>.authenticate(params[:login], params[:password])
12 if logged_in?
13 if params[:remember_me] == "1"
14 self.current_<%= file_name %>.remember_me
15 cookies[:auth_token] = { :value => self.current_<%= file_name %>.remember_token , :expires => self.current_<%= file_name %>.remember_token_expires_at }
16 end
17 redirect_back_or_default('/')
18 flash[:notice] = "Logged in successfully"
19 else
20 render :action => 'new'
21 end
22 end
23
24 def destroy
25 self.current_<%= file_name %>.forget_me if logged_in?
26 cookies.delete :auth_token
27 reset_session
28 flash[:notice] = "You have been logged out."
29 redirect_back_or_default('/')
30 end
31end
  
1quentin:
2 id: 1
3 login: quentin
4 email: quentin@example.com
5 salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
6 crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
7 created_at: <%%= 5.days.ago.to_s :db %>
8<% if options[:include_activation] %> activation_code: 8f24789ae988411ccf33ab0c30fe9106fab32e9b <% end %>
9<% if options[:include_activation] %> activated_at: <%%= 5.days.ago.to_s :db %> <% end %>
10<% if options[:stateful] %> state: active<% end %>
11aaron:
12 id: 2
13 login: aaron
14 email: aaron@example.com
15 salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
16 crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
17 created_at: <%%= 1.days.ago.to_s :db %>
18<% if options[:include_activation] %> activation_code: 8f24789ae988411ccf33ab0c30fe9106fab32e9a <% end %>
19<% if options[:stateful] %> state: pending<% end %>
  
1require File.dirname(__FILE__) + '/../spec_helper'
2
3# Be sure to include AuthenticatedTestHelper in spec/spec_helper.rb instead
4# Then, you can remove it from this and the units test.
5include AuthenticatedTestHelper
6
7describe <%= controller_class_name %>Controller do
8 fixtures :<%= table_name %>
9
10 it 'logins and redirects' do
11 post :create, :login => 'quentin', :password => 'test'
12 session[:<%= file_name %>_id].should_not be_nil
13 response.should be_redirect
14 end
15
16 it 'fails login and does not redirect' do
17 post :create, :login => 'quentin', :password => 'bad password'
18 session[:<%= file_name %>_id].should be_nil
19 response.should be_success
20 end
21
22 it 'logs out' do
23 login_as :quentin
24 get :destroy
25 session[:<%= file_name %>_id].should be_nil
26 response.should be_redirect
27 end
28
29 it 'remembers me' do
30 post :create, :login => 'quentin', :password => 'test', :remember_me => "1"
31 response.cookies["auth_token"].should_not be_nil
32 end
33
34 it 'does not remember me' do
35 post :create, :login => 'quentin', :password => 'test', :remember_me => "0"
36 response.cookies["auth_token"].should be_nil
37 end
38
39 it 'deletes token on logout' do
40 login_as :quentin
41 get :destroy
42 response.cookies["auth_token"].should == []
43 end
44
45 it 'logs in with cookie' do
46 <%= table_name %>(:quentin).remember_me
47 request.cookies["auth_token"] = cookie_for(:quentin)
48 get :new
49 controller.send(:logged_in?).should be_true
50 end
51
52 it 'fails expired cookie login' do
53 <%= table_name %>(:quentin).remember_me
54 <%= table_name %>(:quentin).update_attribute :remember_token_expires_at, 5.minutes.ago
55 request.cookies["auth_token"] = cookie_for(:quentin)
56 get :new
57 controller.send(:logged_in?).should_not be_true
58 end
59
60 it 'fails cookie login' do
61 <%= table_name %>(:quentin).remember_me
62 request.cookies["auth_token"] = auth_token('invalid_auth_token')
63 get :new
64 controller.send(:logged_in?).should_not be_true
65 end
66
67 def auth_token(token)
68 CGI::Cookie.new('name' => 'auth_token', 'value' => token)
69 end
70
71 def cookie_for(<%= file_name %>)
72 auth_token <%= table_name %>(<%= file_name %>).remember_token
73 end
74end
  
1require File.dirname(__FILE__) + '/../test_helper'
2require '<%= controller_file_name %>_controller'
3
4# Re-raise errors caught by the controller.
5class <%= controller_class_name %>Controller; def rescue_action(e) raise e end; end
6
7class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase
8 # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9 # Then, you can remove it from this and the units test.
10 include AuthenticatedTestHelper
11
12 fixtures :<%= table_name %>
13
14 def setup
15 @controller = <%= controller_class_name %>Controller.new
16 @request = ActionController::TestRequest.new
17 @response = ActionController::TestResponse.new
18 end
19
20 def test_should_login_and_redirect
21 post :create, :login => 'quentin', :password => 'test'
22 assert session[:<%= file_name %>_id]
23 assert_response :redirect
24 end
25
26 def test_should_fail_login_and_not_redirect
27 post :create, :login => 'quentin', :password => 'bad password'
28 assert_nil session[:<%= file_name %>_id]
29 assert_response :success
30 end
31
32 def test_should_logout
33 login_as :quentin
34 get :destroy
35 assert_nil session[:<%= file_name %>_id]
36 assert_response :redirect
37 end
38
39 def test_should_remember_me
40 post :create, :login => 'quentin', :password => 'test', :remember_me => "1"
41 assert_not_nil @response.cookies["auth_token"]
42 end
43
44 def test_should_not_remember_me
45 post :create, :login => 'quentin', :password => 'test', :remember_me => "0"
46 assert_nil @response.cookies["auth_token"]
47 end
48
49 def test_should_delete_token_on_logout
50 login_as :quentin
51 get :destroy
52 assert_equal @response.cookies["auth_token"], []
53 end
54
55 def test_should_login_with_cookie
56 <%= table_name %>(:quentin).remember_me
57 @request.cookies["auth_token"] = cookie_for(:quentin)
58 get :new
59 assert @controller.send(:logged_in?)
60 end
61
62 def test_should_fail_expired_cookie_login
63 <%= table_name %>(:quentin).remember_me
64 <%= table_name %>(:quentin).update_attribute :remember_token_expires_at, 5.minutes.ago
65 @request.cookies["auth_token"] = cookie_for(:quentin)
66 get :new
67 assert !@controller.send(:logged_in?)
68 end
69
70 def test_should_fail_cookie_login
71 <%= table_name %>(:quentin).remember_me
72 @request.cookies["auth_token"] = auth_token('invalid_auth_token')
73 get :new
74 assert !@controller.send(:logged_in?)
75 end
76
77 protected
78 def auth_token(token)
79 CGI::Cookie.new('name' => 'auth_token', 'value' => token)
80 end
81
82 def cookie_for(<%= file_name %>)
83 auth_token <%= table_name %>(<%= file_name %>).remember_token
84 end
85end
  
1module <%= controller_class_name %>Helper
2end
  
1<%% form_tag <%= controller_singular_name %>_path do -%>
2<p><label for="login">Login</label><br/>
3<%%= text_field_tag 'login' %></p>
4
5<p><label for="password">Password</label><br/>
6<%%= password_field_tag 'password' %></p>
7
8<!-- Uncomment this if you want this functionality
9<p><label for="remember_me">Remember me:</label>
10<%%= check_box_tag 'remember_me' %></p>
11-->
12
13<p><%%= submit_tag 'Log in' %></p>
14<%% end -%>
  
1class <%= class_name %>Mailer < ActionMailer::Base
2 def signup_notification(<%= file_name %>)
3 setup_email(<%= file_name %>)
4 @subject += 'Please activate your new account'
5 <% if options[:include_activation] %>
6 @body[:url] = "http://YOURSITE/activate/#{<%= file_name %>.activation_code}"
7 <% else %>
8 @body[:url] = "http://YOURSITE/login/" <% end %>
9 end
10
11 def activation(<%= file_name %>)
12 setup_email(<%= file_name %>)
13 @subject += 'Your account has been activated!'
14 @body[:url] = "http://YOURSITE/"
15 end
16
17 protected
18 def setup_email(<%= file_name %>)
19 @recipients = "#{<%= file_name %>.email}"
20 @from = "ADMINEMAIL"
21 @subject = "[YOURSITE] "
22 @sent_on = Time.now
23 @body[:<%= file_name %>] = <%= file_name %>
24 end
25end
  
1require File.dirname(__FILE__) + '/../test_helper'
2require '<%= file_name %>_mailer'
3
4class <%= class_name %>MailerTest < Test::Unit::TestCase
5 FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
6 CHARSET = "utf-8"
7
8 include ActionMailer::Quoting
9
10 def setup
11 ActionMailer::Base.delivery_method = :test
12 ActionMailer::Base.perform_deliveries = true
13 ActionMailer::Base.deliveries = []
14
15 @expected = TMail::Mail.new
16 @expected.set_content_type "text", "plain", { "charset" => CHARSET }
17 end
18
19 def test_dummy_test
20 #do nothing
21 end
22
23 private
24 def read_fixture(action)
25 IO.readlines("#{FIXTURES_PATH}/<%= file_name %>_mailer/#{action}")
26 end
27
28 def encode(subject)
29 quoted_printable(subject, CHARSET)
30 end
31end
  
1class <%= migration_name %> < ActiveRecord::Migration
2 def self.up
3 create_table "<%= table_name %>", :force => true do |t|
4 t.column :login, :string
5 t.column :email, :string
6 t.column :crypted_password, :string, :limit => 40
7 t.column :salt, :string, :limit => 40
8 t.column :created_at, :datetime
9 t.column :updated_at, :datetime
10 t.column :remember_token, :string
11 t.column :remember_token_expires_at, :datetime
12 <% if options[:include_activation] %>t.column :activation_code, :string, :limit => 40
13 t.column :activated_at, :datetime<% end %>
14 <% if options[:stateful] %>t.column :state, :string, :null => :no, :default => 'passive'
15 t.column :deleted_at, :datetime<% end %>
16 end
17 end
18
19 def self.down
20 drop_table "<%= table_name %>"
21 end
22end
  
1require 'digest/sha1'
2class <%= class_name %> < ActiveRecord::Base
3 # Virtual attribute for the unencrypted password
4 attr_accessor :password
5
6 validates_presence_of :login, :email
7 validates_presence_of :password, :if => :password_required?
8 validates_presence_of :password_confirmation, :if => :password_required?
9 validates_length_of :password, :within => 4..40, :if => :password_required?
10 validates_confirmation_of :password, :if => :password_required?
11 validates_length_of :login, :within => 3..40
12 validates_length_of :email, :within => 3..100
13 validates_uniqueness_of :login, :email, :case_sensitive => false
14 before_save :encrypt_password
15 <% if options[:include_activation] && !options[:stateful] %>before_create :make_activation_code <% end %>
16 # prevents a user from submitting a crafted form that bypasses activation
17 # anything else you want your user to change should be added here.
18 attr_accessible :login, :email, :password, :password_confirmation
19<% if options[:stateful] %>
20 acts_as_state_machine :initial => :pending
21 state :passive
22 state :pending, :enter => :make_activation_code
23 state :active, :enter => :do_activate
24 state :suspended
25 state :deleted, :enter => :do_delete
26
27 event :register do
28 transitions :from => :passive, :to => :pending, :guard => Proc.new {|u| !(u.crypted_password.blank? && u.password.blank?) }
29 end
30
31 event :activate do
32 transitions :from => :pending, :to => :active
33 end
34
35 event :suspend do
36 transitions :from => [:passive, :pending, :active], :to => :suspended
37 end
38
39 event :delete do
40 transitions :from => [:passive, :pending, :active, :suspended], :to => :deleted
41 end
42
43 event :unsuspend do
44 transitions :from => :suspended, :to => :active, :guard => Proc.new {|u| !u.activated_at.blank? }
45 transitions :from => :suspended, :to => :pending, :guard => Proc.new {|u| !u.activation_code.blank? }
46 transitions :from => :suspended, :to => :passive
47 end
48<% elsif options[:include_activation] %>
49 # Activates the user in the database.
50 def activate
51 @activated = true
52 self.activated_at = Time.now.utc
53 self.activation_code = nil
54 save(false)
55 end
56
57 def active?
58 # the existence of an activation code means they have not activated yet
59 activation_code.nil?
60 end
61
62 # Returns true if the user has just been activated.
63 def pending?
64 @activated
65 end
66<% end %>
67 # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
68 def self.authenticate(login, password)
69 u = <%
70 if options[:stateful] %>find_in_state :first, :active, :conditions => {:login => login}<%
71 elsif options[:include_activation] %>find :first, :conditions => ['login = ? and activated_at IS NOT NULL', login]<%
72 else %>find_by_login(login)<%
73 end %> # need to get the salt
74 u && u.authenticated?(password) ? u : nil
75 end
76
77 # Encrypts some data with the salt.
78 def self.encrypt(password, salt)
79 Digest::SHA1.hexdigest("--#{salt}--#{password}--")
80 end
81
82 # Encrypts the password with the user salt
83 def encrypt(password)
84 self.class.encrypt(password, salt)
85 end
86
87 def authenticated?(password)
88 crypted_password == encrypt(password)
89 end
90
91 def remember_token?
92 remember_token_expires_at && Time.now.utc < remember_token_expires_at
93 end
94
95 # These create and unset the fields required for remembering users between browser closes
96 def remember_me
97 remember_me_for 2.weeks
98 end
99
100 def remember_me_for(time)
101 remember_me_until time.from_now.utc
102 end
103
104 def remember_me_until(time)
105 self.remember_token_expires_at = time
106 self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
107 save(false)
108 end
109
110 def forget_me
111 self.remember_token_expires_at = nil
112 self.remember_token = nil
113 save(false)
114 end
115
116 protected
117 # before filter
118 def encrypt_password
119 return if password.blank?
120 self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
121 self.crypted_password = encrypt(password)
122 end
123
124 def password_required?
125 crypted_password.blank? || !password.blank?
126 end
127 <% if options[:include_activation] %>
128 def make_activation_code
129<% if options[:stateful] %> self.deleted_at = nil<% end %>
130 self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
131 end<% end %>
132 <% if options[:stateful] %>
133 def do_delete
134 self.deleted_at = Time.now.utc
135 end
136
137 def do_activate
138 self.activated_at = Time.now.utc
139 self.deleted_at = self.activation_code = nil
140 end<% end %>
141end
  
1class <%= model_controller_class_name %>Controller < ApplicationController
2 # Be sure to include AuthenticationSystem in Application Controller instead
3 include AuthenticatedSystem
4 <% if options[:stateful] %>
5 # Protect these actions behind an admin login
6 # before_filter :admin_required, :only => [:suspend, :unsuspend, :destroy, :purge]
7 before_filter :find_<%= file_name %>, :only => [:suspend, :unsuspend, :destroy, :purge]
8 <% end %>
9
10 # render new.rhtml
11 def new
12 end
13
14 def create
15 cookies.delete :auth_token
16 # protects against session fixation attacks, wreaks havoc with
17 # request forgery protection.
18 # uncomment at your own risk
19 # reset_session
20 @<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
21 @<%= file_name %>.<% if options[:stateful] %>register! if @<%= file_name %>.valid?<% else %>save<% end %>
22 if @<%= file_name %>.errors.empty?
23 self.current_<%= file_name %> = @<%= file_name %>
24 redirect_back_or_default('/')
25 flash[:notice] = "Thanks for signing up!"
26 else
27 render :action => 'new'
28 end
29 end
30<% if options[:include_activation] %>
31 def activate
32 self.current_<%= file_name %> = params[:activation_code].blank? ? :false : <%= class_name %>.find_by_activation_code(params[:activation_code])
33 if logged_in? && !current_<%= file_name %>.active?
34 current_<%= file_name %>.activate<% if options[:stateful] %>!<% end %>
35 flash[:notice] = "Signup complete!"
36 end
37 redirect_back_or_default('/')
38 end
39<% end %><% if options[:stateful] %>
40 def suspend
41 @<%= file_name %>.suspend!
42 redirect_to <%= table_name %>_path
43 end
44
45 def unsuspend
46 @<%= file_name %>.unsuspend!
47 redirect_to <%= table_name %>_path
48 end
49
50 def destroy
51 @<%= file_name %>.delete!
52 redirect_to <%= table_name %>_path
53 end
54
55 def purge
56 @<%= file_name %>.destroy
57 redirect_to <%= table_name %>_path
58 end
59
60protected
61 def find_<%= file_name %>
62 @<%= file_name %> = <%= class_name %>.find(params[:id])
63 end
64<% end %>
65end
  
1require File.dirname(__FILE__) + '/../spec_helper'
2
3# Be sure to include AuthenticatedTestHelper in spec/spec_helper.rb instead
4# Then, you can remove it from this and the units test.
5include AuthenticatedTestHelper
6
7describe <%= model_controller_class_name %>Controller do
8 fixtures :<%= table_name %>
9
10 it 'allows signup' do
11 lambda do
12 create_<%= file_name %>
13 response.should be_redirect
14 end.should change(<%= class_name %>, :count).by(1)
15 end
16
17 <% if options[:stateful] %>
18 it 'signs up user in pending state' do
19 create_user
20 assigns(:user).should be_pending
21 end<% end %>
22
23 <% if options[:include_activation] %>
24 it 'signs up user with activation code' do
25 create_user
26 assigns(:user).activation_code.should_not be_nil
27 end<% end %>
28
29 it 'requires login on signup' do
30 lambda do
31 create_<%= file_name %>(:login => nil)
32 assigns[:<%= file_name %>].errors.on(:login).should_not be_nil
33 response.should be_success
34 end.should_not change(<%= class_name %>, :count)
35 end
36
37 it 'requires password on signup' do
38 lambda do
39 create_<%= file_name %>(:password => nil)
40 assigns[:<%= file_name %>].errors.on(:password).should_not be_nil
41 response.should be_success
42 end.should_not change(<%= class_name %>, :count)
43 end
44
45 it 'requires password confirmation on signup' do
46 lambda do
47 create_<%= file_name %>(:password_confirmation => nil)
48 assigns[:<%= file_name %>].errors.on(:password_confirmation).should_not be_nil
49 response.should be_success
50 end.should_not change(<%= class_name %>, :count)
51 end
52
53 it 'requires email on signup' do
54 lambda do
55 create_<%= file_name %>(:email => nil)
56 assigns[:<%= file_name %>].errors.on(:email).should_not be_nil
57 response.should be_success
58 end.should_not change(<%= class_name %>, :count)
59 end
60
61 <% if options[:include_activation] %>
62 it 'activates user' do
63 <%= class_name %>.authenticate('aaron', 'test').should be_nil
64 get :activate, :activation_code => <%= table_name %>(:aaron).activation_code
65 response.should redirect_to('/')
66 flash[:notice].should_not be_nil
67 <%= class_name %>.authenticate('aaron', 'test').should == <%= table_name %>(:aaron)
68 end
69
70 it 'does not activate user without key' do
71 get :activate
72 flash[:notice].should be_nil
73 end
74
75 it 'does not activate user with blank key' do
76 get :activate, :activation_code => ''
77 flash[:notice].should be_nil
78 end<% end %>
79
80 def create_<%= file_name %>(options = {})
81 post :create, :<%= file_name %> => { :login => 'quire', :email => 'quire@example.com',
82 :password => 'quire', :password_confirmation => 'quire' }.merge(options)
83 end
84end
  
1require File.dirname(__FILE__) + '/../test_helper'
2require '<%= model_controller_file_name %>_controller'
3
4# Re-raise errors caught by the controller.
5class <%= model_controller_class_name %>Controller; def rescue_action(e) raise e end; end
6
7class <%= model_controller_class_name %>ControllerTest < Test::Unit::TestCase
8 # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9 # Then, you can remove it from this and the units test.
10 include AuthenticatedTestHelper
11
12 fixtures :<%= table_name %>
13
14 def setup
15 @controller = <%= model_controller_class_name %>Controller.new
16 @request = ActionController::TestRequest.new
17 @response = ActionController::TestResponse.new
18 end
19
20 def test_should_allow_signup
21 assert_difference '<%= class_name %>.count' do
22 create_<%= file_name %>
23 assert_response :redirect
24 end
25 end
26
27 def test_should_require_login_on_signup
28 assert_no_difference '<%= class_name %>.count' do
29 create_<%= file_name %>(:login => nil)
30 assert assigns(:<%= file_name %>).errors.on(:login)
31 assert_response :success
32 end
33 end
34
35 def test_should_require_password_on_signup
36 assert_no_difference '<%= class_name %>.count' do
37 create_<%= file_name %>(:password => nil)
38 assert assigns(:<%= file_name %>).errors.on(:password)
39 assert_response :success
40 end
41 end
42
43 def test_should_require_password_confirmation_on_signup
44 assert_no_difference '<%= class_name %>.count' do
45 create_<%= file_name %>(:password_confirmation => nil)
46 assert assigns(:<%= file_name %>).errors.on(:password_confirmation)
47 assert_response :success
48 end
49 end
50
51 def test_should_require_email_on_signup
52 assert_no_difference '<%= class_name %>.count' do
53 create_<%= file_name %>(:email => nil)
54 assert assigns(:<%= file_name %>).errors.on(:email)
55 assert_response :success
56 end
57 end
58 <% if options[:include_activation] %>
59 def test_should_activate_user
60 assert_nil <%= class_name %>.authenticate('aaron', 'test')
61 get :activate, :activation_code => <%= table_name %>(:aaron).activation_code
62 assert_redirected_to '/'
63 assert_not_nil flash[:notice]
64 assert_equal <%= table_name %>(:aaron), <%= class_name %>.authenticate('aaron', 'test')
65 end
66
67 def test_should_not_activate_user_without_key
68 get :activate
69 assert_nil flash[:notice]
70 rescue ActionController::RoutingError
71 # in the event your routes deny this, we'll just bow out gracefully.
72 end
73
74 def test_should_not_activate_user_with_blank_key
75 get :activate, :activation_code => ''
76 assert_nil flash[:notice]
77 rescue ActionController::RoutingError
78 # well played, sir
79 end<% end %>
80
81 protected
82 def create_<%= file_name %>(options = {})
83 post :create, :<%= file_name %> => { :login => 'quire', :email => 'quire@example.com',
84 :password => 'quire', :password_confirmation => 'quire' }.merge(options)
85 end
86end
  
1module <%= model_controller_class_name %>Helper
2end
  
1class <%= class_name %>Observer < ActiveRecord::Observer
2 def after_create(<%= file_name %>)
3 <%= class_name %>Mailer.deliver_signup_notification(<%= file_name %>)
4 end
5
6 def after_save(<%= file_name %>)
7 <% if options[:include_activation] %>
8 <%= class_name %>Mailer.deliver_activation(<%= file_name %>) if <%= file_name %>.pending?
9 <% end %>
10 end
11end
  
1<%%= error_messages_for :<%= file_name %> %>
2<%% form_for :<%= file_name %>, :url => <%= table_name %>_path do |f| -%>
3<p><label for="login">Login</label><br/>
4<%%= f.text_field :login %></p>
5
6<p><label for="email">Email</label><br/>
7<%%= f.text_field :email %></p>
8
9<p><label for="password">Password</label><br/>
10<%%= f.password_field :password %></p>
11
12<p><label for="password_confirmation">Confirm Password</label><br/>
13<%%= f.password_field :password_confirmation %></p>
14
15<p><%%= submit_tag 'Sign up' %></p>
16<%% end -%>
  
1Your account has been created.
2
3 Username: <%%= @<%= file_name %>.login %>
4 Password: <%%= @<%= file_name %>.password %>
5
6Visit this url to activate your account:
7
8 <%%= @url %>
  
1require File.dirname(__FILE__) + '/../spec_helper'
2
3# Be sure to include AuthenticatedTestHelper in spec/spec_helper.rb instead.
4# Then, you can remove it from this and the functional test.
5include AuthenticatedTestHelper
6
7describe <%= class_name %> do
8 fixtures :<%= table_name %>
9
10 describe 'being created' do
11 before do
12 @<%= file_name %> = nil
13 @creating_<%= file_name %> = lambda do
14 @<%= file_name %> = create_<%= file_name %>
15 violated "#{@<%= file_name %>.errors.full_messages.to_sentence}" if @<%= file_name %>.new_record?
16 end
17 end
18
19 it 'increments User#count' do
20 @creating_<%= file_name %>.should change(<%= class_name %>, :count).by(1)
21 end
22<% if options[:include_activation] %>
23 it 'initializes #activation_code' do
24 @creating_<%= file_name %>.call
25 @<%= file_name %>.reload.activation_code.should_not be_nil
26 end
27<% end %><% if options[:stateful] %>
28 it 'starts in pending state' do
29 @creating_<%= file_name %>.call
30 @<%= file_name %>.should be_pending
31 end
32<% end %> end
33
34 it 'requires login' do
35 lambda do
36 u = create_<%= file_name %>(:login => nil)
37 u.errors.on(:login).should_not be_nil
38 end.should_not change(<%= class_name %>, :count)
39 end
40
41 it 'requires password' do
42 lambda do
43 u = create_<%= file_name %>(:password => nil)
44 u.errors.on(:password).should_not be_nil
45 end.should_not change(<%= class_name %>, :count)
46 end
47
48 it 'requires password confirmation' do
49 lambda do
50 u = create_<%= file_name %>(:password_confirmation => nil)
51 u.errors.on(:password_confirmation).should_not be_nil
52 end.should_not change(<%= class_name %>, :count)
53 end
54
55 it 'requires email' do
56 lambda do
57 u = create_<%= file_name %>(:email => nil)
58 u.errors.on(:email).should_not be_nil
59 end.should_not change(<%= class_name %>, :count)
60 end
61
62 it 'resets password' do
63 <%= table_name %>(:quentin).update_attributes(:password => 'new password', :password_confirmation => 'new password')
64 <%= class_name %>.authenticate('quentin', 'new password').should == <%= table_name %>(:quentin)
65 end
66
67 it 'does not rehash password' do
68 <%= table_name %>(:quentin).update_attributes(:login => 'quentin2')
69 <%= class_name %>.authenticate('quentin2', 'test').should == <%= table_name %>(:quentin)
70 end
71
72 it 'authenticates <%= file_name %>' do
73 <%= class_name %>.authenticate('quentin', 'test').should == <%= table_name %>(:quentin)
74 end
75
76 it 'sets remember token' do
77 <%= table_name %>(:quentin).remember_me
78 <%= table_name %>(:quentin).remember_token.should_not be_nil
79 <%= table_name %>(:quentin).remember_token_expires_at.should_not be_nil
80 end
81
82 it 'unsets remember token' do
83 <%= table_name %>(:quentin).remember_me
84 <%= table_name %>(:quentin).remember_token.should_not be_nil
85 <%= table_name %>(:quentin).forget_me
86 <%= table_name %>(:quentin).remember_token.should be_nil
87 end
88
89 it 'remembers me for one week' do
90 before = 1.week.from_now.utc
91 <%= table_name %>(:quentin).remember_me_for 1.week
92 after = 1.week.from_now.utc
93 <%= table_name %>(:quentin).remember_token.should_not be_nil
94 <%= table_name %>(:quentin).remember_token_expires_at.should_not be_nil
95 <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after).should be_true
96 end
97
98 it 'remembers me until one week' do
99 time = 1.week.from_now.utc
100 <%= table_name %>(:quentin).remember_me_until time
101 <%= table_name %>(:quentin).remember_token.should_not be_nil
102 <%= table_name %>(:quentin).remember_token_expires_at.should_not be_nil
103 <%= table_name %>(:quentin).remember_token_expires_at.should == time
104 end
105
106 it 'remembers me default two weeks' do
107 before = 2.weeks.from_now.utc
108 <%= table_name %>(:quentin).remember_me
109 after = 2.weeks.from_now.utc
110 <%= table_name %>(:quentin).remember_token.should_not be_nil
111 <%= table_name %>(:quentin).remember_token_expires_at.should_not be_nil
112 <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after).should be_true
113 end
114<% if options[:stateful] %>
115 it 'registers passive <%= file_name %>' do
116 <%= file_name %> = create_<%= file_name %>(:password => nil, :password_confirmation => nil)
117 <%= file_name %>.should be_passive
118 <%= file_name %>.update_attributes(:password => 'new password', :password_confirmation => 'new password')
119 <%= file_name %>.register!
120 <%= file_name %>.should be_pending
121 end
122
123 it 'suspends <%= file_name %>' do
124 <%= table_name %>(:quentin).suspend!
125 <%= table_name %>(:quentin).should be_suspended
126 end
127
128 it 'does not authenticate suspended <%= file_name %>' do
129 <%= table_name %>(:quentin).suspend!
130 <%= class_name %>.authenticate('quentin', 'test').should_not == <%= table_name %>(:quentin)
131 end
132
133 it 'deletes <%= file_name %>' do
134 <%= table_name %>(:quentin).deleted_at.should be_nil
135 <%= table_name %>(:quentin).delete!
136 <%= table_name %>(:quentin).deleted_at.should_not be_nil
137 <%= table_name %>(:quentin).should be_deleted
138 end
139
140 describe "being unsuspended" do
141 fixtures :<%= table_name %>
142
143 before do
144 @<%= file_name %> = <%= table_name %>(:quentin)
145 @<%= file_name %>.suspend!
146 end
147
148 it 'reverts to active state' do
149 @<%= file_name %>.unsuspend!
150 @<%= file_name %>.should be_active
151 end
152
153 it 'reverts to passive state if activation_code and activated_at are nil' do
154 <%= class_name %>.update_all :activation_code => nil, :activated_at => nil
155 @<%= file_name %>.reload.unsuspend!
156 @<%= file_name %>.should be_passive
157 end
158
159 it 'reverts to pending state if activation_code is set and activated_at is nil' do
160 <%= class_name %>.update_all :activation_code => 'foo-bar', :activated_at => nil
161 @<%= file_name %>.reload.unsuspend!
162 @<%= file_name %>.should be_pending
163 end
164 end
165<% end %>
166protected
167 def create_<%= file_name %>(options = {})
168 record = <%= class_name %>.new({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options))
169 record.<% if options[:stateful] %>register! if record.valid?<% else %>save<% end %>
170 record
171 end
172end
  
1require File.dirname(__FILE__) + '/../test_helper'
2
3class <%= class_name %>Test < Test::Unit::TestCase
4 # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead.
5 # Then, you can remove it from this and the functional test.
6 include AuthenticatedTestHelper
7 fixtures :<%= table_name %>
8
9 def test_should_create_<%= file_name %>
10 assert_difference '<%= class_name %>.count' do
11 <%= file_name %> = create_<%= file_name %>
12 assert !<%= file_name %>.new_record?, "#{<%= file_name %>.errors.full_messages.to_sentence}"
13 end
14 end
15<% if options[:include_activation] %>
16 def test_should_initialize_activation_code_upon_creation
17 <%= file_name %> = create_<%= file_name %>
18 assert_not_nil <%= file_name %>.reload.activation_code
19 end
20<% end %><% if options[:stateful] %>
21 def test_should_create_and_start_in_pending_state
22 <%= file_name %> = create_<%= file_name %>
23 assert <%= file_name %>.pending?
24 end
25
26<% end %>
27 def test_should_require_login
28 assert_no_difference '<%= class_name %>.count' do
29 u = create_<%= file_name %>(:login => nil)
30 assert u.errors.on(:login)
31 end
32 end
33
34 def test_should_require_password
35 assert_no_difference '<%= class_name %>.count' do
36 u = create_<%= file_name %>(:password => nil)
37 assert u.errors.on(:password)
38 end
39 end
40
41 def test_should_require_password_confirmation
42 assert_no_difference '<%= class_name %>.count' do
43 u = create_<%= file_name %>(:password_confirmation => nil)
44 assert u.errors.on(:password_confirmation)
45 end
46 end
47
48 def test_should_require_email
49 assert_no_difference '<%= class_name %>.count' do
50 u = create_<%= file_name %>(:email => nil)
51 assert u.errors.on(:email)
52 end
53 end
54
55 def test_should_reset_password
56 <%= table_name %>(:quentin).update_attributes(:password => 'new password', :password_confirmation => 'new password')
57 assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'new password')
58 end
59
60 def test_should_not_rehash_password
61 <%= table_name %>(:quentin).update_attributes(:login => 'quentin2')
62 assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin2', 'test')
63 end
64
65 def test_should_authenticate_<%= file_name %>
66 assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'test')
67 end
68
69 def test_should_set_remember_token
70 <%= table_name %>(:quentin).remember_me
71 assert_not_nil <%= table_name %>(:quentin).remember_token
72 assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
73 end
74
75 def test_should_unset_remember_token
76 <%= table_name %>(:quentin).remember_me
77 assert_not_nil <%= table_name %>(:quentin).remember_token
78 <%= table_name %>(:quentin).forget_me
79 assert_nil <%= table_name %>(:quentin).remember_token
80 end
81
82 def test_should_remember_me_for_one_week
83 before = 1.week.from_now.utc
84 <%= table_name %>(:quentin).remember_me_for 1.week
85 after = 1.week.from_now.utc
86 assert_not_nil <%= table_name %>(:quentin).remember_token
87 assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
88 assert <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after)
89 end
90
91 def test_should_remember_me_until_one_week
92 time = 1.week.from_now.utc
93 <%= table_name %>(:quentin).remember_me_until time
94 assert_not_nil <%= table_name %>(:quentin).remember_token
95 assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
96 assert_equal <%= table_name %>(:quentin).remember_token_expires_at, time
97 end
98
99 def test_should_remember_me_default_two_weeks
100 before = 2.weeks.from_now.utc
101 <%= table_name %>(:quentin).remember_me
102 after = 2.weeks.from_now.utc
103 assert_not_nil <%= table_name %>(:quentin).remember_token
104 assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
105 assert <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after)
106 end
107<% if options[:stateful] %>
108 def test_should_register_passive_<%= file_name %>
109 <%= file_name %> = create_<%= file_name %>(:password => nil, :password_confirmation => nil)
110 assert <%= file_name %>.passive?
111 <%= file_name %>.update_attributes(:password => 'new password', :password_confirmation => 'new password')
112 <%= file_name %>.register!
113 assert <%= file_name %>.pending?
114 end
115
116 def test_should_suspend_<%= file_name %>
117 <%= table_name %>(:quentin).suspend!
118 assert <%= table_name %>(:quentin).suspended?
119 end
120
121 def test_suspended_<%= file_name %>_should_not_authenticate
122 <%= table_name %>(:quentin).suspend!
123 assert_not_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'test')
124 end
125
126 def test_should_unsuspend_<%= file_name %>_to_active_state
127 <%= table_name %>(:quentin).suspend!
128 assert <%= table_name %>(:quentin).suspended?
129 <%= table_name %>(:quentin).unsuspend!
130 assert <%= table_name %>(:quentin).active?
131 end
132
133 def test_should_unsuspend_<%= file_name %>_with_nil_activation_code_and_activated_at_to_passive_state
134 <%= table_name %>(:quentin).suspend!
135 <%= class_name %>.update_all :activation_code => nil, :activated_at => nil
136 assert <%= table_name %>(:quentin).suspended?
137 <%= table_name %>(:quentin).reload.unsuspend!
138 assert <%= table_name %>(:quentin).passive?
139 end
140
141 def test_should_unsuspend_<%= file_name %>_with_activation_code_and_nil_activated_at_to_pending_state
142 <%= table_name %>(:quentin).suspend!
143 <%= class_name %>.update_all :activation_code => 'foo-bar', :activated_at => nil
144 assert <%= table_name %>(:quentin).suspended?
145 <%= table_name %>(:quentin).reload.unsuspend!
146 assert <%= table_name %>(:quentin).pending?
147 end
148
149 def test_should_delete_<%= file_name %>
150 assert_nil <%= table_name %>(:quentin).deleted_at
151 <%= table_name %>(:quentin).delete!
152 assert_not_nil <%= table_name %>(:quentin).deleted_at
153 assert <%= table_name %>(:quentin).deleted?
154 end
155<% end %>
156protected
157 def create_<%= file_name %>(options = {})
158 <%= class_name %>.create({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options))
159 end
160end
  
1puts IO.read(File.join(File.dirname(__FILE__), 'README'))
  
1Rails::Generator::Commands::Create.class_eval do
2 def route_resource(*resources)
3 resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
4 sentinel = 'ActionController::Routing::Routes.draw do |map|'
5
6 logger.route "map.resource #{resource_list}"
7 unless options[:pretend]
8 gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
9 "#{match}\n map.resource #{resource_list}\n"
10 end
11 end
12 end
13end
14
15Rails::Generator::Commands::Destroy.class_eval do
16 def route_resource(*resources)
17 resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
18 look_for = "\n map.resource #{resource_list}\n"
19 logger.route "map.resource #{resource_list}"
20 gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
21 end
22end
23
24Rails::Generator::Commands::List.class_eval do
25 def route_resource(*resources)
26 resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
27 logger.route "map.resource #{resource_list}"
28 end
29end