clearance 1.8.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of clearance might be problematic. Click here for more details.

Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +25 -6
  4. data/.yardopts +6 -0
  5. data/Appraisals +15 -4
  6. data/CONTRIBUTING.md +4 -1
  7. data/Gemfile +5 -3
  8. data/Gemfile.lock +102 -96
  9. data/NEWS.md +742 -311
  10. data/README.md +217 -339
  11. data/app/controllers/clearance/passwords_controller.rb +35 -21
  12. data/app/controllers/clearance/sessions_controller.rb +17 -4
  13. data/app/controllers/clearance/users_controller.rb +10 -4
  14. data/app/mailers/clearance_mailer.rb +2 -3
  15. data/app/views/clearance_mailer/change_password.html.erb +6 -3
  16. data/app/views/clearance_mailer/change_password.text.erb +5 -0
  17. data/app/views/layouts/application.html.erb +2 -2
  18. data/app/views/passwords/create.html.erb +1 -1
  19. data/app/views/passwords/edit.html.erb +2 -2
  20. data/app/views/passwords/new.html.erb +2 -2
  21. data/app/views/sessions/_form.html.erb +2 -2
  22. data/app/views/sessions/new.html.erb +1 -1
  23. data/app/views/users/new.html.erb +2 -2
  24. data/bin/setup +6 -2
  25. data/config/locales/clearance.en.yml +6 -0
  26. data/db/migrate/20110111224543_create_clearance_users.rb +1 -1
  27. data/gemfiles/{rails3.2.gemfile → rails32.gemfile} +4 -2
  28. data/gemfiles/{rails4.0.gemfile → rails40.gemfile} +6 -3
  29. data/gemfiles/{rails4.1.gemfile → rails41.gemfile} +6 -3
  30. data/gemfiles/{rails4.2.gemfile → rails42.gemfile} +6 -3
  31. data/gemfiles/rails50.gemfile +21 -0
  32. data/lib/clearance/authentication.rb +61 -2
  33. data/lib/clearance/authorization.rb +47 -4
  34. data/lib/clearance/back_door.rb +29 -6
  35. data/lib/clearance/configuration.rb +152 -15
  36. data/lib/clearance/constraints/signed_in.rb +21 -0
  37. data/lib/clearance/constraints/signed_out.rb +12 -0
  38. data/lib/clearance/constraints.rb +12 -0
  39. data/lib/clearance/controller.rb +13 -0
  40. data/lib/clearance/default_sign_in_guard.rb +17 -0
  41. data/lib/clearance/engine.rb +24 -4
  42. data/lib/clearance/password_strategies/bcrypt.rb +16 -21
  43. data/lib/clearance/password_strategies/bcrypt_migration_from_sha1.rb +19 -0
  44. data/lib/clearance/password_strategies/blowfish.rb +17 -0
  45. data/lib/clearance/password_strategies/sha1.rb +17 -0
  46. data/lib/clearance/password_strategies.rb +13 -0
  47. data/lib/clearance/rack_session.rb +13 -0
  48. data/lib/clearance/rspec.rb +15 -4
  49. data/lib/clearance/session.rb +46 -1
  50. data/lib/clearance/session_status.rb +7 -0
  51. data/lib/clearance/sign_in_guard.rb +65 -0
  52. data/lib/clearance/test_unit.rb +3 -3
  53. data/lib/clearance/testing/controller_helpers.rb +44 -0
  54. data/lib/clearance/testing/deny_access_matcher.rb +36 -2
  55. data/lib/clearance/testing/helpers.rb +9 -25
  56. data/lib/clearance/testing/view_helpers.rb +32 -0
  57. data/lib/clearance/token.rb +7 -0
  58. data/lib/clearance/user.rb +182 -4
  59. data/lib/clearance/version.rb +1 -1
  60. data/lib/clearance.rb +2 -0
  61. data/lib/generators/clearance/install/install_generator.rb +24 -5
  62. data/lib/generators/clearance/install/templates/clearance.rb +1 -0
  63. data/lib/generators/clearance/install/templates/db/migrate/add_clearance_to_users.rb +3 -3
  64. data/lib/generators/clearance/install/templates/db/migrate/create_users.rb +2 -2
  65. data/lib/generators/clearance/install/templates/user.rb.erb +3 -0
  66. data/lib/generators/clearance/routes/routes_generator.rb +23 -0
  67. data/lib/generators/clearance/routes/templates/routes.rb +7 -7
  68. data/lib/generators/clearance/specs/templates/features/clearance/user_signs_out_spec.rb.tt +1 -1
  69. data/lib/generators/clearance/specs/templates/features/clearance/visitor_resets_password_spec.rb.tt +12 -2
  70. data/lib/generators/clearance/specs/templates/features/clearance/visitor_signs_in_spec.rb.tt +1 -1
  71. data/lib/generators/clearance/specs/templates/features/clearance/visitor_signs_up_spec.rb.tt +1 -1
  72. data/lib/generators/clearance/specs/templates/features/clearance/visitor_updates_password_spec.rb.tt +1 -1
  73. data/spec/acceptance/clearance_installation_spec.rb +4 -1
  74. data/spec/app_templates/app/models/rails5/user.rb +5 -0
  75. data/spec/app_templates/config/initializers/clearance.rb +2 -0
  76. data/spec/app_templates/testapp/app/controllers/home_controller.rb +5 -1
  77. data/spec/app_templates/testapp/config/initializers/action_mailer.rb +1 -3
  78. data/spec/clearance/back_door_spec.rb +25 -6
  79. data/spec/clearance/controller_spec.rb +11 -0
  80. data/spec/clearance/rack_session_spec.rb +5 -5
  81. data/spec/clearance/session_spec.rb +2 -15
  82. data/spec/clearance/testing/{helpers_spec.rb → controller_helpers_spec.rb} +12 -12
  83. data/spec/clearance/testing/view_helpers_spec.rb +37 -0
  84. data/spec/configuration_spec.rb +94 -86
  85. data/spec/controllers/apis_controller_spec.rb +6 -2
  86. data/spec/controllers/forgeries_controller_spec.rb +6 -1
  87. data/spec/controllers/passwords_controller_spec.rb +17 -16
  88. data/spec/controllers/permissions_controller_spec.rb +13 -3
  89. data/spec/controllers/sessions_controller_spec.rb +4 -4
  90. data/spec/dummy/app/controllers/application_controller.rb +5 -1
  91. data/spec/dummy/application.rb +4 -0
  92. data/spec/generators/clearance/install/install_generator_spec.rb +29 -3
  93. data/spec/generators/clearance/routes/routes_generator_spec.rb +5 -1
  94. data/spec/generators/clearance/views/views_generator_spec.rb +11 -10
  95. data/spec/helpers/helper_helpers_spec.rb +10 -0
  96. data/spec/mailers/clearance_mailer_spec.rb +13 -19
  97. data/spec/password_strategies/bcrypt_migration_from_sha1_spec.rb +6 -0
  98. data/spec/password_strategies/blowfish_spec.rb +6 -0
  99. data/spec/password_strategies/sha1_spec.rb +6 -0
  100. data/spec/requests/csrf_rotation_spec.rb +33 -0
  101. data/spec/spec_helper.rb +11 -2
  102. data/spec/support/generator_spec_helpers.rb +13 -1
  103. data/spec/support/http_method_shim.rb +23 -0
  104. data/spec/user_spec.rb +9 -0
  105. data/spec/views/view_helpers_spec.rb +10 -0
  106. metadata +22 -9
  107. data/lib/generators/clearance/install/templates/user.rb +0 -3
@@ -1,10 +1,23 @@
1
1
  require 'active_support/deprecation'
2
2
 
3
3
  class Clearance::PasswordsController < Clearance::BaseController
4
- skip_before_filter :require_login, only: [:create, :edit, :new, :update]
5
- skip_before_filter :authorize, only: [:create, :edit, :new, :update]
6
- before_filter :forbid_missing_token, only: [:edit, :update]
7
- before_filter :forbid_non_existent_user, only: [:edit, :update]
4
+ if respond_to?(:before_action)
5
+ skip_before_action :require_login,
6
+ only: [:create, :edit, :new, :update],
7
+ raise: false
8
+ skip_before_action :authorize,
9
+ only: [:create, :edit, :new, :update],
10
+ raise: false
11
+ before_action :ensure_existing_user, only: [:edit, :update]
12
+ else
13
+ skip_before_filter :require_login,
14
+ only: [:create, :edit, :new, :update],
15
+ raise: false
16
+ skip_before_filter :authorize,
17
+ only: [:create, :edit, :new, :update],
18
+ raise: false
19
+ before_filter :ensure_existing_user, only: [:edit, :update]
20
+ end
8
21
 
9
22
  def create
10
23
  if user = find_user_for_create
@@ -16,7 +29,13 @@ class Clearance::PasswordsController < Clearance::BaseController
16
29
 
17
30
  def edit
18
31
  @user = find_user_for_edit
19
- render template: 'passwords/edit'
32
+
33
+ if params[:token]
34
+ session[:password_reset_token] = params[:token]
35
+ redirect_to url_for
36
+ else
37
+ render template: 'passwords/edit'
38
+ end
20
39
  end
21
40
 
22
41
  def new
@@ -29,6 +48,7 @@ class Clearance::PasswordsController < Clearance::BaseController
29
48
  if @user.update_password password_reset_params
30
49
  sign_in @user
31
50
  redirect_to url_after_update
51
+ session[:password_reset_token] = nil
32
52
  else
33
53
  flash_failure_after_update
34
54
  render template: 'passwords/edit'
@@ -40,7 +60,7 @@ class Clearance::PasswordsController < Clearance::BaseController
40
60
  def deliver_email(user)
41
61
  mail = ::ClearanceMailer.change_password(user)
42
62
 
43
- if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("4.2.0")
63
+ if mail.respond_to?(:deliver_later)
44
64
  mail.deliver_later
45
65
  else
46
66
  mail.deliver
@@ -58,9 +78,10 @@ class Clearance::PasswordsController < Clearance::BaseController
58
78
 
59
79
  def find_user_by_id_and_confirmation_token
60
80
  user_param = Clearance.configuration.user_id_parameter
81
+ token = session[:password_reset_token] || params[:token]
61
82
 
62
83
  Clearance.configuration.user_model.
63
- find_by_id_and_confirmation_token params[user_param], params[:token].to_s
84
+ find_by_id_and_confirmation_token params[user_param], token.to_s
64
85
  end
65
86
 
66
87
  def find_user_for_create
@@ -76,6 +97,13 @@ class Clearance::PasswordsController < Clearance::BaseController
76
97
  find_user_by_id_and_confirmation_token
77
98
  end
78
99
 
100
+ def ensure_existing_user
101
+ unless find_user_by_id_and_confirmation_token
102
+ flash_failure_when_forbidden
103
+ render template: "passwords/new"
104
+ end
105
+ end
106
+
79
107
  def flash_failure_when_forbidden
80
108
  flash.now[:notice] = translate(:forbidden,
81
109
  scope: [:clearance, :controllers, :passwords],
@@ -88,20 +116,6 @@ class Clearance::PasswordsController < Clearance::BaseController
88
116
  default: t('flashes.failure_after_update'))
89
117
  end
90
118
 
91
- def forbid_missing_token
92
- if params[:token].to_s.blank?
93
- flash_failure_when_forbidden
94
- render template: 'passwords/new'
95
- end
96
- end
97
-
98
- def forbid_non_existent_user
99
- unless find_user_by_id_and_confirmation_token
100
- flash_failure_when_forbidden
101
- render template: 'passwords/new'
102
- end
103
- end
104
-
105
119
  def url_after_create
106
120
  sign_in_url
107
121
  end
@@ -1,8 +1,21 @@
1
1
  class Clearance::SessionsController < Clearance::BaseController
2
- before_filter :redirect_signed_in_users, only: [:new]
3
- skip_before_filter :require_login, only: [:create, :new, :destroy]
4
- skip_before_filter :authorize, only: [:create, :new, :destroy]
5
- protect_from_forgery except: :create
2
+ if respond_to?(:before_action)
3
+ before_action :redirect_signed_in_users, only: [:new]
4
+ skip_before_action :require_login,
5
+ only: [:create, :new, :destroy],
6
+ raise: false
7
+ skip_before_action :authorize,
8
+ only: [:create, :new, :destroy],
9
+ raise: false
10
+ else
11
+ before_filter :redirect_signed_in_users, only: [:new]
12
+ skip_before_filter :require_login,
13
+ only: [:create, :new, :destroy],
14
+ raise: false
15
+ skip_before_filter :authorize,
16
+ only: [:create, :new, :destroy],
17
+ raise: false
18
+ end
6
19
 
7
20
  def create
8
21
  @user = authenticate(params)
@@ -1,7 +1,13 @@
1
1
  class Clearance::UsersController < Clearance::BaseController
2
- before_filter :redirect_signed_in_users, only: [:create, :new]
3
- skip_before_filter :require_login, only: [:create, :new]
4
- skip_before_filter :authorize, only: [:create, :new]
2
+ if respond_to?(:before_action)
3
+ before_action :redirect_signed_in_users, only: [:create, :new]
4
+ skip_before_action :require_login, only: [:create, :new], raise: false
5
+ skip_before_action :authorize, only: [:create, :new], raise: false
6
+ else
7
+ before_filter :redirect_signed_in_users, only: [:create, :new]
8
+ skip_before_filter :require_login, only: [:create, :new], raise: false
9
+ skip_before_filter :authorize, only: [:create, :new], raise: false
10
+ end
5
11
 
6
12
  def new
7
13
  @user = user_from_params
@@ -50,6 +56,6 @@ class Clearance::UsersController < Clearance::BaseController
50
56
  end
51
57
 
52
58
  def user_params
53
- params[:user] || Hash.new
59
+ params[Clearance.configuration.user_parameter] || Hash.new
54
60
  end
55
61
  end
@@ -6,9 +6,8 @@ class ClearanceMailer < ActionMailer::Base
6
6
  to: @user.email,
7
7
  subject: I18n.t(
8
8
  :change_password,
9
- scope: [:clearance, :models, :clearance_mailer],
10
- default: "Change your password"
11
- )
9
+ scope: [:clearance, :models, :clearance_mailer]
10
+ ),
12
11
  )
13
12
  end
14
13
  end
@@ -1,5 +1,8 @@
1
- <%= t(".opening") %>
1
+ <p><%= t(".opening") %></p>
2
2
 
3
- <%= edit_user_password_url(@user, token: @user.confirmation_token.html_safe) %>
3
+ <p>
4
+ <%= link_to t(".link_text", default: "Change my password"),
5
+ edit_user_password_url(@user, token: @user.confirmation_token.html_safe) %>
6
+ </p>
4
7
 
5
- <%= raw t(".closing") %>
8
+ <p><%= raw t(".closing") %></p>
@@ -0,0 +1,5 @@
1
+ <%= t(".opening") %>
2
+
3
+ <%= edit_user_password_url(@user, token: @user.confirmation_token.html_safe) %>
4
+
5
+ <%= raw t(".closing") %>
@@ -7,9 +7,9 @@
7
7
  <body>
8
8
  <div id="header">
9
9
  <% if signed_in? -%>
10
- <%= button_to t('.sign_out'), sign_out_path, method: :delete %>
10
+ <%= button_to t(".sign_out"), sign_out_path, method: :delete %>
11
11
  <% else -%>
12
- <%= link_to t('.sign_in'), sign_in_path %>
12
+ <%= link_to t(".sign_in"), sign_in_path %>
13
13
  <% end -%>
14
14
  </div>
15
15
 
@@ -1,3 +1,3 @@
1
1
  <div id="clearance" class="password-reset">
2
- <p><%= t '.description' %></p>
2
+ <p><%= t(".description") %></p>
3
3
  </div>
@@ -1,7 +1,7 @@
1
1
  <div id="clearance" class="password-reset">
2
- <h2><%= t '.title' %></h2>
2
+ <h2><%= t(".title") %></h2>
3
3
 
4
- <p><%= t '.description' %></p>
4
+ <p><%= t(".description") %></p>
5
5
 
6
6
  <%= form_for :password_reset,
7
7
  url: user_password_path(@user, token: @user.confirmation_token),
@@ -1,7 +1,7 @@
1
1
  <div id="clearance" class="password-reset">
2
- <h2><%= t '.title' %></h2>
2
+ <h2><%= t(".title") %></h2>
3
3
 
4
- <p><%= t '.description' %></p>
4
+ <p><%= t(".description") %></p>
5
5
 
6
6
  <%= form_for :password, url: passwords_path do |form| %>
7
7
  <div class="text-field">
@@ -15,8 +15,8 @@
15
15
 
16
16
  <div class="other-links">
17
17
  <% if Clearance.configuration.allow_sign_up? %>
18
- <%= link_to t('.sign_up'), sign_up_path %>
18
+ <%= link_to t(".sign_up"), sign_up_path %>
19
19
  <% end %>
20
- <%= link_to t('.forgot_password'), new_password_path %>
20
+ <%= link_to t(".forgot_password"), new_password_path %>
21
21
  </div>
22
22
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <div id="clearance" class="sign-in">
2
- <h2><%= t '.title' %></h2>
2
+ <h2><%= t(".title") %></h2>
3
3
 
4
4
  <%= render partial: '/sessions/form' %>
5
5
 
@@ -1,5 +1,5 @@
1
1
  <div id="clearance" class="sign-up">
2
- <h2><%= t('.title') %></h2>
2
+ <h2><%= t(".title") %></h2>
3
3
 
4
4
  <%= form_for @user do |form| %>
5
5
  <%= render partial: '/users/form', object: form %>
@@ -9,7 +9,7 @@
9
9
  </div>
10
10
 
11
11
  <div class="other-links">
12
- <%= link_to t('.sign_in'), sign_in_path %>
12
+ <%= link_to t(".sign_in"), sign_in_path %>
13
13
  </div>
14
14
  <% end %>
15
15
  </div>
data/bin/setup CHANGED
@@ -4,8 +4,12 @@ set -e
4
4
 
5
5
  # Install required gems, including Appraisal, which helps us test against
6
6
  # multiple Rails versions
7
- bundle install
8
- bundle exec appraisal install
7
+ gem install bundler --conservative
8
+ bundle check || bundle install
9
+
10
+ if [ -z "$CI" ]; then
11
+ bundle exec appraisal install
12
+ fi
9
13
 
10
14
  # Set up database for the application that Clearance tests against
11
15
  RAILS_ENV=test bundle exec rake dummy:db:reset
@@ -1,9 +1,14 @@
1
1
  ---
2
2
  en:
3
+ clearance:
4
+ models:
5
+ clearance_mailer:
6
+ change_password: Change your password
3
7
  clearance_mailer:
4
8
  change_password:
5
9
  closing: If you didn't request this, ignore this email. Your password has
6
10
  not been changed.
11
+ link_text: Change my password
7
12
  opening: "Someone, hopefully you, requested we send you a link to change
8
13
  your password:"
9
14
  flashes:
@@ -11,6 +16,7 @@ en:
11
16
  failure_after_update: Password can't be blank.
12
17
  failure_when_forbidden: Please double check the URL or try submitting
13
18
  the form again.
19
+ failure_when_not_signed_in: Please sign in to continue.
14
20
  helpers:
15
21
  label:
16
22
  password:
@@ -1,6 +1,6 @@
1
1
  class CreateClearanceUsers < ActiveRecord::Migration
2
2
  def self.up
3
- create_table :users do |t|
3
+ create_table :users do |t|
4
4
  t.timestamps null: false
5
5
  t.string :email, null: false
6
6
  t.string :encrypted_password, limit: 128, null: false
@@ -2,14 +2,16 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem "addressable", "~> 2.4.0"
5
6
  gem "appraisal", "~> 1.0"
6
7
  gem "ammeter"
7
8
  gem "bundler", "~> 1.3"
8
- gem "capybara", ">= 2.3"
9
+ gem "capybara", ">= 2.6.2"
9
10
  gem "database_cleaner", "~> 1.0"
10
11
  gem "factory_girl_rails", "~> 4.2"
12
+ gem "nokogiri", "~> 1.6.8"
11
13
  gem "rspec-rails", "~> 3.1"
12
- gem "shoulda-matchers", "~> 2.4"
14
+ gem "shoulda-matchers", "~> 2.8"
13
15
  gem "sqlite3", "~> 1.3"
14
16
  gem "timecop", "~> 0.6"
15
17
  gem "pry", :require => false
@@ -2,18 +2,21 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal", "~> 1.0"
5
+ gem "addressable", "~> 2.4.0"
6
+ gem "appraisal"
6
7
  gem "ammeter"
7
8
  gem "bundler", "~> 1.3"
8
- gem "capybara", ">= 2.3"
9
+ gem "capybara", ">= 2.6.2"
9
10
  gem "database_cleaner", "~> 1.0"
10
11
  gem "factory_girl_rails", "~> 4.2"
12
+ gem "nokogiri", "~> 1.6.8"
11
13
  gem "rspec-rails", "~> 3.1"
12
- gem "shoulda-matchers", "~> 2.4"
14
+ gem "shoulda-matchers", "~> 2.8"
13
15
  gem "sqlite3", "~> 1.3"
14
16
  gem "timecop", "~> 0.6"
15
17
  gem "pry", :require => false
16
18
  gem "rails", "~> 4.0.13"
17
19
  gem "test-unit"
20
+ gem "mime-types", "~> 2.99"
18
21
 
19
22
  gemspec :path => "../"
@@ -2,17 +2,20 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal", "~> 1.0"
5
+ gem "addressable", "~> 2.4.0"
6
+ gem "appraisal"
6
7
  gem "ammeter"
7
8
  gem "bundler", "~> 1.3"
8
- gem "capybara", ">= 2.3"
9
+ gem "capybara", ">= 2.6.2"
9
10
  gem "database_cleaner", "~> 1.0"
10
11
  gem "factory_girl_rails", "~> 4.2"
12
+ gem "nokogiri", "~> 1.6.8"
11
13
  gem "rspec-rails", "~> 3.1"
12
- gem "shoulda-matchers", "~> 2.4"
14
+ gem "shoulda-matchers", "~> 2.8"
13
15
  gem "sqlite3", "~> 1.3"
14
16
  gem "timecop", "~> 0.6"
15
17
  gem "pry", :require => false
16
18
  gem "rails", "~> 4.1.9"
19
+ gem "mime-types", "~> 2.99"
17
20
 
18
21
  gemspec :path => "../"
@@ -2,17 +2,20 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "appraisal", "~> 1.0"
5
+ gem "addressable", "~> 2.4.0"
6
+ gem "appraisal"
6
7
  gem "ammeter"
7
8
  gem "bundler", "~> 1.3"
8
- gem "capybara", ">= 2.3"
9
+ gem "capybara", ">= 2.6.2"
9
10
  gem "database_cleaner", "~> 1.0"
10
11
  gem "factory_girl_rails", "~> 4.2"
12
+ gem "nokogiri", "~> 1.6.8"
11
13
  gem "rspec-rails", "~> 3.1"
12
- gem "shoulda-matchers", "~> 2.4"
14
+ gem "shoulda-matchers", "~> 2.8"
13
15
  gem "sqlite3", "~> 1.3"
14
16
  gem "timecop", "~> 0.6"
15
17
  gem "pry", :require => false
16
18
  gem "rails", "~> 4.2.0"
19
+ gem "mime-types", "~> 2.99"
17
20
 
18
21
  gemspec :path => "../"
@@ -0,0 +1,21 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "addressable", "~> 2.4.0"
6
+ gem "appraisal"
7
+ gem "ammeter"
8
+ gem "bundler", "~> 1.3"
9
+ gem "capybara", ">= 2.6.2"
10
+ gem "database_cleaner", "~> 1.0"
11
+ gem "factory_girl_rails", "~> 4.2"
12
+ gem "nokogiri", "~> 1.6.8"
13
+ gem "rspec-rails", "~> 3.5.0.beta1"
14
+ gem "shoulda-matchers", "~> 2.8"
15
+ gem "sqlite3", "~> 1.3"
16
+ gem "timecop", "~> 0.6"
17
+ gem "pry", :require => false
18
+ gem "rails", "~> 5.0.0.beta3"
19
+ gem "rails-controller-testing"
20
+
21
+ gemspec :path => "../"
@@ -4,9 +4,11 @@ module Clearance
4
4
 
5
5
  included do
6
6
  helper_method :current_user, :signed_in?, :signed_out?
7
- hide_action(
7
+ private(
8
+ :authenticate,
8
9
  :current_user,
9
10
  :current_user=,
11
+ :handle_unverified_request,
10
12
  :sign_in,
11
13
  :sign_out,
12
14
  :signed_in?,
@@ -14,40 +16,96 @@ module Clearance
14
16
  )
15
17
  end
16
18
 
19
+ # Authenticate a user with a provided email and password
20
+ # @param [ActionController::Parameters] params The parameters from the
21
+ # sign in form. `params[:session][:email]` and
22
+ # `params[:session][:password]` are required.
23
+ # @return [User, nil] The user or nil if authentication fails.
17
24
  def authenticate(params)
18
25
  Clearance.configuration.user_model.authenticate(
19
26
  params[:session][:email], params[:session][:password]
20
27
  )
21
28
  end
22
29
 
30
+ # Get the user from the current clearance session. Exposed as a
31
+ # `helper_method`, making it visible to views. Prefer {#signed_in?} or
32
+ # {#signed_out?} if you only want to check for the presence of a current
33
+ # user rather than access the actual user.
34
+ #
35
+ # @return [User, nil] The user if one is signed in or nil otherwise.
23
36
  def current_user
24
37
  clearance_session.current_user
25
38
  end
26
39
 
40
+ # @deprecated Use the {#sign_in} method instead.
27
41
  def current_user=(user)
28
42
  warn "#{Kernel.caller.first}: [DEPRECATION] " +
29
43
  'Assigning the current_user has been deprecated. Use the sign_in method instead.'
30
44
  clearance_session.sign_in user
31
45
  end
32
46
 
47
+ # Sign in the provided user.
48
+ # @param [User] user
49
+ #
50
+ # Signing in will run the stack of {Configuration#sign_in_guards}.
51
+ #
52
+ # You can provide a block to this method to handle the result of that stack.
53
+ # Your block will receive either a {SuccessStatus} or {FailureStatus}
54
+ #
55
+ # sign_in(user) do |status|
56
+ # if status.success?
57
+ # # ...
58
+ # else
59
+ # # ...
60
+ # end
61
+ # end
62
+ #
63
+ # For an example of how clearance uses this internally, see
64
+ # {SessionsController#create}.
65
+ #
66
+ # Signing in will also regenerate the CSRF token for the current session,
67
+ # provided {Configuration#rotate_csrf_token_on_sign_in} is set.
33
68
  def sign_in(user, &block)
34
- clearance_session.sign_in user, &block
69
+ clearance_session.sign_in(user, &block)
70
+
71
+ if signed_in? && Clearance.configuration.rotate_csrf_on_sign_in?
72
+ session.delete(:_csrf_token)
73
+ form_authenticity_token
74
+ end
35
75
  end
36
76
 
77
+ # Destroy the current user's Clearance session.
78
+ # See {Session#sign_out} for specifics.
37
79
  def sign_out
38
80
  clearance_session.sign_out
39
81
  end
40
82
 
83
+ # True if there is a currently-signed-in user. Exposed as a `helper_method`,
84
+ # making it available to views.
85
+ #
86
+ # Using `signed_in?` is preferable to checking {#current_user} against nil
87
+ # as it will allow you to introduce a null user object more simply at a
88
+ # later date.
89
+ #
90
+ # @return [Boolean]
41
91
  def signed_in?
42
92
  clearance_session.signed_in?
43
93
  end
44
94
 
95
+ # True if there is no currently-signed-in user. Exposed as a
96
+ # `helper_method`, making it available to views.
97
+ #
98
+ # Usings `signed_out?` is preferable to checking for presence of
99
+ # {#current_user} as it will allow you to introduce a null user object more
100
+ # simply at a later date.
45
101
  def signed_out?
46
102
  !signed_in?
47
103
  end
48
104
 
49
105
  # CSRF protection in Rails >= 3.0.4
106
+ #
50
107
  # http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails
108
+ # @private
51
109
  def handle_unverified_request
52
110
  super
53
111
  sign_out
@@ -55,6 +113,7 @@ module Clearance
55
113
 
56
114
  protected
57
115
 
116
+ # @api private
58
117
  def clearance_session
59
118
  request.env[:clearance]
60
119
  end
@@ -3,23 +3,52 @@ module Clearance
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- hide_action :authorize, :deny_access, :require_login
6
+ private :authorize, :deny_access, :require_login
7
7
  end
8
8
 
9
+ # Use as a `before_action` to require a user be signed in to proceed.
10
+ # {Authentication#signed_in?} is used to determine if there is a signed in
11
+ # user or not.
12
+ #
13
+ # class PostsController < ApplicationController
14
+ # before_action :require_login
15
+ #
16
+ # def index
17
+ # # ...
18
+ # end
19
+ # end
9
20
  def require_login
10
21
  unless signed_in?
11
- deny_access
22
+ deny_access(I18n.t("flashes.failure_when_not_signed_in"))
12
23
  end
13
24
  end
14
25
 
26
+ # @deprecated use {#require_login}
15
27
  def authorize
16
- warn "[DEPRECATION] Clearance's `authorize` before_filter is " +
28
+ warn "[DEPRECATION] Clearance's `authorize` before_action is " +
17
29
  "deprecated. Use `require_login` instead. Be sure to update any " +
18
- "instances of `skip_before_filter :authorize` or " +
30
+ "instances of `skip_before_action :authorize` or " +
19
31
  "`skip_before_action :authorize` as well"
20
32
  require_login
21
33
  end
22
34
 
35
+ # Responds to unauthorized requests in a manner fitting the request format.
36
+ # `js`, `json`, and `xml` requests will receive a 401 with no body. All
37
+ # other formats will be redirected appropriately and can optionally have the
38
+ # flash message set.
39
+ #
40
+ # When redirecting, the originally requested url will be stored in the
41
+ # session (`session[:return_to]`), allowing it to be used as a redirect url
42
+ # once the user has successfully signed in.
43
+ #
44
+ # If there is a signed in user, the request will be redirected according to
45
+ # the value returned from {#url_after_denied_access_when_signed_in}.
46
+ #
47
+ # If there is no signed in user, the request will be redirected according to
48
+ # the value returned from {#url_after_denied_access_when_signed_out}.
49
+ # For the exact redirect behavior, see {#redirect_request}.
50
+ #
51
+ # @param [String] flash_message
23
52
  def deny_access(flash_message = nil)
24
53
  respond_to do |format|
25
54
  format.any(:js, :json, :xml) { head :unauthorized }
@@ -29,6 +58,7 @@ module Clearance
29
58
 
30
59
  protected
31
60
 
61
+ # @api private
32
62
  def redirect_request(flash_message)
33
63
  store_location
34
64
 
@@ -43,21 +73,25 @@ module Clearance
43
73
  end
44
74
  end
45
75
 
76
+ # @api private
46
77
  def clear_return_to
47
78
  session[:return_to] = nil
48
79
  end
49
80
 
81
+ # @api private
50
82
  def store_location
51
83
  if request.get?
52
84
  session[:return_to] = request.original_fullpath
53
85
  end
54
86
  end
55
87
 
88
+ # @api private
56
89
  def redirect_back_or(default)
57
90
  redirect_to(return_to || default)
58
91
  clear_return_to
59
92
  end
60
93
 
94
+ # @api private
61
95
  def return_to
62
96
  if return_to_url
63
97
  uri = URI.parse(return_to_url)
@@ -65,14 +99,23 @@ module Clearance
65
99
  end
66
100
  end
67
101
 
102
+ # @api private
68
103
  def return_to_url
69
104
  session[:return_to]
70
105
  end
71
106
 
107
+ # Used as the redirect location when {#deny_access} is called and there is a
108
+ # currently signed in user.
109
+ #
110
+ # @return [String]
72
111
  def url_after_denied_access_when_signed_in
73
112
  Clearance.configuration.redirect_url
74
113
  end
75
114
 
115
+ # Used as the redirect location when {#deny_access} is called and there is
116
+ # no currently signed in user.
117
+ #
118
+ # @return [String]
76
119
  def url_after_denied_access_when_signed_out
77
120
  sign_in_url
78
121
  end