oath 1.1.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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +165 -0
- data/LICENSE.txt +22 -0
- data/NEWS.rdoc +118 -0
- data/README.md +384 -0
- data/Rakefile +6 -0
- data/lib/oath.rb +132 -0
- data/lib/oath/back_door.rb +53 -0
- data/lib/oath/configuration.rb +149 -0
- data/lib/oath/constraints/signed_in.rb +14 -0
- data/lib/oath/constraints/signed_out.rb +14 -0
- data/lib/oath/controller_helpers.rb +161 -0
- data/lib/oath/failure_app.rb +48 -0
- data/lib/oath/field_map.rb +56 -0
- data/lib/oath/param_transformer.rb +38 -0
- data/lib/oath/railtie.rb +11 -0
- data/lib/oath/services.rb +5 -0
- data/lib/oath/services/authentication.rb +40 -0
- data/lib/oath/services/password_reset.rb +27 -0
- data/lib/oath/services/sign_in.rb +25 -0
- data/lib/oath/services/sign_out.rb +24 -0
- data/lib/oath/services/sign_up.rb +42 -0
- data/lib/oath/strategies/password_strategy.rb +42 -0
- data/lib/oath/test/controller_helpers.rb +43 -0
- data/lib/oath/test/helpers.rb +24 -0
- data/lib/oath/version.rb +4 -0
- data/lib/oath/warden_setup.rb +47 -0
- data/oath.gemspec +30 -0
- data/spec/features/user/user_signs_in_spec.rb +14 -0
- data/spec/features/user/user_signs_in_through_back_door_spec.rb +11 -0
- data/spec/features/user/user_tries_to_access_constrained_routes_spec.rb +18 -0
- data/spec/features/user/user_tries_to_access_http_auth_page_spec.rb +9 -0
- data/spec/features/visitor/visitor_fails_to_sign_up_spec.rb +10 -0
- data/spec/features/visitor/visitor_is_unauthorized_spec.rb +8 -0
- data/spec/features/visitor/visitor_signs_in_via_invalid_form_spec.rb +11 -0
- data/spec/features/visitor/visitor_signs_up_spec.rb +40 -0
- data/spec/features/visitor/visitor_tries_to_access_constrained_routes_spec.rb +14 -0
- data/spec/features/visitor/visitor_uses_remember_token_spec.rb +13 -0
- data/spec/oath/configuration_spec.rb +11 -0
- data/spec/oath/controller_helpers_spec.rb +180 -0
- data/spec/oath/field_map_spec.rb +19 -0
- data/spec/oath/services/authentication_spec.rb +25 -0
- data/spec/oath/services/password_reset_spec.rb +24 -0
- data/spec/oath/services/sign_in_spec.rb +13 -0
- data/spec/oath/services/sign_out_spec.rb +13 -0
- data/spec/oath/services/sign_up_spec.rb +49 -0
- data/spec/oath/strategies/password_strategy_spec.rb +23 -0
- data/spec/oath/test_controller_helpers_spec.rb +63 -0
- data/spec/oath/test_helpers_spec.rb +97 -0
- data/spec/oath_spec.rb +27 -0
- data/spec/rails_app/Rakefile +7 -0
- data/spec/rails_app/app/assets/images/rails.png +0 -0
- data/spec/rails_app/app/assets/javascripts/application.js +13 -0
- data/spec/rails_app/app/assets/stylesheets/application.css +13 -0
- data/spec/rails_app/app/controllers/application_controller.rb +4 -0
- data/spec/rails_app/app/controllers/basic_auth_controller.rb +7 -0
- data/spec/rails_app/app/controllers/constrained_to_users_controller.rb +5 -0
- data/spec/rails_app/app/controllers/constrained_to_visitors_controller.rb +5 -0
- data/spec/rails_app/app/controllers/failures_controller.rb +5 -0
- data/spec/rails_app/app/controllers/invalid_sessions_controller.rb +2 -0
- data/spec/rails_app/app/controllers/posts_controller.rb +6 -0
- data/spec/rails_app/app/controllers/sessions_controller.rb +26 -0
- data/spec/rails_app/app/controllers/users_controller.rb +23 -0
- data/spec/rails_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_app/app/models/user.rb +10 -0
- data/spec/rails_app/app/views/invalid_sessions/new.html.erb +4 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +18 -0
- data/spec/rails_app/app/views/posts/index.html.erb +1 -0
- data/spec/rails_app/app/views/sessions/new.html.erb +5 -0
- data/spec/rails_app/app/views/users/new.html.erb +5 -0
- data/spec/rails_app/config.ru +4 -0
- data/spec/rails_app/config/application.rb +58 -0
- data/spec/rails_app/config/boot.rb +6 -0
- data/spec/rails_app/config/database.yml +25 -0
- data/spec/rails_app/config/environment.rb +5 -0
- data/spec/rails_app/config/environments/development.rb +29 -0
- data/spec/rails_app/config/environments/production.rb +54 -0
- data/spec/rails_app/config/environments/test.rb +29 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/inflections.rb +15 -0
- data/spec/rails_app/config/initializers/secret_token.rb +7 -0
- data/spec/rails_app/config/routes.rb +24 -0
- data/spec/rails_app/db/seeds.rb +7 -0
- data/spec/rails_app/public/404.html +26 -0
- data/spec/rails_app/public/422.html +26 -0
- data/spec/rails_app/public/500.html +25 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/script/rails +6 -0
- data/spec/spec_helper.rb +37 -0
- metadata +325 -0
data/Rakefile
ADDED
data/lib/oath.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'warden'
|
2
|
+
require "oath/version"
|
3
|
+
require "oath/configuration"
|
4
|
+
require "oath/services"
|
5
|
+
require "oath/controller_helpers"
|
6
|
+
require "oath/railtie"
|
7
|
+
require "oath/failure_app"
|
8
|
+
require "oath/back_door"
|
9
|
+
require "oath/warden_setup"
|
10
|
+
require "oath/field_map"
|
11
|
+
require "oath/param_transformer"
|
12
|
+
require "oath/strategies/password_strategy"
|
13
|
+
require "active_support/core_ext/module/attribute_accessors"
|
14
|
+
|
15
|
+
# Oath is an authentication toolkit designed to allow developers to create their own
|
16
|
+
# authentication solutions. If you're interested in a default implementation try
|
17
|
+
# {http://github.com/halogenandtoast/oath-generators Oath Generators}
|
18
|
+
# @since 0.0.15
|
19
|
+
module Oath
|
20
|
+
mattr_accessor :warden_config
|
21
|
+
mattr_accessor :config
|
22
|
+
|
23
|
+
module Test
|
24
|
+
autoload :Helpers, "oath/test/helpers"
|
25
|
+
autoload :ControllerHelpers, "oath/test/controller_helpers"
|
26
|
+
end
|
27
|
+
|
28
|
+
# initialize Oath. Sets up warden and the default configuration.
|
29
|
+
#
|
30
|
+
# @note This is used in {Oath::Railtie} in order to bootstrap Oath
|
31
|
+
# @param warden_config [Warden::Config] the configuration from warden
|
32
|
+
# @see Oath::Railtie
|
33
|
+
# @see Oath::Configuration
|
34
|
+
def self.initialize warden_config
|
35
|
+
setup_config
|
36
|
+
setup_warden_config(warden_config)
|
37
|
+
end
|
38
|
+
|
39
|
+
# compares the token (undigested password) to a digested password
|
40
|
+
#
|
41
|
+
# @param digest [String] A digested password
|
42
|
+
# @param token [String] An undigested password
|
43
|
+
# @see Oath::Configuration#default_token_comparison
|
44
|
+
# @return [Boolean] whether the token and digest match
|
45
|
+
def self.compare_token(digest, token)
|
46
|
+
config.token_comparison.call(digest, token)
|
47
|
+
end
|
48
|
+
|
49
|
+
# hashes a token
|
50
|
+
#
|
51
|
+
# @param token [String] the password in undigested form
|
52
|
+
# @see Oath::Configuration#default_hashing_method
|
53
|
+
# @return [String] a digest of the token
|
54
|
+
def self.hash_token(token)
|
55
|
+
config.hashing_method.call(token)
|
56
|
+
end
|
57
|
+
|
58
|
+
# performs transformations on params for signing up and
|
59
|
+
# signing in
|
60
|
+
#
|
61
|
+
# @param params [Hash] hash of parameters to transform
|
62
|
+
# @see Oath::Configuration#param_transofmrations
|
63
|
+
# @return [Hash] hash with transformed parameters
|
64
|
+
def self.transform_params(params)
|
65
|
+
ParamTransformer.new(params, config.param_transformations).to_h
|
66
|
+
end
|
67
|
+
|
68
|
+
# the user class
|
69
|
+
#
|
70
|
+
# @see Oath::Configuration#setup_class_defaults
|
71
|
+
# @deprecated Use Oath.config.user_class instead
|
72
|
+
# @return [Class] the User class
|
73
|
+
def self.user_class
|
74
|
+
warn "#{Kernel.caller.first}: [DEPRECATION] " +
|
75
|
+
'Accessing the user class through the Oath module is deprecated. Use Oath.config.user_class instead.'
|
76
|
+
config.user_class
|
77
|
+
end
|
78
|
+
|
79
|
+
# finds a user based on their credentials
|
80
|
+
#
|
81
|
+
# @param params [Hash] a hash of user parameters
|
82
|
+
# @param field_map [FieldMap] a field map in order to allow multiple lookup fields
|
83
|
+
# @see Oath::Configuration#default_find_method
|
84
|
+
# @return [User] if user is found
|
85
|
+
# @return [nil] if no user is found
|
86
|
+
def self.lookup(params, field_map)
|
87
|
+
if params.present?
|
88
|
+
fields = FieldMap.new(params, field_map).to_fields
|
89
|
+
self.config.find_method.call(fields)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Puts oath into test mode. This will disable hashing passwords
|
94
|
+
# @note You must call this if you want to use oath in your tests
|
95
|
+
def self.test_mode!
|
96
|
+
Warden.test_mode!
|
97
|
+
self.config ||= Oath::Configuration.new
|
98
|
+
config.hashing_method = ->(password) { password }
|
99
|
+
config.token_comparison = ->(digest, undigested_password) do
|
100
|
+
digest == undigested_password
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Configures oath
|
105
|
+
#
|
106
|
+
# @yield [configuration] Yield the current configuration
|
107
|
+
# @example A custom configuration
|
108
|
+
# Oath.configure do |config|
|
109
|
+
# config.user_lookup_field = :username
|
110
|
+
# config.user_token_store_field = :hashed_password
|
111
|
+
# end
|
112
|
+
def self.configure(&block)
|
113
|
+
self.config ||= Oath::Configuration.new
|
114
|
+
yield self.config
|
115
|
+
end
|
116
|
+
|
117
|
+
# Resets oath in between tests.
|
118
|
+
# @note You must call this between tests
|
119
|
+
def self.test_reset!
|
120
|
+
Warden.test_reset!
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def self.setup_config
|
126
|
+
self.config ||= Oath::Configuration.new
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.setup_warden_config(warden_config)
|
130
|
+
self.warden_config = WardenSetup.new(warden_config).call
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Oath
|
2
|
+
# Middleware used in tests to allow users to be signed in directly, without
|
3
|
+
# having to load and submit the sign in form. The user should be provided by
|
4
|
+
# using the key :as in a hash passed to the path.
|
5
|
+
#
|
6
|
+
# @note This should only be used for testing purposes
|
7
|
+
# @since 0.0.15
|
8
|
+
# @example Using the backdoor in an rspec feature spec
|
9
|
+
# feature "User dashboard" do
|
10
|
+
# scenario "user visits dashboard" do
|
11
|
+
# user = create(:user)
|
12
|
+
# visit dashboard_path(as: user)
|
13
|
+
# expect(page).to have_css("#dashboard")
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
class BackDoor
|
17
|
+
# Create the a new BackDoor middleware for test purposes
|
18
|
+
# @return [BackDoor]
|
19
|
+
def initialize(app, &block)
|
20
|
+
@app = app
|
21
|
+
|
22
|
+
if block
|
23
|
+
@sign_in_block = block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Execute the BackDoor middleware signing in the user specified with :as
|
28
|
+
def call(env)
|
29
|
+
sign_in_through_the_back_door(env)
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def sign_in_through_the_back_door(env)
|
36
|
+
params = Rack::Utils.parse_query(env['QUERY_STRING'])
|
37
|
+
user_id = params['as']
|
38
|
+
|
39
|
+
if user_id.present?
|
40
|
+
user = find_user(user_id)
|
41
|
+
env["warden"].set_user(user)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_user(user_id)
|
46
|
+
if @sign_in_block
|
47
|
+
@sign_in_block.call(user_id)
|
48
|
+
else
|
49
|
+
Oath.config.user_class.find(user_id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module Oath
|
2
|
+
# Configuration options for Oath
|
3
|
+
# @since 0.0.15
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :user_token_field, :user_token_store_field
|
6
|
+
attr_accessor :hashing_method, :token_comparison, :user_lookup_field
|
7
|
+
attr_accessor :sign_in_notice
|
8
|
+
attr_accessor :sign_in_service, :sign_up_service, :sign_out_service
|
9
|
+
attr_accessor :authentication_service, :password_reset_service
|
10
|
+
attr_accessor :failure_app
|
11
|
+
attr_accessor :creation_method, :find_method
|
12
|
+
attr_accessor :no_login_handler, :no_login_redirect
|
13
|
+
attr_accessor :authentication_strategy
|
14
|
+
attr_accessor :warden_serialize_into_session, :warden_serialize_from_session
|
15
|
+
attr_accessor :param_transformations
|
16
|
+
|
17
|
+
attr_writer :user_class
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
setup_class_defaults
|
21
|
+
setup_token_hashing
|
22
|
+
setup_notices
|
23
|
+
setup_services
|
24
|
+
setup_warden
|
25
|
+
setup_param_transformations
|
26
|
+
end
|
27
|
+
|
28
|
+
# Default creation method. Can be overriden via {Oath.configure}
|
29
|
+
#
|
30
|
+
# @see #creation_method=
|
31
|
+
def default_creation_method
|
32
|
+
->(params) do
|
33
|
+
updated_params = Oath.transform_params(params)
|
34
|
+
Oath.config.user_class.create(updated_params)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Default hashing method. Can be overriden via {Oath.configure}
|
39
|
+
#
|
40
|
+
# @see #hashing_method=
|
41
|
+
def default_hashing_method
|
42
|
+
->(token) do
|
43
|
+
if token.present?
|
44
|
+
BCrypt::Password.create(token)
|
45
|
+
else
|
46
|
+
token
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Default find method. Can be overriden via {Oath.configure}
|
52
|
+
#
|
53
|
+
# @see #find_method=
|
54
|
+
# @see Oath.config.user_class
|
55
|
+
def default_find_method
|
56
|
+
->(params) do
|
57
|
+
updated_params = Oath.transform_params(params)
|
58
|
+
Oath.config.user_class.find_by(updated_params)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Default token comparison method. Can be overriden via {Oath.configure}
|
63
|
+
#
|
64
|
+
# @see #token_comparison=
|
65
|
+
def default_token_comparison
|
66
|
+
->(digest, undigested_token) do
|
67
|
+
BCrypt::Password.new(digest) == undigested_token
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Default handler when user is not logged in. Can be overriden via {Oath.configure}
|
72
|
+
#
|
73
|
+
# @see #no_login_handler=
|
74
|
+
# @see #sign_in_notice
|
75
|
+
# @see #no_login_redirect
|
76
|
+
def default_no_login_handler
|
77
|
+
->(controller) do
|
78
|
+
notice = Oath.config.sign_in_notice
|
79
|
+
|
80
|
+
if notice.respond_to?(:call)
|
81
|
+
controller.flash.notice = notice.call
|
82
|
+
else
|
83
|
+
warn "[DEPRECATION] `Oath.config.sign_in_notice` should be a lambda instead of a string"
|
84
|
+
controller.flash.notice = notice
|
85
|
+
end
|
86
|
+
|
87
|
+
controller.redirect_to Oath.config.no_login_redirect
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# User class. Can be overriden via {Oath.configure}
|
92
|
+
#
|
93
|
+
# @see #user_class=
|
94
|
+
def user_class
|
95
|
+
@user_class.constantize
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def setup_token_hashing
|
101
|
+
@hashing_method = default_hashing_method
|
102
|
+
@token_comparison = default_token_comparison
|
103
|
+
end
|
104
|
+
|
105
|
+
def setup_notices
|
106
|
+
@sign_in_notice = -> { 'You must be signed in' }
|
107
|
+
end
|
108
|
+
|
109
|
+
def setup_class_defaults
|
110
|
+
@user_class = 'User'
|
111
|
+
@user_token_field = :password
|
112
|
+
@user_token_store_field = :password_digest
|
113
|
+
@user_lookup_field = :email
|
114
|
+
@creation_method = default_creation_method
|
115
|
+
@find_method = default_find_method
|
116
|
+
@no_login_redirect = { controller: '/sessions', action: 'new' }
|
117
|
+
@no_login_handler = default_no_login_handler
|
118
|
+
end
|
119
|
+
|
120
|
+
def setup_services
|
121
|
+
@authentication_service = Oath::Services::Authentication
|
122
|
+
@sign_in_service = Oath::Services::SignIn
|
123
|
+
@sign_up_service = Oath::Services::SignUp
|
124
|
+
@sign_out_service = Oath::Services::SignOut
|
125
|
+
@password_reset_service = Oath::Services::PasswordReset
|
126
|
+
end
|
127
|
+
|
128
|
+
def setup_warden
|
129
|
+
setup_warden_requirements
|
130
|
+
setup_warden_serialization
|
131
|
+
end
|
132
|
+
|
133
|
+
def setup_warden_requirements
|
134
|
+
@failure_app = Oath::FailureApp
|
135
|
+
@authentication_strategy = Oath::Strategies::PasswordStrategy
|
136
|
+
end
|
137
|
+
|
138
|
+
def setup_warden_serialization
|
139
|
+
@warden_serialize_into_session = -> (user) { user.id }
|
140
|
+
@warden_serialize_from_session = -> (id) { Oath.config.user_class.find_by(id: id) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def setup_param_transformations
|
144
|
+
@param_transformations = {
|
145
|
+
"email" => ->(value) { value.downcase }
|
146
|
+
}
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Oath
|
2
|
+
module Constraints
|
3
|
+
# Rails route constraint for signed in users
|
4
|
+
class SignedIn
|
5
|
+
# Checks to see if the constraint is matched by having a user signed in
|
6
|
+
#
|
7
|
+
# @param request [Rack::Request] A rack request
|
8
|
+
def matches?(request)
|
9
|
+
warden = request.env["warden"]
|
10
|
+
warden && warden.authenticated?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Oath
|
2
|
+
module Constraints
|
3
|
+
# Rails route constraint for signed out users
|
4
|
+
class SignedOut
|
5
|
+
# Checks to see if the constraint is matched by not having a user signed in
|
6
|
+
#
|
7
|
+
# @param request [Rack::Request] A rack request
|
8
|
+
def matches?(request)
|
9
|
+
warden = request.env["warden"]
|
10
|
+
warden && warden.unauthenticated?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'bcrypt'
|
2
|
+
require 'active_support/concern'
|
3
|
+
|
4
|
+
module Oath
|
5
|
+
# Mixin to be included in Rails controllers.
|
6
|
+
# @since 0.0.15
|
7
|
+
module ControllerHelpers
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
included do
|
10
|
+
if respond_to?(:helper_method)
|
11
|
+
helper_method :current_user, :signed_in?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Sign in a user
|
16
|
+
#
|
17
|
+
# @note Uses the {Oath::Services::SignIn} service to create a session
|
18
|
+
#
|
19
|
+
# @param user [User] the user object to sign in
|
20
|
+
# @yield Yields to the block if the user is successfully signed in
|
21
|
+
# @return [Object] returns the value from calling perform on the {Oath::Services::SignIn} service
|
22
|
+
def sign_in user
|
23
|
+
Oath.config.sign_in_service.new(user, warden).perform.tap do |status|
|
24
|
+
if status && block_given?
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Sign out the current session
|
31
|
+
#
|
32
|
+
# @note Uses the {Oath::Services::SignOut} service to destroy the session
|
33
|
+
#
|
34
|
+
# @return [Object] returns the value from calling perform on the {Oath::Services::SignOut} service
|
35
|
+
def sign_out
|
36
|
+
Oath.config.sign_out_service.new(warden).perform
|
37
|
+
end
|
38
|
+
|
39
|
+
# Sign up a user
|
40
|
+
#
|
41
|
+
# @note Uses the {Oath::Services::SignUp} service to create a user
|
42
|
+
#
|
43
|
+
# @param user_params [Hash] params containing lookup and token fields
|
44
|
+
# @yield Yields to the block if the user is signed up successfully
|
45
|
+
# @return [Object] returns the value from calling perform on the {Oath::Services::SignUp} service
|
46
|
+
def sign_up user_params
|
47
|
+
Oath.config.sign_up_service.new(user_params).perform.tap do |status|
|
48
|
+
if status && block_given?
|
49
|
+
yield
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Authenticates a session.
|
55
|
+
#
|
56
|
+
# @note Uses the {Oath::Services::Authentication} service to verify the user's details
|
57
|
+
#
|
58
|
+
# @param session_params [Hash] params containing lookup and token fields
|
59
|
+
# @param field_map [Hash] Field map used for allowing users to sign in with multiple fields e.g. email and username
|
60
|
+
# @return [User] if authentication succeeded
|
61
|
+
# @return [nil] if authentication failed
|
62
|
+
# @example Basic usage
|
63
|
+
# class SessionsController < ApplicationController
|
64
|
+
# def create
|
65
|
+
# user = authenticate_session(session_params)
|
66
|
+
#
|
67
|
+
# if sign_in(user)
|
68
|
+
# redirect_to(root_path)
|
69
|
+
# else
|
70
|
+
# render :new
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# private
|
75
|
+
#
|
76
|
+
# def session_params
|
77
|
+
# params.require(:session).permit(:email, :password)
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# end
|
81
|
+
# @example Using the field map to authenticate using multiple lookup fields
|
82
|
+
# class SessionsController < ApplicationController
|
83
|
+
# def create
|
84
|
+
# user = authenticate_session(session_params, email_or_username: [:email, :username])
|
85
|
+
#
|
86
|
+
# if sign_in(user)
|
87
|
+
# redirect_to(root_path)
|
88
|
+
# else
|
89
|
+
# render :new
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# private
|
94
|
+
#
|
95
|
+
# def session_params
|
96
|
+
# params.require(:session).permit(:email_or_username, :password)
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# end
|
100
|
+
|
101
|
+
def authenticate_session session_params, field_map = nil
|
102
|
+
token_field = Oath.config.user_token_field
|
103
|
+
params_hash = Oath.transform_params(session_params).symbolize_keys
|
104
|
+
password = params_hash.fetch(token_field)
|
105
|
+
user = Oath.lookup(params_hash.except(token_field), field_map)
|
106
|
+
authenticate(user, password)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Authenticates a user given a password
|
110
|
+
#
|
111
|
+
# @note Uses the {Oath::Services::Authentication} service to verify the user's credentials
|
112
|
+
#
|
113
|
+
# @param user [User] the user
|
114
|
+
# @param password [String] the password
|
115
|
+
# @return [User] if authentication succeeded
|
116
|
+
# @return [nil] if authentication failed
|
117
|
+
def authenticate user, password
|
118
|
+
Oath.config.authentication_service.new(user, password).perform
|
119
|
+
end
|
120
|
+
|
121
|
+
# Resets a user's password
|
122
|
+
#
|
123
|
+
# @note Uses the {Oath::Services::PasswordReset} service to change a user's password
|
124
|
+
#
|
125
|
+
# @param user [User] the user
|
126
|
+
# @param password [String] the password
|
127
|
+
def reset_password user, password
|
128
|
+
Oath.config.password_reset_service.new(user, password).perform
|
129
|
+
end
|
130
|
+
|
131
|
+
# @api private
|
132
|
+
def warden
|
133
|
+
request.env['warden']
|
134
|
+
end
|
135
|
+
|
136
|
+
# helper_method that returns the current user
|
137
|
+
#
|
138
|
+
# @return [User] if user is signed in
|
139
|
+
# @return [nil] if user is not signed in
|
140
|
+
def current_user
|
141
|
+
@current_user ||= warden.user
|
142
|
+
end
|
143
|
+
|
144
|
+
# helper_method that checks if there is a user signed in
|
145
|
+
#
|
146
|
+
# @return [User] if user is signed in
|
147
|
+
# @return [nil] if user is not signed in
|
148
|
+
def signed_in?
|
149
|
+
warden.user
|
150
|
+
end
|
151
|
+
|
152
|
+
# before_action that determines what to do when the user is not signed in
|
153
|
+
#
|
154
|
+
# @note Uses the no login handler
|
155
|
+
def require_login
|
156
|
+
unless signed_in?
|
157
|
+
Oath.config.no_login_handler.call(self)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|