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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +25 -6
- data/.yardopts +6 -0
- data/Appraisals +15 -4
- data/CONTRIBUTING.md +4 -1
- data/Gemfile +5 -3
- data/Gemfile.lock +102 -96
- data/NEWS.md +742 -311
- data/README.md +217 -339
- data/app/controllers/clearance/passwords_controller.rb +35 -21
- data/app/controllers/clearance/sessions_controller.rb +17 -4
- data/app/controllers/clearance/users_controller.rb +10 -4
- data/app/mailers/clearance_mailer.rb +2 -3
- data/app/views/clearance_mailer/change_password.html.erb +6 -3
- data/app/views/clearance_mailer/change_password.text.erb +5 -0
- data/app/views/layouts/application.html.erb +2 -2
- data/app/views/passwords/create.html.erb +1 -1
- data/app/views/passwords/edit.html.erb +2 -2
- data/app/views/passwords/new.html.erb +2 -2
- data/app/views/sessions/_form.html.erb +2 -2
- data/app/views/sessions/new.html.erb +1 -1
- data/app/views/users/new.html.erb +2 -2
- data/bin/setup +6 -2
- data/config/locales/clearance.en.yml +6 -0
- data/db/migrate/20110111224543_create_clearance_users.rb +1 -1
- data/gemfiles/{rails3.2.gemfile → rails32.gemfile} +4 -2
- data/gemfiles/{rails4.0.gemfile → rails40.gemfile} +6 -3
- data/gemfiles/{rails4.1.gemfile → rails41.gemfile} +6 -3
- data/gemfiles/{rails4.2.gemfile → rails42.gemfile} +6 -3
- data/gemfiles/rails50.gemfile +21 -0
- data/lib/clearance/authentication.rb +61 -2
- data/lib/clearance/authorization.rb +47 -4
- data/lib/clearance/back_door.rb +29 -6
- data/lib/clearance/configuration.rb +152 -15
- data/lib/clearance/constraints/signed_in.rb +21 -0
- data/lib/clearance/constraints/signed_out.rb +12 -0
- data/lib/clearance/constraints.rb +12 -0
- data/lib/clearance/controller.rb +13 -0
- data/lib/clearance/default_sign_in_guard.rb +17 -0
- data/lib/clearance/engine.rb +24 -4
- data/lib/clearance/password_strategies/bcrypt.rb +16 -21
- data/lib/clearance/password_strategies/bcrypt_migration_from_sha1.rb +19 -0
- data/lib/clearance/password_strategies/blowfish.rb +17 -0
- data/lib/clearance/password_strategies/sha1.rb +17 -0
- data/lib/clearance/password_strategies.rb +13 -0
- data/lib/clearance/rack_session.rb +13 -0
- data/lib/clearance/rspec.rb +15 -4
- data/lib/clearance/session.rb +46 -1
- data/lib/clearance/session_status.rb +7 -0
- data/lib/clearance/sign_in_guard.rb +65 -0
- data/lib/clearance/test_unit.rb +3 -3
- data/lib/clearance/testing/controller_helpers.rb +44 -0
- data/lib/clearance/testing/deny_access_matcher.rb +36 -2
- data/lib/clearance/testing/helpers.rb +9 -25
- data/lib/clearance/testing/view_helpers.rb +32 -0
- data/lib/clearance/token.rb +7 -0
- data/lib/clearance/user.rb +182 -4
- data/lib/clearance/version.rb +1 -1
- data/lib/clearance.rb +2 -0
- data/lib/generators/clearance/install/install_generator.rb +24 -5
- data/lib/generators/clearance/install/templates/clearance.rb +1 -0
- data/lib/generators/clearance/install/templates/db/migrate/add_clearance_to_users.rb +3 -3
- data/lib/generators/clearance/install/templates/db/migrate/create_users.rb +2 -2
- data/lib/generators/clearance/install/templates/user.rb.erb +3 -0
- data/lib/generators/clearance/routes/routes_generator.rb +23 -0
- data/lib/generators/clearance/routes/templates/routes.rb +7 -7
- data/lib/generators/clearance/specs/templates/features/clearance/user_signs_out_spec.rb.tt +1 -1
- data/lib/generators/clearance/specs/templates/features/clearance/visitor_resets_password_spec.rb.tt +12 -2
- data/lib/generators/clearance/specs/templates/features/clearance/visitor_signs_in_spec.rb.tt +1 -1
- data/lib/generators/clearance/specs/templates/features/clearance/visitor_signs_up_spec.rb.tt +1 -1
- data/lib/generators/clearance/specs/templates/features/clearance/visitor_updates_password_spec.rb.tt +1 -1
- data/spec/acceptance/clearance_installation_spec.rb +4 -1
- data/spec/app_templates/app/models/rails5/user.rb +5 -0
- data/spec/app_templates/config/initializers/clearance.rb +2 -0
- data/spec/app_templates/testapp/app/controllers/home_controller.rb +5 -1
- data/spec/app_templates/testapp/config/initializers/action_mailer.rb +1 -3
- data/spec/clearance/back_door_spec.rb +25 -6
- data/spec/clearance/controller_spec.rb +11 -0
- data/spec/clearance/rack_session_spec.rb +5 -5
- data/spec/clearance/session_spec.rb +2 -15
- data/spec/clearance/testing/{helpers_spec.rb → controller_helpers_spec.rb} +12 -12
- data/spec/clearance/testing/view_helpers_spec.rb +37 -0
- data/spec/configuration_spec.rb +94 -86
- data/spec/controllers/apis_controller_spec.rb +6 -2
- data/spec/controllers/forgeries_controller_spec.rb +6 -1
- data/spec/controllers/passwords_controller_spec.rb +17 -16
- data/spec/controllers/permissions_controller_spec.rb +13 -3
- data/spec/controllers/sessions_controller_spec.rb +4 -4
- data/spec/dummy/app/controllers/application_controller.rb +5 -1
- data/spec/dummy/application.rb +4 -0
- data/spec/generators/clearance/install/install_generator_spec.rb +29 -3
- data/spec/generators/clearance/routes/routes_generator_spec.rb +5 -1
- data/spec/generators/clearance/views/views_generator_spec.rb +11 -10
- data/spec/helpers/helper_helpers_spec.rb +10 -0
- data/spec/mailers/clearance_mailer_spec.rb +13 -19
- data/spec/password_strategies/bcrypt_migration_from_sha1_spec.rb +6 -0
- data/spec/password_strategies/blowfish_spec.rb +6 -0
- data/spec/password_strategies/sha1_spec.rb +6 -0
- data/spec/requests/csrf_rotation_spec.rb +33 -0
- data/spec/spec_helper.rb +11 -2
- data/spec/support/generator_spec_helpers.rb +13 -1
- data/spec/support/http_method_shim.rb +23 -0
- data/spec/user_spec.rb +9 -0
- data/spec/views/view_helpers_spec.rb +10 -0
- metadata +22 -9
- data/lib/generators/clearance/install/templates/user.rb +0 -3
@@ -1,4 +1,17 @@
|
|
1
1
|
module Clearance
|
2
|
+
# Control how users are authenticated and how passwords are stored.
|
3
|
+
#
|
4
|
+
# The default password strategy is {Clearance::PasswordStrategies::BCrypt},
|
5
|
+
# but this can be overridden in {Clearance::Configuration}.
|
6
|
+
#
|
7
|
+
# You can supply your own password strategy by implementing a module that
|
8
|
+
# responds to the proper interface methods. Once this module is configured as
|
9
|
+
# your password strategy, Clearance will mix it into your Clearance User
|
10
|
+
# class. Thus, your module can access any methods or attributes on User.
|
11
|
+
#
|
12
|
+
# Password strategies need to respond to `authenticated?(password)` and
|
13
|
+
# `password=(new_password)`. For an example of how to implement these methods,
|
14
|
+
# see {Clearance::PasswordStrategies::BCrypt}.
|
2
15
|
module PasswordStrategies
|
3
16
|
autoload :BCrypt, 'clearance/password_strategies/bcrypt'
|
4
17
|
autoload :BCryptMigrationFromSHA1,
|
@@ -1,9 +1,22 @@
|
|
1
1
|
module Clearance
|
2
|
+
# Rack middleware that manages the Clearance {Session}. This middleware is
|
3
|
+
# automatically mounted by the Clearance {Engine}.
|
4
|
+
#
|
5
|
+
# * maintains the session cookie specified by your {Configuration}.
|
6
|
+
# * exposes previously cookied sessions to Clearance and your app at
|
7
|
+
# `request.env[:clearance]`, which {Authentication#current_user} pulls the
|
8
|
+
# user from.
|
9
|
+
#
|
10
|
+
# @see Session
|
11
|
+
# @see Configuration#cookie_name
|
12
|
+
#
|
2
13
|
class RackSession
|
3
14
|
def initialize(app)
|
4
15
|
@app = app
|
5
16
|
end
|
6
17
|
|
18
|
+
# Reads previously existing sessions from a cookie and maintains the cookie
|
19
|
+
# on each response.
|
7
20
|
def call(env)
|
8
21
|
session = Clearance::Session.new(env)
|
9
22
|
env[:clearance] = session
|
data/lib/clearance/rspec.rb
CHANGED
@@ -1,8 +1,19 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "rspec/rails"
|
2
|
+
require "clearance/testing/deny_access_matcher"
|
3
|
+
require "clearance/testing/controller_helpers"
|
4
|
+
require "clearance/testing/view_helpers"
|
4
5
|
|
5
6
|
RSpec.configure do |config|
|
6
7
|
config.include Clearance::Testing::Matchers, type: :controller
|
7
|
-
config.include Clearance::Testing::
|
8
|
+
config.include Clearance::Testing::ControllerHelpers, type: :controller
|
9
|
+
config.include Clearance::Testing::ViewHelpers, type: :view
|
10
|
+
config.include Clearance::Testing::ViewHelpers, type: :helper
|
11
|
+
|
12
|
+
config.before(:each, type: :view) do
|
13
|
+
view.extend Clearance::Testing::ViewHelpers::CurrentUser
|
14
|
+
end
|
15
|
+
|
16
|
+
config.before(:each, type: :helper) do
|
17
|
+
view.extend Clearance::Testing::ViewHelpers::CurrentUser
|
18
|
+
end
|
8
19
|
end
|
data/lib/clearance/session.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
require 'clearance/default_sign_in_guard'
|
2
2
|
|
3
3
|
module Clearance
|
4
|
+
# Represents a clearance session, ultimately persisted in
|
5
|
+
# `request.env[:clearance]` by {RackSession}.
|
4
6
|
class Session
|
7
|
+
# @param env The current rack environment
|
5
8
|
def initialize(env)
|
6
9
|
@env = env
|
7
10
|
@current_user = nil
|
8
11
|
@cookies = nil
|
9
12
|
end
|
10
13
|
|
14
|
+
# Called by {RackSession} to add the Clearance session cookie to a response.
|
15
|
+
#
|
16
|
+
# @return [void]
|
11
17
|
def add_cookie_to_headers(headers)
|
12
18
|
if cookie_value[:value].present?
|
13
19
|
Rack::Utils.set_cookie_header!(
|
@@ -18,6 +24,9 @@ module Clearance
|
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
27
|
+
# The current user represented by this session.
|
28
|
+
#
|
29
|
+
# @return [User, nil]
|
21
30
|
def current_user
|
22
31
|
if remember_token.present?
|
23
32
|
@current_user ||= user_from_remember_token(remember_token)
|
@@ -26,6 +35,20 @@ module Clearance
|
|
26
35
|
@current_user
|
27
36
|
end
|
28
37
|
|
38
|
+
# Sign the provided user in, if approved by the configured sign in guards.
|
39
|
+
# If the sign in guard stack returns {SuccessStatus}, the {#current_user}
|
40
|
+
# will be set and then remember token cookie will be set to the user's
|
41
|
+
# remember token. If the stack returns {FailureStatus}, {#current_user} will
|
42
|
+
# be nil.
|
43
|
+
#
|
44
|
+
# In either event, the resulting status will be yielded to a provided block,
|
45
|
+
# if provided. See {SessionsController#create} for an example of how this
|
46
|
+
# can be used.
|
47
|
+
#
|
48
|
+
# @param [User] user
|
49
|
+
# @yieldparam [SuccessStatus,FailureStatus] status Result of the sign in
|
50
|
+
# operation.
|
51
|
+
# @return [void]
|
29
52
|
def sign_in(user, &block)
|
30
53
|
@current_user = user
|
31
54
|
status = run_sign_in_stack
|
@@ -41,6 +64,13 @@ module Clearance
|
|
41
64
|
end
|
42
65
|
end
|
43
66
|
|
67
|
+
# Invalidates the users remember token and removes the remember token cookie
|
68
|
+
# from the store. The invalidation of the remember token causes any other
|
69
|
+
# sessions that are signed in from other locations to also be invalidated on
|
70
|
+
# their next request. This is because all Clearance sessions for a given
|
71
|
+
# user share a remember token.
|
72
|
+
#
|
73
|
+
# @return [void]
|
44
74
|
def sign_out
|
45
75
|
if signed_in?
|
46
76
|
current_user.reset_remember_token!
|
@@ -50,24 +80,33 @@ module Clearance
|
|
50
80
|
cookies.delete remember_token_cookie
|
51
81
|
end
|
52
82
|
|
83
|
+
# True if {#current_user} is set.
|
84
|
+
#
|
85
|
+
# @return [Boolean]
|
53
86
|
def signed_in?
|
54
87
|
current_user.present?
|
55
88
|
end
|
56
89
|
|
90
|
+
# True if {#current_user} is not set
|
91
|
+
#
|
92
|
+
# @return [Boolean]
|
57
93
|
def signed_out?
|
58
94
|
! signed_in?
|
59
95
|
end
|
60
96
|
|
61
97
|
private
|
62
98
|
|
99
|
+
# @api private
|
63
100
|
def cookies
|
64
|
-
@cookies ||=
|
101
|
+
@cookies ||= ActionDispatch::Request.new(@env).cookie_jar
|
65
102
|
end
|
66
103
|
|
104
|
+
# @api private
|
67
105
|
def remember_token
|
68
106
|
cookies[remember_token_cookie]
|
69
107
|
end
|
70
108
|
|
109
|
+
# @api private
|
71
110
|
def remember_token_expires
|
72
111
|
if expires_configuration.arity == 1
|
73
112
|
expires_configuration.call(cookies)
|
@@ -80,23 +119,28 @@ module Clearance
|
|
80
119
|
end
|
81
120
|
end
|
82
121
|
|
122
|
+
# @api private
|
83
123
|
def remember_token_cookie
|
84
124
|
Clearance.configuration.cookie_name.freeze
|
85
125
|
end
|
86
126
|
|
127
|
+
# @api private
|
87
128
|
def expires_configuration
|
88
129
|
Clearance.configuration.cookie_expiration
|
89
130
|
end
|
90
131
|
|
132
|
+
# @api private
|
91
133
|
def user_from_remember_token(token)
|
92
134
|
Clearance.configuration.user_model.where(remember_token: token).first
|
93
135
|
end
|
94
136
|
|
137
|
+
# @api private
|
95
138
|
def run_sign_in_stack
|
96
139
|
@stack ||= initialize_sign_in_guard_stack
|
97
140
|
@stack.call
|
98
141
|
end
|
99
142
|
|
143
|
+
# @api private
|
100
144
|
def initialize_sign_in_guard_stack
|
101
145
|
default_guard = DefaultSignInGuard.new(self)
|
102
146
|
guards = Clearance.configuration.sign_in_guards
|
@@ -106,6 +150,7 @@ module Clearance
|
|
106
150
|
end
|
107
151
|
end
|
108
152
|
|
153
|
+
# @api private
|
109
154
|
def cookie_value
|
110
155
|
value = {
|
111
156
|
expires: remember_token_expires,
|
@@ -1,17 +1,24 @@
|
|
1
1
|
module Clearance
|
2
|
+
# Indicates a user was successfully signed in, passing all {SignInGuard}s.
|
2
3
|
class SuccessStatus
|
4
|
+
# Is true, indicating that the sign in was successful.
|
3
5
|
def success?
|
4
6
|
true
|
5
7
|
end
|
6
8
|
end
|
7
9
|
|
10
|
+
# Indicates a failure in the {SignInGuard} stack which prevented successful
|
11
|
+
# sign in.
|
8
12
|
class FailureStatus
|
13
|
+
# The reason the sign in failed.
|
9
14
|
attr_reader :failure_message
|
10
15
|
|
16
|
+
# @param [String] failure_message The reason the sign in failed.
|
11
17
|
def initialize(failure_message)
|
12
18
|
@failure_message = failure_message
|
13
19
|
end
|
14
20
|
|
21
|
+
# Is false, indicating that the sign in was unsuccessful.
|
15
22
|
def success?
|
16
23
|
false
|
17
24
|
end
|
@@ -1,20 +1,83 @@
|
|
1
1
|
require 'clearance/session_status'
|
2
2
|
|
3
3
|
module Clearance
|
4
|
+
# The base class for {DefaultSignInGuard} and all custom sign in guards.
|
5
|
+
#
|
6
|
+
# Sign in guards provide you with fine-grained control over the process of
|
7
|
+
# signing in a user. Each guard is run in order and can do one of the
|
8
|
+
# following:
|
9
|
+
#
|
10
|
+
# * Fail the sign in process
|
11
|
+
# * Call the next guard in the stack
|
12
|
+
# * Short circuit all remaining guards, declaring sign in successfull.
|
13
|
+
#
|
14
|
+
# Sign In Guards could be used, for instance, to require that a user confirm
|
15
|
+
# their email address before being allowed to sign in.
|
16
|
+
#
|
17
|
+
# # in config/initializers/clearance.rb
|
18
|
+
# Clearance.configure do |config|
|
19
|
+
# config.sign_in_guards = [ConfirmationGuard]
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # in lib/guards/confirmation_guard.rb
|
23
|
+
# class ConfirmationGuard < Clearance::SignInGuard
|
24
|
+
# def call
|
25
|
+
# if signed_in? && current_user.email_confirmed?
|
26
|
+
# next_guard
|
27
|
+
# else
|
28
|
+
# failure("You must confirm your email address.")
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Calling `success` or `failure` in any guard short circuits all of the
|
34
|
+
# remaining guards in the stack. In most cases, you will want to either call
|
35
|
+
# `failure` or `next_guard`. The {DefaultSignInGuard} will always be the final
|
36
|
+
# guard called and will handle calling `success` if appropriate.
|
37
|
+
#
|
38
|
+
# The stack is designed such that calling `call` will eventually return
|
39
|
+
# {SuccessStatus} or {FailureStatus}, thus halting the chain.
|
4
40
|
class SignInGuard
|
41
|
+
# Creates an instance of a sign in guard.
|
42
|
+
#
|
43
|
+
# This is called by {Session} automatically using the array of guards
|
44
|
+
# configured in {Configuration#sign_in_guards} and the {DefaultSignInGuard}.
|
45
|
+
# There is no reason for users of Clearance to concern themselves with the
|
46
|
+
# initialization of each guard or the stack as a whole.
|
47
|
+
#
|
48
|
+
# @param [Session] session The current clearance session
|
49
|
+
# @param [[SignInGuard]] stack The sign in guards that come after this
|
50
|
+
# guard in the stack
|
5
51
|
def initialize(session, stack = [])
|
6
52
|
@session = session
|
7
53
|
@stack = stack
|
8
54
|
end
|
9
55
|
|
56
|
+
# Indicates the entire sign in operation is successful and that no further
|
57
|
+
# guards should be run.
|
58
|
+
#
|
59
|
+
# In most cases your guards will want to delegate this responsibility to the
|
60
|
+
# {DefaultSignInGuard}, allowing the entire stack to execute. In that case,
|
61
|
+
# your custom guard would likely want to call `next_guard` instead.
|
62
|
+
#
|
63
|
+
# @return [SuccessStatus]
|
10
64
|
def success
|
11
65
|
SuccessStatus.new
|
12
66
|
end
|
13
67
|
|
68
|
+
# Indicates this guard failed, and the entire sign in process should fail as
|
69
|
+
# a result.
|
70
|
+
#
|
71
|
+
# @param [String] message The reason the guard failed.
|
72
|
+
# @return [FailureStatus]
|
14
73
|
def failure(message)
|
15
74
|
FailureStatus.new(message)
|
16
75
|
end
|
17
76
|
|
77
|
+
# Passes off responsibility for determining success or failure to the next
|
78
|
+
# guard in the stack.
|
79
|
+
#
|
80
|
+
# @return [SuccessStatus, FailureStatus]
|
18
81
|
def next_guard
|
19
82
|
stack.call
|
20
83
|
end
|
@@ -23,10 +86,12 @@ module Clearance
|
|
23
86
|
|
24
87
|
attr_reader :stack, :session
|
25
88
|
|
89
|
+
# True if there is a currently a user stored in the clearance environment.
|
26
90
|
def signed_in?
|
27
91
|
session.signed_in?
|
28
92
|
end
|
29
93
|
|
94
|
+
# The user currently stored in the clearance environment.
|
30
95
|
def current_user
|
31
96
|
session.current_user
|
32
97
|
end
|
data/lib/clearance/test_unit.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "clearance/testing/deny_access_matcher"
|
2
|
+
require "clearance/testing/controller_helpers"
|
3
3
|
|
4
4
|
ActionController::TestCase.extend Clearance::Testing::Matchers
|
5
5
|
|
6
6
|
class ActionController::TestCase
|
7
|
-
include Clearance::Testing::
|
7
|
+
include Clearance::Testing::ControllerHelpers
|
8
8
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Clearance
|
2
|
+
module Testing
|
3
|
+
# Provides helpers to your controller specs.
|
4
|
+
# These are typically used in tests by requiring `clearance/rspec` or
|
5
|
+
# `clearance/test_unit` as appropriate in your `rails_helper.rb` or
|
6
|
+
# `test_helper.rb` files.
|
7
|
+
module ControllerHelpers
|
8
|
+
# @api private
|
9
|
+
def setup_controller_request_and_response
|
10
|
+
super
|
11
|
+
@request.env[:clearance] = Clearance::Session.new(@request.env)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Signs in a user that is created using FactoryGirl.
|
15
|
+
# The factory name is derrived from your `user_class` Clearance
|
16
|
+
# configuration.
|
17
|
+
#
|
18
|
+
# @raise [RuntimeError] if FactoryGirl is not defined.
|
19
|
+
def sign_in
|
20
|
+
unless defined?(FactoryGirl)
|
21
|
+
raise("Clearance's `sign_in` helper requires factory_girl")
|
22
|
+
end
|
23
|
+
|
24
|
+
factory = Clearance.configuration.user_model.to_s.underscore.to_sym
|
25
|
+
sign_in_as FactoryGirl.create(factory)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Signs in the provided user.
|
29
|
+
#
|
30
|
+
# @return user
|
31
|
+
def sign_in_as(user)
|
32
|
+
@request.env[:clearance].sign_in(user)
|
33
|
+
user
|
34
|
+
end
|
35
|
+
|
36
|
+
# Signs out a user that may be signed in.
|
37
|
+
#
|
38
|
+
# @return [void]
|
39
|
+
def sign_out
|
40
|
+
@request.env[:clearance].sign_out
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,10 +1,40 @@
|
|
1
1
|
module Clearance
|
2
2
|
module Testing
|
3
|
+
# Provides matchers to be used in your controller specs.
|
4
|
+
# These are typically exposed to your controller specs by
|
5
|
+
# requiring `clearance/rspec` or `clearance/test_unit` as
|
6
|
+
# appropriate in your `rails_helper.rb` or `test_helper.rb`
|
7
|
+
# files.
|
3
8
|
module Matchers
|
9
|
+
# The `deny_access` matcher is used to assert that a
|
10
|
+
# request is denied access by clearance.
|
11
|
+
# @option opts [String] :flash The expected flash notice message. Defaults
|
12
|
+
# to nil, which means the flash will not be checked.
|
13
|
+
# @option opts [String] :redirect The expected redirect url. Defaults to
|
14
|
+
# `'/'` if signed in or the `sign_in_url` if signed out.
|
15
|
+
#
|
16
|
+
# class PostsController < ActionController::Base
|
17
|
+
# before_action :require_login
|
18
|
+
#
|
19
|
+
# def index
|
20
|
+
# @posts = Post.all
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# describe PostsController do
|
25
|
+
# describe "#index" do
|
26
|
+
# it "denies access to users not signed in" do
|
27
|
+
# get :index
|
28
|
+
#
|
29
|
+
# expect(controller).to deny_access
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# end
|
4
33
|
def deny_access(opts = {})
|
5
34
|
DenyAccessMatcher.new(self, opts)
|
6
35
|
end
|
7
36
|
|
37
|
+
# @api private
|
8
38
|
class DenyAccessMatcher
|
9
39
|
attr_reader :failure_message, :failure_message_when_negated
|
10
40
|
|
@@ -37,13 +67,17 @@ module Clearance
|
|
37
67
|
private
|
38
68
|
|
39
69
|
def denied_access_url
|
40
|
-
if
|
41
|
-
|
70
|
+
if clearance_session.signed_in?
|
71
|
+
Clearance.configuration.redirect_url
|
42
72
|
else
|
43
73
|
@controller.sign_in_url
|
44
74
|
end
|
45
75
|
end
|
46
76
|
|
77
|
+
def clearance_session
|
78
|
+
@controller.request.env[:clearance]
|
79
|
+
end
|
80
|
+
|
47
81
|
def flash_notice
|
48
82
|
@controller.flash[:notice]
|
49
83
|
end
|
@@ -1,31 +1,15 @@
|
|
1
|
+
require "clerance/testing/controller_helpers"
|
2
|
+
|
1
3
|
module Clearance
|
2
4
|
module Testing
|
5
|
+
# @deprecated Use Clearance::Testing::ControllerHelpers
|
3
6
|
module Helpers
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
unless defined?(FactoryGirl)
|
11
|
-
raise(
|
12
|
-
RuntimeError,
|
13
|
-
"Clearance's `sign_in` helper requires factory_girl"
|
14
|
-
)
|
15
|
-
end
|
16
|
-
|
17
|
-
factory = Clearance.configuration.user_model.to_s.underscore.to_sym
|
18
|
-
sign_in_as FactoryGirl.create(factory)
|
19
|
-
end
|
20
|
-
|
21
|
-
def sign_in_as(user)
|
22
|
-
@controller.sign_in user
|
23
|
-
user
|
24
|
-
end
|
25
|
-
|
26
|
-
def sign_out
|
27
|
-
@controller.sign_out
|
28
|
-
end
|
7
|
+
warn(
|
8
|
+
"#{Kernel.caller.first} [DEPRECATION] Clearance::Testing::Helpers is "\
|
9
|
+
"deprecated and has been replaced with " \
|
10
|
+
"Clearance::Testing::ControllerHelpers. Require " \
|
11
|
+
"clearance/testing/controller_helpers instead."
|
12
|
+
)
|
29
13
|
end
|
30
14
|
end
|
31
15
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Clearance
|
2
|
+
module Testing
|
3
|
+
# Provides helpers to your view and helper specs.
|
4
|
+
# Using these helpers makes `current_user`, `signed_in?` and `signed_out?`
|
5
|
+
# behave properly in view and helper specs.
|
6
|
+
module ViewHelpers
|
7
|
+
# Sets current_user on the view under test to a new instance of your user
|
8
|
+
# model.
|
9
|
+
def sign_in
|
10
|
+
view.current_user = Clearance.configuration.user_model.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Sets current_user on the view under test to the supplied user.
|
14
|
+
def sign_in_as(user)
|
15
|
+
view.current_user = user
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
module CurrentUser
|
20
|
+
attr_accessor :current_user
|
21
|
+
|
22
|
+
def signed_in?
|
23
|
+
current_user.present?
|
24
|
+
end
|
25
|
+
|
26
|
+
def signed_out?
|
27
|
+
!signed_in?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/clearance/token.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
module Clearance
|
2
|
+
# Random token used for password reset and remember tokens.
|
3
|
+
# Clearance tokens are also public API and are inteded to be used anywhere you
|
4
|
+
# need a random token to correspond to a given user (e.g. you added an email
|
5
|
+
# confirmation token).
|
2
6
|
class Token
|
7
|
+
# Generate a new random, 20 byte hex token.
|
8
|
+
#
|
9
|
+
# @return [String]
|
3
10
|
def self.new
|
4
11
|
SecureRandom.hex(20).encode('UTF-8')
|
5
12
|
end
|