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,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
@@ -1,8 +1,19 @@
1
- require 'rspec/rails'
2
- require 'clearance/testing/deny_access_matcher'
3
- require 'clearance/testing/helpers'
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::Helpers, type: :controller
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
@@ -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 ||= @env['action_dispatch.cookies'] || Rack::Request.new(@env).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
@@ -1,8 +1,8 @@
1
- require 'clearance/testing/deny_access_matcher'
2
- require 'clearance/testing/helpers'
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::Helpers
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 @controller.signed_in?
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
- def setup_controller_request_and_response
5
- super
6
- @request.env[:clearance] = Clearance::Session.new(@request.env)
7
- end
8
-
9
- def sign_in
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
@@ -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