thoughtbot-clearance 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/README.textile +147 -60
  2. data/Rakefile +29 -21
  3. data/TODO.textile +1 -15
  4. data/generators/clearance/clearance_generator.rb +31 -9
  5. data/generators/clearance/lib/insert_commands.rb +103 -0
  6. data/generators/clearance/lib/rake_commands.rb +22 -0
  7. data/generators/clearance/templates/README +37 -0
  8. data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +3 -1
  9. data/generators/clearance/templates/app/views/passwords/edit.html.erb +4 -4
  10. data/generators/clearance/templates/db/migrate/create_users_with_clearance_columns.rb +21 -0
  11. data/generators/clearance/templates/db/migrate/update_users_with_clearance_columns.rb +41 -0
  12. data/generators/clearance/templates/test/{factories.rb → factories/clearance_user.rb} +1 -1
  13. data/lib/clearance.rb +3 -4
  14. data/lib/clearance/app/controllers/application_controller.rb +47 -61
  15. data/lib/clearance/app/controllers/confirmations_controller.rb +25 -33
  16. data/lib/clearance/app/controllers/passwords_controller.rb +41 -46
  17. data/lib/clearance/app/controllers/sessions_controller.rb +49 -56
  18. data/lib/clearance/app/controllers/users_controller.rb +21 -29
  19. data/lib/clearance/app/models/clearance_mailer.rb +15 -19
  20. data/lib/clearance/app/models/user.rb +53 -56
  21. data/lib/clearance/test/functional/confirmations_controller_test.rb +4 -35
  22. data/lib/clearance/test/functional/passwords_controller_test.rb +9 -5
  23. data/lib/clearance/test/functional/sessions_controller_test.rb +67 -17
  24. data/lib/clearance/test/functional/users_controller_test.rb +15 -7
  25. data/lib/clearance/test/test_helper.rb +10 -81
  26. data/lib/clearance/test/unit/clearance_mailer_test.rb +5 -5
  27. data/lib/clearance/test/unit/user_test.rb +42 -59
  28. data/rails/init.rb +1 -0
  29. data/shoulda_macros/clearance.rb +45 -0
  30. metadata +14 -6
  31. data/generators/clearance/templates/app/views/confirmations/new.html.erb +0 -6
  32. data/lib/clearance/version.rb +0 -7
@@ -0,0 +1,22 @@
1
+ Rails::Generator::Commands::Create.class_eval do
2
+ def rake_db_migrate
3
+ logger.rake "db:migrate"
4
+ unless system("rake db:migrate")
5
+ logger.rake "db:migrate failed. Rolling back"
6
+ command(:destroy).invoke!
7
+ end
8
+ end
9
+ end
10
+
11
+ Rails::Generator::Commands::Destroy.class_eval do
12
+ def rake_db_migrate
13
+ logger.rake "db:rollback"
14
+ system "rake db:rollback"
15
+ end
16
+ end
17
+
18
+ Rails::Generator::Commands::List.class_eval do
19
+ def rake_db_migrate
20
+ logger.rake "db:migrate"
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ *******************************************************************************
2
+ Ok, enough fancy automatic stuff. Time for some old school monkey copy-pasting.
3
+
4
+ 1. For any other file(s) that you already had and didn't want to overwrite, add
5
+ the corresponding Clearance module. They are namespaced exactly like the
6
+ directory structure of a Rails app, e.g:
7
+
8
+ if app/models/user.rb already exists, add:
9
+
10
+ class User < ActiveRecord::Base
11
+ include Clearance::App::Models::User
12
+ ...
13
+
14
+ 2. You need to define HOST constant in your environments files. In config/environments/test.rb and config/environments/development.rb it can be:
15
+
16
+ HOST = "localhost"
17
+
18
+ While in config/environments/production.rb it must be the actual host your application is deployed to because the constant is used by mailers to generate URLs in emails.
19
+
20
+ In config/environment.rb:
21
+
22
+ DO_NOT_REPLY = "donotreply@example.com"
23
+
24
+ 3. Clearance depends on root_url, so please make sure that it is defined in
25
+ your config/routes.rb:
26
+
27
+ map.root :controller => 'my_home_controller'
28
+
29
+ 4. To run tests you need to add the Clearance module to your
30
+ test/test_helper.rb:
31
+
32
+ class Test::Unit::TestCase
33
+ self.use_transactional_fixtures = true
34
+ self.use_instantiated_fixtures = false
35
+ include Clearance::Test::TestHelper
36
+ end
37
+ *******************************************************************************
@@ -1,6 +1,8 @@
1
1
  Someone, hopefully you, has requested that we send you a link to change your password.
2
2
 
3
3
  Here's the link:
4
- <%= edit_user_password_url @user, :email => @user.email, :password => @user.crypted_password %>
4
+ <%= edit_user_password_url(@user,
5
+ :email => @user.email,
6
+ :password => @user.crypted_password) %>
5
7
 
6
8
  If you didn't request this, no need to freak out, your password hasn't been changed. You can just ignore this email.
@@ -3,11 +3,11 @@
3
3
  </p>
4
4
 
5
5
  <%= error_messages_for :user %>
6
+
6
7
  <% form_for(:user,
7
- :url => user_password_path(
8
- @user,
9
- :email => @user.email,
10
- :password => @user.crypted_password),
8
+ :url => user_password_path(@user,
9
+ :email => @user.email,
10
+ :password => @user.crypted_password),
11
11
  :html => { :method => :put }) do |form| %>
12
12
  <div class="password_field">
13
13
  <%= form.label :password, 'Choose password' %>
@@ -0,0 +1,21 @@
1
+ class CreateOrUpdateUsersWithClearanceColumns < ActiveRecord::Migration
2
+ def self.up
3
+ create_table(:users) do |t|
4
+ t.string :email
5
+ t.string :crypted_password, :limit => 40
6
+ t.string :salt, :limit => 40
7
+ t.string :remember_token
8
+ t.datetime :remember_token_expires_at
9
+ t.boolean :confirmed, :default => false, :null => false
10
+ end
11
+
12
+ add_index :users, [:email, :crypted_password]
13
+ add_index :users, [:id, :salt]
14
+ add_index :users, :email
15
+ add_index :users, :remember_token
16
+ end
17
+
18
+ def self.down
19
+ drop_table :users
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ class CreateOrUpdateUsersWithClearanceColumns < ActiveRecord::Migration
2
+ def self.up
3
+ <%
4
+ existing_columns = ActiveRecord::Base.connection.columns(:users).map { |column| column.name }
5
+ columns = [
6
+ [:email, 't.string :email'],
7
+ [:crypted_password, 't.string :crypted_password, :limit => 40'],
8
+ [:salt, 't.string :salt, :limit => 40'],
9
+ [:remember_token, 't.string :remember_token'],
10
+ [:remember_token_expires_at, 't.datetime :remember_token_expires_at'],
11
+ [:confirmed, 't.boolean :confirmed, :default => false, :null => false']
12
+ ].delete_if {|c| existing_columns.include?(c.first.to_s)}
13
+ -%>
14
+ change_table(:users) do |t|
15
+ <% columns.each do |c| -%>
16
+ <%= c.last %>
17
+ <% end -%>
18
+ end
19
+
20
+ <%
21
+ existing_indexes = ActiveRecord::Base.connection.indexes(:users).map { |index| index.name }
22
+ indexes = [
23
+ [:index_users_on_email_and_crypted_password, 'add_index :users, [:email, :crypted_password]'],
24
+ [:index_users_on_id_and_salt, 'add_index :users, [:id, :salt]'],
25
+ [:index_users_on_email, 'add_index :users, :email'],
26
+ [:index_users_on_remember_token, 'add_index :users, :remember_token']
27
+ ].delete_if {|i| existing_indexes.include?(i.first.to_s)}
28
+ -%>
29
+ <% indexes.each do |i| -%>
30
+ <%= i.last %>
31
+ <% end -%>
32
+ end
33
+
34
+ def self.down
35
+ change_table(:users) do |t|
36
+ <% unless columns.empty? -%>
37
+ t.remove <%= columns.collect {|c| ":#{c.first}" }.join(',') %>
38
+ <% end -%>
39
+ end
40
+ end
41
+ end
@@ -2,7 +2,7 @@ Factory.sequence :email do |n|
2
2
  "user#{n}@example.com"
3
3
  end
4
4
 
5
- Factory.define :user do |user|
5
+ Factory.define :clearance_user, :class => 'user' do |user|
6
6
  user.email { Factory.next :email }
7
7
  user.password "password"
8
8
  user.password_confirmation "password"
@@ -3,13 +3,12 @@ require 'clearance/app/controllers/confirmations_controller'
3
3
  require 'clearance/app/controllers/passwords_controller'
4
4
  require 'clearance/app/controllers/sessions_controller'
5
5
  require 'clearance/app/controllers/users_controller'
6
- require 'clearance/app/models/user'
7
6
  require 'clearance/app/models/clearance_mailer'
7
+ require 'clearance/app/models/user'
8
8
  require 'clearance/test/functional/confirmations_controller_test'
9
+ require 'clearance/test/functional/passwords_controller_test'
9
10
  require 'clearance/test/functional/sessions_controller_test'
10
11
  require 'clearance/test/functional/users_controller_test'
11
- require 'clearance/test/functional/passwords_controller_test'
12
12
  require 'clearance/test/test_helper'
13
- require 'clearance/test/unit/user_test'
14
13
  require 'clearance/test/unit/clearance_mailer_test'
15
- require 'clearance/version'
14
+ require 'clearance/test/unit/user_test'
@@ -3,79 +3,65 @@ module Clearance
3
3
  module Controllers
4
4
  module ApplicationController
5
5
 
6
- def self.included(base)
7
- base.class_eval do
6
+ def self.included(controller)
7
+ controller.class_eval do
8
8
  helper_method :current_user
9
9
  helper_method :logged_in?
10
10
 
11
- include InstanceMethods
11
+ def current_user
12
+ user_from_session || user_from_cookie
13
+ end
12
14
 
13
- protected
14
- include ProtectedInstanceMethods
15
- end
16
- end
17
-
18
- module InstanceMethods
19
- def current_user
20
- @current_user ||= (user_from_session || user_from_cookie)
21
- end
22
-
23
- def logged_in?
24
- ! current_user.nil?
25
- end
26
- end
15
+ def logged_in?
16
+ ! current_user.nil?
17
+ end
18
+
19
+ protected
20
+
21
+ def authenticate
22
+ deny_access unless logged_in?
23
+ end
27
24
 
28
- module ProtectedInstanceMethods
29
- def authenticate
30
- deny_access unless logged_in?
31
- end
25
+ def user_from_session
26
+ User.find_by_id session[:user_id]
27
+ end
32
28
 
33
- def user_from_session
34
- user_model.find_by_id session[:user_id]
35
- end
29
+ def user_from_cookie
30
+ if cookies[:auth_token]
31
+ user = User.find_by_remember_token(cookies[:auth_token])
32
+ end
33
+ user && user.remember_token? ? user : nil
34
+ end
36
35
 
37
- def user_from_cookie
38
- user = user_model.find_by_remember_token(cookies[:auth_token]) if cookies[:auth_token]
39
- user && user.remember_token? ? user : nil
40
- end
36
+ # Level of indirection so you can easily overwrite this method
37
+ # but also call #login .
38
+ def log_user_in(user)
39
+ login(user)
40
+ end
41
41
 
42
- # Level of indirection so you can easily override this method
43
- # but also call #login .
44
- def log_user_in(user)
45
- login(user)
46
- end
47
-
48
- def login(user)
49
- session[:user_id] = user.id if user
50
- @current_user = user
51
- end
42
+ def login(user)
43
+ session[:user_id] = user.id if user
44
+ end
52
45
 
53
- def redirect_back_or(default)
54
- session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
55
- session[:return_to] = nil
56
- end
57
-
58
- def redirect_to_root
59
- redirect_to root_url
60
- end
46
+ def redirect_back_or(default)
47
+ session[:return_to] ||= params[:return_to]
48
+ session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
49
+ session[:return_to] = nil
50
+ end
61
51
 
62
- def store_location
63
- session[:return_to] = request.request_uri
64
- end
52
+ def redirect_to_root
53
+ redirect_to root_url
54
+ end
65
55
 
66
- def deny_access(flash_message = nil, opts = {})
67
- opts[:redirect] ||= new_session_path
68
- store_location
69
- flash[:error] = flash_message if flash_message
70
- redirect_to opts[:redirect]
71
- end
72
-
73
- def user_model
74
- User
75
- end
56
+ def store_location
57
+ session[:return_to] = request.request_uri
58
+ end
76
59
 
77
- def mailer_model
78
- ClearanceMailer
60
+ def deny_access(flash_message = nil, opts = {})
61
+ store_location
62
+ flash[:failure] = flash_message if flash_message
63
+ render :template => "/sessions/new",:status => :unauthorized
64
+ end
79
65
  end
80
66
  end
81
67
  end
@@ -3,44 +3,36 @@ module Clearance
3
3
  module Controllers
4
4
  module ConfirmationsController
5
5
 
6
- def self.included(base)
7
- base.class_eval do
8
- before_filter :existing_user?, :only => [:new, :create]
6
+ def self.included(controller)
7
+ controller.class_eval do
8
+ before_filter :existing_user?, :only => :new
9
9
 
10
- include InstanceMethods
10
+ def new
11
+ create
12
+ end
13
+
14
+ def create
15
+ @user.confirm!
16
+ session[:user_id] = @user.id
17
+ redirect_to url_after_create
18
+ end
11
19
 
12
- private
13
- include PrivateInstanceMethods
14
- end
15
- end
16
-
17
- module InstanceMethods
18
- def new
19
- @user = User.find_by_id_and_salt(params[:user_id], params[:salt])
20
- end
20
+ private
21
+
22
+ def existing_user?
23
+ @user = User.find_by_id_and_salt(params[:user_id], params[:salt])
24
+ if @user.nil?
25
+ render :nothing => true, :status => :not_found
26
+ end
27
+ end
21
28
 
22
- def create
23
- @user = User.find_by_id_and_salt(params[:user_id], params[:salt])
24
- @user.confirm!
25
- session[:user_id] = @user.id
26
- redirect_to url_after_create
27
- end
28
- end
29
-
30
- module PrivateInstanceMethods
31
- def existing_user?
32
- user = User.find_by_id_and_salt(params[:user_id], params[:salt])
33
- if user.nil?
34
- render :nothing => true, :status => :not_found
29
+ def url_after_create
30
+ root_url
35
31
  end
32
+
36
33
  end
37
-
38
- def url_after_create
39
- root_url
40
- end
41
- end
42
-
34
+ end
43
35
  end
44
36
  end
45
37
  end
46
- end
38
+ end
@@ -3,64 +3,59 @@ module Clearance
3
3
  module Controllers
4
4
  module PasswordsController
5
5
 
6
- def self.included(base)
7
- base.class_eval do
6
+ def self.included(controller)
7
+ controller.class_eval do
8
8
  before_filter :existing_user?, :only => [:edit, :update]
9
9
  filter_parameter_logging :password, :password_confirmation
10
10
 
11
- include InstanceMethods
12
-
13
- private
14
- include PrivateInstanceMethods
15
- end
16
- end
17
-
18
- module InstanceMethods
19
- def new
20
- end
11
+ def new
12
+ end
21
13
 
22
- def create
23
- user = User.find_by_email params[:password][:email]
24
- if user.nil?
25
- flash.now[:warning] = 'Unknown email'
26
- render :action => :new
27
- else
28
- ClearanceMailer.deliver_change_password user
29
- redirect_to url_after_create
14
+ def create
15
+ user = User.find_by_email(params[:password][:email])
16
+ if user.nil?
17
+ flash.now[:warning] = 'Unknown email'
18
+ render :action => :new
19
+ else
20
+ ClearanceMailer.deliver_change_password user
21
+ flash[:notice] = "Details for changing your password " <<
22
+ "have been sent to #{user.email}"
23
+ redirect_to url_after_create
24
+ end
30
25
  end
31
- end
32
26
 
33
- def edit
34
- @user = User.find_by_email_and_crypted_password(params[:email],
35
- params[:password])
36
- end
27
+ def edit
28
+ @user = User.find_by_email_and_crypted_password(params[:email],
29
+ params[:password])
30
+ end
37
31
 
38
- def update
39
- @user = User.find_by_email_and_crypted_password(params[:email],
40
- params[:password])
41
- if @user.update_attributes params[:user]
42
- session[:user_id] = @user.id
43
- redirect_to @user
44
- else
45
- render :action => :edit
32
+ def update
33
+ @user = User.find_by_email_and_crypted_password(params[:email],
34
+ params[:password])
35
+ if @user.update_attributes params[:user]
36
+ session[:user_id] = @user.id
37
+ redirect_to @user
38
+ else
39
+ render :action => :edit
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def existing_user?
46
+ user = User.find_by_email_and_crypted_password(params[:email],
47
+ params[:password])
48
+ if user.nil?
49
+ render :nothing => true, :status => :not_found
50
+ end
46
51
  end
47
- end
48
- end
49
52
 
50
- module PrivateInstanceMethods
51
- def existing_user?
52
- user = User.find_by_email_and_crypted_password(params[:email],
53
- params[:password])
54
- if user.nil?
55
- render :nothing => true, :status => :not_found
53
+ def url_after_create
54
+ new_session_url
56
55
  end
57
- end
58
-
59
- def url_after_create
60
- new_session_url
56
+
61
57
  end
62
58
  end
63
-
64
59
  end
65
60
  end
66
61
  end