omniauth-identity 1.1.1 → 3.0.3
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 +5 -5
- data/CHANGELOG.md +81 -0
- data/CODE_OF_CONDUCT.md +133 -0
- data/LICENSE +22 -0
- data/README.md +238 -0
- data/lib/omniauth-identity.rb +2 -0
- data/lib/omniauth-identity/version.rb +3 -1
- data/lib/omniauth/identity.rb +3 -2
- data/lib/omniauth/identity/model.rb +17 -14
- data/lib/omniauth/identity/models/active_record.rb +4 -1
- data/lib/omniauth/identity/models/couch_potato.rb +3 -4
- data/lib/omniauth/identity/models/mongoid.rb +3 -7
- data/lib/omniauth/identity/models/{mongo_mapper.rb → no_brainer.rb} +6 -4
- data/lib/omniauth/identity/secure_password.rb +4 -4
- data/lib/omniauth/strategies/identity.rb +92 -39
- data/spec/omniauth/identity/model_spec.rb +60 -59
- data/spec/omniauth/identity/models/active_record_spec.rb +24 -8
- data/spec/omniauth/identity/models/couch_potato_spec.rb +17 -11
- data/spec/omniauth/identity/models/mongoid_spec.rb +23 -13
- data/spec/omniauth/identity/models/no_brainer_spec.rb +17 -0
- data/spec/omniauth/identity/secure_password_spec.rb +12 -12
- data/spec/omniauth/strategies/identity_spec.rb +178 -67
- data/spec/spec_helper.rb +20 -6
- metadata +75 -128
- data/.gitignore +0 -4
- data/.rspec +0 -2
- data/Gemfile +0 -11
- data/Gemfile.lock +0 -179
- data/Guardfile +0 -10
- data/README.markdown +0 -202
- data/Rakefile +0 -9
- data/lib/omniauth/identity/models/data_mapper.rb +0 -32
- data/omniauth-identity.gemspec +0 -32
- data/spec/omniauth/identity/models/data_mapper_spec.rb +0 -22
- data/spec/omniauth/identity/models/mongo_mapper_spec.rb +0 -15
data/lib/omniauth-identity.rb
CHANGED
data/lib/omniauth/identity.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'omniauth'
|
2
4
|
|
3
5
|
module OmniAuth
|
@@ -10,10 +12,9 @@ module OmniAuth
|
|
10
12
|
autoload :SecurePassword, 'omniauth/identity/secure_password'
|
11
13
|
module Models
|
12
14
|
autoload :ActiveRecord, 'omniauth/identity/models/active_record'
|
13
|
-
autoload :MongoMapper, 'omniauth/identity/models/mongo_mapper'
|
14
15
|
autoload :Mongoid, 'omniauth/identity/models/mongoid'
|
15
|
-
autoload :DataMapper, 'omniauth/identity/models/data_mapper'
|
16
16
|
autoload :CouchPotatoModule, 'omniauth/identity/models/couch_potato'
|
17
|
+
autoload :NoBrainer, 'omniauth/identity/models/no_brainer'
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module OmniAuth
|
2
4
|
module Identity
|
3
5
|
# This module provides an includable interface for implementing the
|
@@ -28,6 +30,7 @@ module OmniAuth
|
|
28
30
|
def authenticate(conditions, password)
|
29
31
|
instance = locate(conditions)
|
30
32
|
return false unless instance
|
33
|
+
|
31
34
|
instance.authenticate(password)
|
32
35
|
end
|
33
36
|
|
@@ -36,7 +39,7 @@ module OmniAuth
|
|
36
39
|
# @return [String] The method name.
|
37
40
|
def auth_key(method = false)
|
38
41
|
@auth_key = method.to_s unless method == false
|
39
|
-
@auth_key = nil if @auth_key == ''
|
42
|
+
@auth_key = nil if !defined?(@auth_key) || @auth_key == ''
|
40
43
|
|
41
44
|
@auth_key || 'email'
|
42
45
|
end
|
@@ -52,22 +55,20 @@ module OmniAuth
|
|
52
55
|
raise NotImplementedError
|
53
56
|
end
|
54
57
|
|
55
|
-
SCHEMA_ATTRIBUTES = %w
|
58
|
+
SCHEMA_ATTRIBUTES = %w[name email nickname first_name last_name location description image phone].freeze
|
56
59
|
# A hash of as much of the standard OmniAuth schema as is stored
|
57
60
|
# in this particular model. By default, this will call instance
|
58
61
|
# methods for each of the attributes it needs in turn, ignoring
|
59
62
|
# any for which `#respond_to?` is `false`.
|
60
63
|
#
|
61
|
-
# If `first_name`, `nickname`, and/or `last_name` is provided but
|
64
|
+
# If `first_name`, `nickname`, and/or `last_name` is provided but
|
62
65
|
# `name` is not, it will be automatically calculated.
|
63
66
|
#
|
64
67
|
# @return [Hash] A string-keyed hash of user information.
|
65
68
|
def info
|
66
|
-
|
69
|
+
SCHEMA_ATTRIBUTES.each_with_object({}) do |attribute, hash|
|
67
70
|
hash[attribute] = send(attribute) if respond_to?(attribute)
|
68
|
-
hash
|
69
71
|
end
|
70
|
-
info
|
71
72
|
end
|
72
73
|
|
73
74
|
# An identifying string that must be globally unique to the
|
@@ -75,22 +76,23 @@ module OmniAuth
|
|
75
76
|
#
|
76
77
|
# @return [String] An identifier string unique to this identity.
|
77
78
|
def uid
|
78
|
-
if respond_to?(
|
79
|
-
return nil if
|
80
|
-
|
79
|
+
if respond_to?(:id)
|
80
|
+
return nil if id.nil?
|
81
|
+
|
82
|
+
id.to_s
|
81
83
|
else
|
82
|
-
raise NotImplementedError
|
84
|
+
raise NotImplementedError
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
86
88
|
# Used to retrieve the user-supplied authentication key (e.g. a
|
87
89
|
# username or email). Determined using the class method of the same name,
|
88
|
-
# defaults to `:email`.
|
90
|
+
# defaults to `:email`.
|
89
91
|
#
|
90
92
|
# @return [String] An identifying string that will be entered by
|
91
93
|
# users upon sign in.
|
92
94
|
def auth_key
|
93
|
-
if respond_to?(self.class.auth_key)
|
95
|
+
if respond_to?(self.class.auth_key.to_sym)
|
94
96
|
send(self.class.auth_key)
|
95
97
|
else
|
96
98
|
raise NotImplementedError
|
@@ -104,8 +106,9 @@ module OmniAuth
|
|
104
106
|
# @param [String] value The value to which the auth key should be
|
105
107
|
# set.
|
106
108
|
def auth_key=(value)
|
107
|
-
|
108
|
-
|
109
|
+
auth_key_setter = "#{self.class.auth_key}=".to_sym
|
110
|
+
if respond_to?(auth_key_setter)
|
111
|
+
send(auth_key_setter, value)
|
109
112
|
else
|
110
113
|
raise NotImplementedError
|
111
114
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
|
3
5
|
module OmniAuth
|
@@ -12,10 +14,11 @@ module OmniAuth
|
|
12
14
|
|
13
15
|
def self.auth_key=(key)
|
14
16
|
super
|
15
|
-
validates_uniqueness_of key, :
|
17
|
+
validates_uniqueness_of key, case_sensitive: false
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.locate(search_hash)
|
21
|
+
search_hash = search_hash.reverse_merge!('provider' => 'identity') if column_names.include?('provider')
|
19
22
|
where(search_hash).first
|
20
23
|
end
|
21
24
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'couch_potato'
|
2
4
|
|
3
5
|
module OmniAuth
|
@@ -5,11 +7,8 @@ module OmniAuth
|
|
5
7
|
module Models
|
6
8
|
# can not be named CouchPotato since there is a class with that name
|
7
9
|
module CouchPotatoModule
|
8
|
-
|
9
10
|
def self.included(base)
|
10
|
-
|
11
11
|
base.class_eval do
|
12
|
-
|
13
12
|
include ::OmniAuth::Identity::Model
|
14
13
|
include ::OmniAuth::Identity::SecurePassword
|
15
14
|
|
@@ -17,7 +16,7 @@ module OmniAuth
|
|
17
16
|
|
18
17
|
def self.auth_key=(key)
|
19
18
|
super
|
20
|
-
validates_uniqueness_of key, :
|
19
|
+
validates_uniqueness_of key, case_sensitive: false
|
21
20
|
end
|
22
21
|
|
23
22
|
def self.locate(search_hash)
|
@@ -1,14 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'mongoid'
|
2
4
|
|
3
5
|
module OmniAuth
|
4
6
|
module Identity
|
5
7
|
module Models
|
6
8
|
module Mongoid
|
7
|
-
|
8
9
|
def self.included(base)
|
9
|
-
|
10
10
|
base.class_eval do
|
11
|
-
|
12
11
|
include ::OmniAuth::Identity::Model
|
13
12
|
include ::OmniAuth::Identity::SecurePassword
|
14
13
|
|
@@ -16,17 +15,14 @@ module OmniAuth
|
|
16
15
|
|
17
16
|
def self.auth_key=(key)
|
18
17
|
super
|
19
|
-
validates_uniqueness_of key, :
|
18
|
+
validates_uniqueness_of key, case_sensitive: false
|
20
19
|
end
|
21
20
|
|
22
21
|
def self.locate(search_hash)
|
23
22
|
where(search_hash).first
|
24
23
|
end
|
25
|
-
|
26
24
|
end
|
27
|
-
|
28
25
|
end
|
29
|
-
|
30
26
|
end
|
31
27
|
end
|
32
28
|
end
|
@@ -1,9 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nobrainer'
|
2
4
|
|
3
5
|
module OmniAuth
|
4
6
|
module Identity
|
5
7
|
module Models
|
6
|
-
|
8
|
+
# http://nobrainer.io/ an ORM for RethinkDB
|
9
|
+
module NoBrainer
|
7
10
|
def self.included(base)
|
8
11
|
base.class_eval do
|
9
12
|
include ::OmniAuth::Identity::Model
|
@@ -13,7 +16,7 @@ module OmniAuth
|
|
13
16
|
|
14
17
|
def self.auth_key=(key)
|
15
18
|
super
|
16
|
-
validates_uniqueness_of key, :
|
19
|
+
validates_uniqueness_of key, case_sensitive: false
|
17
20
|
end
|
18
21
|
|
19
22
|
def self.locate(search_hash)
|
@@ -25,4 +28,3 @@ module OmniAuth
|
|
25
28
|
end
|
26
29
|
end
|
27
30
|
end
|
28
|
-
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bcrypt'
|
2
4
|
|
3
5
|
module OmniAuth
|
@@ -9,9 +11,7 @@ module OmniAuth
|
|
9
11
|
# a has_secure_password method.
|
10
12
|
module SecurePassword
|
11
13
|
def self.included(base)
|
12
|
-
unless base.respond_to?(:has_secure_password)
|
13
|
-
base.extend ClassMethods
|
14
|
-
end
|
14
|
+
base.extend ClassMethods unless base.respond_to?(:has_secure_password)
|
15
15
|
end
|
16
16
|
|
17
17
|
module ClassMethods
|
@@ -40,7 +40,7 @@ module OmniAuth
|
|
40
40
|
# User.find_by_name("david").try(:authenticate, "notright") # => nil
|
41
41
|
# User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user
|
42
42
|
def has_secure_password
|
43
|
-
attr_reader
|
43
|
+
attr_reader :password
|
44
44
|
|
45
45
|
validates_confirmation_of :password
|
46
46
|
validates_presence_of :password_digest
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module OmniAuth
|
2
4
|
module Strategies
|
3
5
|
# The identity strategy allows you to provide simple internal
|
@@ -6,76 +8,91 @@ module OmniAuth
|
|
6
8
|
class Identity
|
7
9
|
include OmniAuth::Strategy
|
8
10
|
|
9
|
-
option :fields, [
|
10
|
-
|
11
|
-
|
12
|
-
option :
|
13
|
-
option :
|
11
|
+
option :fields, %i[name email]
|
12
|
+
|
13
|
+
# Primary Feature Switches:
|
14
|
+
option :enable_registration, true # See #other_phase and #request_phase
|
15
|
+
option :enable_login, true # See #other_phase
|
16
|
+
|
17
|
+
# Customization Options:
|
18
|
+
option :on_login, nil # See #request_phase
|
19
|
+
option :on_validation, nil # See #registration_phase
|
20
|
+
option :on_registration, nil # See #registration_phase
|
21
|
+
option :on_failed_registration, nil # See #registration_phase
|
22
|
+
option :locate_conditions, ->(req) { { model.auth_key => req['auth_key'] } }
|
14
23
|
|
15
24
|
def request_phase
|
16
25
|
if options[:on_login]
|
17
|
-
options[:on_login].call(
|
26
|
+
options[:on_login].call(env)
|
18
27
|
else
|
19
|
-
|
20
|
-
:title => (options[:title] || "Identity Verification"),
|
21
|
-
:url => callback_path
|
22
|
-
) do |f|
|
23
|
-
f.text_field 'Login', 'auth_key'
|
24
|
-
f.password_field 'Password', 'password'
|
25
|
-
f.html "<p align='center'><a href='#{registration_path}'>Create an Identity</a></p>"
|
26
|
-
end.to_response
|
28
|
+
build_omniauth_login_form.to_response
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
def callback_phase
|
31
33
|
return fail!(:invalid_credentials) unless identity
|
34
|
+
|
32
35
|
super
|
33
36
|
end
|
34
37
|
|
35
38
|
def other_phase
|
36
|
-
if on_registration_path?
|
39
|
+
if options[:enable_registration] && on_registration_path?
|
37
40
|
if request.get?
|
38
41
|
registration_form
|
39
42
|
elsif request.post?
|
40
43
|
registration_phase
|
44
|
+
else
|
45
|
+
call_app!
|
41
46
|
end
|
47
|
+
elsif options[:enable_login] && on_request_path?
|
48
|
+
# OmniAuth, by default, disables "GET" requests for security reasons.
|
49
|
+
# This effectively disables omniauth-identity tool's login form feature.
|
50
|
+
# Because it is disabled by default, and because enabling it would desecuritize all the other
|
51
|
+
# OmniAuth strategies that may be implemented, we do not ask users to modify that setting.
|
52
|
+
# Instead we hook in here in the "other_phase", with a config setting of our own: `enable_login`
|
53
|
+
request_phase
|
42
54
|
else
|
43
55
|
call_app!
|
44
56
|
end
|
45
57
|
end
|
46
58
|
|
47
|
-
def registration_form
|
59
|
+
def registration_form(validation_message = nil)
|
48
60
|
if options[:on_registration]
|
49
|
-
options[:on_registration].call(
|
61
|
+
options[:on_registration].call(env)
|
50
62
|
else
|
51
|
-
|
52
|
-
options[:fields].each do |field|
|
53
|
-
f.text_field field.to_s.capitalize, field.to_s
|
54
|
-
end
|
55
|
-
f.password_field 'Password', 'password'
|
56
|
-
f.password_field 'Confirm Password', 'password_confirmation'
|
57
|
-
end.to_response
|
63
|
+
build_omniauth_registration_form(validation_message).to_response
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
61
67
|
def registration_phase
|
62
|
-
attributes = (options[:fields] + [
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
+
attributes = (options[:fields] + %i[password password_confirmation]).each_with_object({}) do |k, h|
|
69
|
+
h[k] = request[k.to_s]
|
70
|
+
end
|
71
|
+
if model.respond_to?(:column_names) && model.column_names.include?('provider')
|
72
|
+
attributes.reverse_merge!(provider: 'identity')
|
73
|
+
end
|
74
|
+
@identity = model.new(attributes)
|
75
|
+
|
76
|
+
# on_validation may run a Captcha or other validation mechanism
|
77
|
+
# Must return true when validation passes, false otherwise
|
78
|
+
if options[:on_validation] && !options[:on_validation].call(env: env)
|
68
79
|
if options[:on_failed_registration]
|
69
|
-
|
70
|
-
options[:on_failed_registration].call(
|
80
|
+
env['omniauth.identity'] = @identity
|
81
|
+
options[:on_failed_registration].call(env)
|
71
82
|
else
|
72
|
-
|
83
|
+
validation_message = 'Validation failed'
|
84
|
+
registration_form(validation_message)
|
73
85
|
end
|
86
|
+
elsif @identity.save && @identity.persisted?
|
87
|
+
env['PATH_INFO'] = callback_path
|
88
|
+
callback_phase
|
89
|
+
else
|
90
|
+
show_custom_options_or_default
|
74
91
|
end
|
75
92
|
end
|
76
93
|
|
77
|
-
uid{ identity.uid }
|
78
|
-
info{ identity.info }
|
94
|
+
uid { identity.uid }
|
95
|
+
info { identity.info }
|
79
96
|
|
80
97
|
def registration_path
|
81
98
|
options[:registration_path] || "#{path_prefix}/#{name}/register"
|
@@ -86,18 +103,54 @@ module OmniAuth
|
|
86
103
|
end
|
87
104
|
|
88
105
|
def identity
|
89
|
-
if options
|
90
|
-
conditions = instance_exec(request, &options
|
106
|
+
if options[:locate_conditions].is_a? Proc
|
107
|
+
conditions = instance_exec(request, &options[:locate_conditions])
|
91
108
|
conditions.to_hash
|
92
109
|
else
|
93
|
-
conditions = options
|
110
|
+
conditions = options[:locate_conditions].to_hash
|
94
111
|
end
|
95
|
-
@identity ||= model.authenticate(conditions, request['password']
|
112
|
+
@identity ||= model.authenticate(conditions, request['password'])
|
96
113
|
end
|
97
114
|
|
98
115
|
def model
|
99
116
|
options[:model] || ::Identity
|
100
117
|
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def build_omniauth_login_form
|
122
|
+
OmniAuth::Form.build(
|
123
|
+
title: (options[:title] || 'Identity Verification'),
|
124
|
+
url: callback_path
|
125
|
+
) do |f|
|
126
|
+
f.text_field 'Login', 'auth_key'
|
127
|
+
f.password_field 'Password', 'password'
|
128
|
+
if options[:enable_registration]
|
129
|
+
f.html "<p align='center'><a href='#{registration_path}'>Create an Identity</a></p>"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def build_omniauth_registration_form(validation_message)
|
135
|
+
OmniAuth::Form.build(title: 'Register Identity') do |f|
|
136
|
+
f.html "<p style='color:red'>#{validation_message}</p>" if validation_message
|
137
|
+
options[:fields].each do |field|
|
138
|
+
f.text_field field.to_s.capitalize, field.to_s
|
139
|
+
end
|
140
|
+
f.password_field 'Password', 'password'
|
141
|
+
f.password_field 'Confirm Password', 'password_confirmation'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def show_custom_options_or_default
|
146
|
+
if options[:on_failed_registration]
|
147
|
+
env['omniauth.identity'] = @identity
|
148
|
+
options[:on_failed_registration].call(env)
|
149
|
+
else
|
150
|
+
validation_message = 'One or more fields were invalid'
|
151
|
+
registration_form(validation_message)
|
152
|
+
end
|
153
|
+
end
|
101
154
|
end
|
102
155
|
end
|
103
156
|
end
|