qrush-clearance 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/CHANGELOG.textile +176 -0
  2. data/LICENSE +21 -0
  3. data/README.textile +123 -0
  4. data/Rakefile +103 -0
  5. data/TODO.textile +6 -0
  6. data/app/controllers/clearance/confirmations_controller.rb +72 -0
  7. data/app/controllers/clearance/passwords_controller.rb +80 -0
  8. data/app/controllers/clearance/sessions_controller.rb +66 -0
  9. data/app/controllers/clearance/users_controller.rb +34 -0
  10. data/app/models/clearance_mailer.rb +23 -0
  11. data/app/views/clearance_mailer/change_password.html.erb +7 -0
  12. data/app/views/clearance_mailer/confirmation.html.erb +2 -0
  13. data/app/views/passwords/edit.html.erb +23 -0
  14. data/app/views/passwords/new.html.erb +15 -0
  15. data/app/views/sessions/new.html.erb +28 -0
  16. data/app/views/users/_form.html.erb +13 -0
  17. data/app/views/users/new.html.erb +6 -0
  18. data/config/clearance_routes.rb +30 -0
  19. data/generators/clearance/USAGE +1 -0
  20. data/generators/clearance/clearance_generator.rb +41 -0
  21. data/generators/clearance/lib/insert_commands.rb +33 -0
  22. data/generators/clearance/lib/rake_commands.rb +22 -0
  23. data/generators/clearance/templates/README +22 -0
  24. data/generators/clearance/templates/factories.rb +13 -0
  25. data/generators/clearance/templates/migrations/create_users.rb +21 -0
  26. data/generators/clearance/templates/migrations/update_users.rb +41 -0
  27. data/generators/clearance/templates/user.rb +3 -0
  28. data/generators/clearance_features/USAGE +1 -0
  29. data/generators/clearance_features/clearance_features_generator.rb +20 -0
  30. data/generators/clearance_features/templates/features/password_reset.feature +33 -0
  31. data/generators/clearance_features/templates/features/sign_in.feature +42 -0
  32. data/generators/clearance_features/templates/features/sign_out.feature +23 -0
  33. data/generators/clearance_features/templates/features/sign_up.feature +45 -0
  34. data/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb +110 -0
  35. data/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb +5 -0
  36. data/generators/clearance_features/templates/features/support/paths.rb +22 -0
  37. data/generators/clearance_views/USAGE +0 -0
  38. data/generators/clearance_views/clearance_views_generator.rb +27 -0
  39. data/generators/clearance_views/templates/formtastic/passwords/edit.html.erb +21 -0
  40. data/generators/clearance_views/templates/formtastic/passwords/new.html.erb +15 -0
  41. data/generators/clearance_views/templates/formtastic/sessions/new.html.erb +22 -0
  42. data/generators/clearance_views/templates/formtastic/users/_inputs.html.erb +6 -0
  43. data/generators/clearance_views/templates/formtastic/users/new.html.erb +10 -0
  44. data/lib/clearance.rb +6 -0
  45. data/lib/clearance/authentication.rb +102 -0
  46. data/lib/clearance/extensions/errors.rb +6 -0
  47. data/lib/clearance/extensions/rescue.rb +3 -0
  48. data/lib/clearance/extensions/routes.rb +14 -0
  49. data/lib/clearance/user.rb +143 -0
  50. data/rails/init.rb +1 -0
  51. data/shoulda_macros/clearance.rb +268 -0
  52. metadata +145 -0
@@ -0,0 +1,80 @@
1
+ class Clearance::PasswordsController < ApplicationController
2
+
3
+ before_filter :forbid_missing_token, :only => [:edit, :update]
4
+ before_filter :forbid_non_existent_user, :only => [:edit, :update]
5
+ filter_parameter_logging :password, :password_confirmation
6
+
7
+ def new
8
+ render :template => 'passwords/new'
9
+ end
10
+
11
+ def create
12
+ if user = ::User.find_by_email(params[:password][:email])
13
+ user.forgot_password!
14
+ ::ClearanceMailer.deliver_change_password user
15
+ flash_notice_after_create
16
+ redirect_to(url_after_create)
17
+ else
18
+ flash_failure_after_create
19
+ render :template => 'passwords/new'
20
+ end
21
+ end
22
+
23
+ def edit
24
+ @user = ::User.find_by_id_and_token(params[:user_id], params[:token])
25
+ render :template => 'passwords/edit'
26
+ end
27
+
28
+ def update
29
+ @user = ::User.find_by_id_and_token(params[:user_id], params[:token])
30
+
31
+ if @user.update_password(params[:user][:password],
32
+ params[:user][:password_confirmation])
33
+ @user.confirm_email!
34
+ sign_in(@user)
35
+ flash_success_after_update
36
+ redirect_to(url_after_update)
37
+ else
38
+ render :template => 'passwords/edit'
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def forbid_missing_token
45
+ if params[:token].blank?
46
+ raise ActionController::Forbidden, "missing token"
47
+ end
48
+ end
49
+
50
+ def forbid_non_existent_user
51
+ unless ::User.find_by_id_and_token(params[:user_id], params[:token])
52
+ raise ActionController::Forbidden, "non-existent user"
53
+ end
54
+ end
55
+
56
+ def flash_notice_after_create
57
+ flash[:notice] = translate(:deliver_change_password,
58
+ :scope => [:clearance, :controllers, :passwords],
59
+ :default => "You will receive an email within the next few minutes. " <<
60
+ "It contains instructions for changing your password.")
61
+ end
62
+
63
+ def flash_failure_after_create
64
+ flash.now[:failure] = translate(:unknown_email,
65
+ :scope => [:clearance, :controllers, :passwords],
66
+ :default => "Unknown email.")
67
+ end
68
+
69
+ def url_after_create
70
+ new_session_url
71
+ end
72
+
73
+ def flash_success_after_update
74
+ flash[:success] = translate(:signed_in, :default => "Signed in.")
75
+ end
76
+
77
+ def url_after_update
78
+ root_url
79
+ end
80
+ end
@@ -0,0 +1,66 @@
1
+ class Clearance::SessionsController < ApplicationController
2
+
3
+ protect_from_forgery :except => :create
4
+ filter_parameter_logging :password
5
+
6
+ def new
7
+ render :template => 'sessions/new'
8
+ end
9
+
10
+ def create
11
+ @user = ::User.authenticate(params[:session][:email],
12
+ params[:session][:password])
13
+ if @user.nil?
14
+ flash_failure_after_create
15
+ render :template => 'sessions/new', :status => :unauthorized
16
+ else
17
+ if @user.email_confirmed?
18
+ sign_in(@user)
19
+ remember(@user) if remember?
20
+ flash_success_after_create
21
+ redirect_back_or(url_after_create)
22
+ else
23
+ ::ClearanceMailer.deliver_confirmation(@user)
24
+ flash_notice_after_create
25
+ redirect_to(new_session_url)
26
+ end
27
+ end
28
+ end
29
+
30
+ def destroy
31
+ forget(current_user)
32
+ flash_success_after_destroy
33
+ redirect_to(url_after_destroy)
34
+ end
35
+
36
+ private
37
+
38
+ def flash_failure_after_create
39
+ flash.now[:failure] = translate(:bad_email_or_password,
40
+ :scope => [:clearance, :controllers, :sessions],
41
+ :default => "Bad email or password.")
42
+ end
43
+
44
+ def flash_success_after_create
45
+ flash[:success] = translate(:signed_in, :default => "Signed in.")
46
+ end
47
+
48
+ def flash_notice_after_create
49
+ flash[:notice] = translate(:unconfirmed_email,
50
+ :scope => [:clearance, :controllers, :sessions],
51
+ :default => "User has not confirmed email. " <<
52
+ "Confirmation email will be resent.")
53
+ end
54
+
55
+ def url_after_create
56
+ root_url
57
+ end
58
+
59
+ def flash_success_after_destroy
60
+ flash[:success] = translate(:signed_out, :default => "Signed out.")
61
+ end
62
+
63
+ def url_after_destroy
64
+ new_session_url
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ class Clearance::UsersController < ApplicationController
2
+
3
+ before_filter :redirect_to_root, :only => [:new, :create], :if => :signed_in?
4
+ filter_parameter_logging :password
5
+
6
+ def new
7
+ @user = ::User.new(params[:user])
8
+ render :template => 'users/new'
9
+ end
10
+
11
+ def create
12
+ @user = ::User.new params[:user]
13
+ if @user.save
14
+ ::ClearanceMailer.deliver_confirmation @user
15
+ flash_notice_after_create
16
+ redirect_to(url_after_create)
17
+ else
18
+ render :template => 'users/new'
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def flash_notice_after_create
25
+ flash[:notice] = translate(:deliver_confirmation,
26
+ :scope => [:clearance, :controllers, :users],
27
+ :default => "You will receive an email within the next few minutes. " <<
28
+ "It contains instructions for confirming your account.")
29
+ end
30
+
31
+ def url_after_create
32
+ new_session_url
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ class ClearanceMailer < ActionMailer::Base
2
+
3
+ default_url_options[:host] = HOST
4
+
5
+ def change_password(user)
6
+ from DO_NOT_REPLY
7
+ recipients user.email
8
+ subject I18n.t(:change_password,
9
+ :scope => [:clearance, :models, :clearance_mailer],
10
+ :default => "Change your password")
11
+ body :user => user
12
+ end
13
+
14
+ def confirmation(user)
15
+ from DO_NOT_REPLY
16
+ recipients user.email
17
+ subject I18n.t(:confirmation,
18
+ :scope => [:clearance, :models, :clearance_mailer],
19
+ :default => "Account confirmation")
20
+ body :user => user
21
+ end
22
+
23
+ end
@@ -0,0 +1,7 @@
1
+ Someone, hopefully you, has requested that we send you a link to change your password.
2
+
3
+ Here's the link:
4
+
5
+ <%= edit_user_password_url(@user, :token => @user.token, :escape => false) %>
6
+
7
+ If you didn't request this, ignore this email. Don't worry. Your password hasn't been changed.
@@ -0,0 +1,2 @@
1
+
2
+ <%= new_user_confirmation_url :user_id => @user, :token => @user.token, :encode => false %>
@@ -0,0 +1,23 @@
1
+ <h2>Change your password</h2>
2
+
3
+ <p>
4
+ Your password has been reset. Choose a new password below.
5
+ </p>
6
+
7
+ <%= error_messages_for :user %>
8
+
9
+ <% form_for(:user,
10
+ :url => user_password_path(@user, :token => @user.token),
11
+ :html => { :method => :put }) do |form| %>
12
+ <div class="password_field">
13
+ <%= form.label :password, "Choose password" %>
14
+ <%= form.password_field :password %>
15
+ </div>
16
+ <div class="password_field">
17
+ <%= form.label :password_confirmation, "Confirm password" %>
18
+ <%= form.password_field :password_confirmation %>
19
+ </div>
20
+ <div class="submit_field">
21
+ <%= form.submit "Save this password", :disable_with => "Please wait..." %>
22
+ </div>
23
+ <% end %>
@@ -0,0 +1,15 @@
1
+ <h2>Change your password</h2>
2
+
3
+ <p>
4
+ We will email you a link to change your password.
5
+ </p>
6
+
7
+ <% form_for :password, :url => passwords_path do |form| %>
8
+ <div class="text_field">
9
+ <%= form.label :email, "Email address" %>
10
+ <%= form.text_field :email %>
11
+ </div>
12
+ <div class="submit_field">
13
+ <%= form.submit "Reset password", :disable_with => "Please wait..." %>
14
+ </div>
15
+ <% end %>
@@ -0,0 +1,28 @@
1
+ <h2>Sign in</h2>
2
+
3
+ <% form_for :session, :url => session_path do |form| %>
4
+ <div class="text_field">
5
+ <%= form.label :email %>
6
+ <%= form.text_field :email %>
7
+ </div>
8
+ <div class="text_field">
9
+ <%= form.label :password %>
10
+ <%= form.password_field :password %>
11
+ </div>
12
+ <div class="text_field">
13
+ <%= form.check_box :remember_me %>
14
+ <%= form.label :remember_me %>
15
+ </div>
16
+ <div class="submit_field">
17
+ <%= form.submit "Sign in", :disable_with => "Please wait..." %>
18
+ </div>
19
+ <% end %>
20
+
21
+ <ul>
22
+ <li>
23
+ <%= link_to "Sign up", new_user_path %>
24
+ </li>
25
+ <li>
26
+ <%= link_to "Forgot password?", new_password_path %>
27
+ </li>
28
+ </ul>
@@ -0,0 +1,13 @@
1
+ <%= form.error_messages %>
2
+ <div class="text_field">
3
+ <%= form.label :email %>
4
+ <%= form.text_field :email %>
5
+ </div>
6
+ <div class="password_field">
7
+ <%= form.label :password %>
8
+ <%= form.password_field :password %>
9
+ </div>
10
+ <div class="password_field">
11
+ <%= form.label :password_confirmation, "Confirm password" %>
12
+ <%= form.password_field :password_confirmation %>
13
+ </div>
@@ -0,0 +1,6 @@
1
+ <h2>Sign up</h2>
2
+
3
+ <% form_for @user do |form| %>
4
+ <%= render :partial => '/users/form', :object => form %>
5
+ <%= form.submit 'Sign up', :disable_with => 'Please wait...' %>
6
+ <% end %>
@@ -0,0 +1,30 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.resources :passwords,
3
+ :controller => 'clearance/passwords',
4
+ :only => [:new, :create]
5
+
6
+ map.resource :session,
7
+ :controller => 'clearance/sessions',
8
+ :only => [:new, :create, :destroy]
9
+
10
+ map.resources :users, :controller => 'clearance/users' do |users|
11
+ users.resource :password,
12
+ :controller => 'clearance/passwords',
13
+ :only => [:create, :edit, :update]
14
+
15
+ users.resource :confirmation,
16
+ :controller => 'clearance/confirmations',
17
+ :only => [:new, :create]
18
+ end
19
+
20
+ map.sign_up 'sign_up',
21
+ :controller => 'clearance/users',
22
+ :action => 'new'
23
+ map.sign_in 'sign_in',
24
+ :controller => 'clearance/sessions',
25
+ :action => 'new'
26
+ map.sign_out 'sign_out',
27
+ :controller => 'clearance/sessions',
28
+ :action => 'destroy',
29
+ :method => :delete
30
+ end
@@ -0,0 +1 @@
1
+ script/generate clearance
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
2
+ require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
3
+ require 'factory_girl'
4
+
5
+ class ClearanceGenerator < Rails::Generator::Base
6
+
7
+ def manifest
8
+ record do |m|
9
+ m.insert_into "app/controllers/application_controller.rb",
10
+ "include Clearance::Authentication"
11
+
12
+ user_model = "app/models/user.rb"
13
+ if File.exists?(user_model)
14
+ m.insert_into user_model, "include Clearance::User"
15
+ else
16
+ m.directory File.join("app", "models")
17
+ m.file "user.rb", user_model
18
+ end
19
+
20
+ m.directory File.join("test", "factories")
21
+ m.file "factories.rb", "test/factories/clearance.rb"
22
+
23
+ m.migration_template "migrations/#{migration_name}.rb",
24
+ 'db/migrate',
25
+ :migration_file_name => "clearance_#{migration_name}"
26
+
27
+ m.readme "README"
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def migration_name
34
+ if ActiveRecord::Base.connection.table_exists?(:users)
35
+ 'update_users'
36
+ else
37
+ 'create_users'
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,33 @@
1
+ # Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
2
+
3
+ Rails::Generator::Commands::Base.class_eval do
4
+ def file_contains?(relative_destination, line)
5
+ File.read(destination_path(relative_destination)).include?(line)
6
+ end
7
+ end
8
+
9
+ Rails::Generator::Commands::Create.class_eval do
10
+ def insert_into(file, line)
11
+ logger.insert "#{line} into #{file}"
12
+ unless options[:pretend] || file_contains?(file, line)
13
+ gsub_file file, /^(class|module) .+$/ do |match|
14
+ "#{match}\n #{line}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ Rails::Generator::Commands::Destroy.class_eval do
21
+ def insert_into(file, line)
22
+ logger.remove "#{line} from #{file}"
23
+ unless options[:pretend]
24
+ gsub_file file, "\n #{line}", ''
25
+ end
26
+ end
27
+ end
28
+
29
+ Rails::Generator::Commands::List.class_eval do
30
+ def insert_into(file, line)
31
+ logger.insert "#{line} into #{file}"
32
+ end
33
+ end
@@ -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