oath 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|