omniauth-identity 3.1.4 → 3.1.5

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.
@@ -6,12 +6,41 @@ module OmniAuth
6
6
  module Identity
7
7
  module Models
8
8
  # Sequel is an ORM adapter for the following databases:
9
- # ADO, Amalgalite, IBM_DB, JDBC, MySQL, Mysql2, ODBC, Oracle, PostgreSQL, SQLAnywhere, SQLite3, and TinyTDS
9
+ # ADO, Amalgalite, IBM_DB, JDBC, MySQL, Mysql2, ODBC, Oracle, PostgreSQL, SQLAnywhere, SQLite3, and TinyTDS
10
10
  # The homepage is: http://sequel.jeremyevans.net/
11
- # NOTE: Sequel is *not* based on ActiveModel, but supports the API we need, except for `persisted?`:
12
- # * create
13
- # * save
11
+ #
12
+ # This module provides OmniAuth Identity functionality for Sequel models,
13
+ # including secure password handling and authentication key management.
14
+ #
15
+ # @example Usage
16
+ # class User < Sequel::Model(:users)
17
+ # include OmniAuth::Identity::Models::Sequel
18
+ # end
19
+ #
20
+ # # Schema example:
21
+ # # DB.create_table :users do
22
+ # # primary_key :id
23
+ # # String :email, null: false, unique: true
24
+ # # String :password_digest, null: false
25
+ # # end
26
+ #
27
+ # user = User.new(email: 'user@example.com', password: 'password')
28
+ # user.save
29
+ #
30
+ # # Authenticate a user
31
+ # authenticated_user = User.locate(email: 'user@example.com')
32
+ # authenticated_user.authenticate('password') # => user or false
33
+ #
34
+ # @note Sequel is *not* based on ActiveModel, but supports the API we need, except for `persisted?`.
35
+ # @note Validations are enabled by default in versions < 4, but may change to disabled in v4 if ActiveModel is not present.
14
36
  module Sequel
37
+ # Called when this module is included in a model class.
38
+ #
39
+ # This method extends the base class with OmniAuth Identity functionality,
40
+ # including secure password support and authentication key validation.
41
+ #
42
+ # @param base [Class] the model class including this module
43
+ # @return [void]
15
44
  def self.included(base)
16
45
  base.class_eval do
17
46
  # NOTE: Using the deprecated :validations_class_methods because it defines
@@ -30,26 +59,59 @@ module OmniAuth
30
59
  has_secure_password(validations: OmniAuth::Identity::Version.major < 4)
31
60
 
32
61
  class << self
62
+ # @!method self.auth_key=(key)
63
+ # Sets the authentication key for the model and adds uniqueness validation.
64
+ #
65
+ # @param key [Symbol, String] the attribute to use as the authentication key
66
+ # @return [void]
67
+ # @example
68
+ # class User < Sequel::Model(:users)
69
+ # include OmniAuth::Identity::Models::Sequel
70
+ # self.auth_key = :email
71
+ # end
33
72
  def auth_key=(key)
34
73
  super
35
74
  # Sequel version of validates_uniqueness_of! Does not incur ActiveRecord dependency!
36
75
  validates_uniqueness_of(:key, case_sensitive: false)
37
76
  end
38
77
 
39
- # @param arguments [any] -
40
- # Filtering is probably the most common dataset modifying action done in Sequel.
41
- # Both the where and filter methods filter the dataset by modifying the dataset’s WHERE clause.
42
- # Both accept a wide variety of input formats, which are passed as arguments below.
43
- # See: https://sequel.jeremyevans.net/rdoc/files/doc/querying_rdoc.html#label-Filters
78
+ # @!method self.locate(arguments)
79
+ # Finds a record by the given search criteria.
80
+ #
81
+ # Filtering is probably the most common dataset modifying action done in Sequel.
82
+ # Both the where and filter methods filter the dataset by modifying the dataset's WHERE clause.
83
+ # Both accept a wide variety of input formats.
84
+ # See: https://sequel.jeremyevans.net/rdoc/files/doc/querying_rdoc.html#label-Filters
85
+ #
86
+ # @param arguments [any] the search criteria
87
+ # @return [Sequel::Model, nil] the first matching record or nil
88
+ # @example
89
+ # User.locate(email: 'user@example.com')
44
90
  def locate(arguments)
45
91
  where(arguments).first
46
92
  end
47
93
  end
48
94
 
95
+ # @!method persisted?
96
+ # Checks if the record exists in the database.
97
+ #
98
+ # @return [Boolean] true if the record exists, false otherwise
99
+ # @example
100
+ # user = User.new
101
+ # user.persisted? # => false
102
+ # user.save
103
+ # user.persisted? # => true
49
104
  def persisted?
50
105
  exists?
51
106
  end
52
107
 
108
+ # @!method save
109
+ # Saves the record to the database.
110
+ #
111
+ # @return [Boolean] true if saved successfully, false otherwise
112
+ # @example
113
+ # user = User.new(email: 'user@example.com', password: 'password')
114
+ # user.save # => true
53
115
  def save
54
116
  super
55
117
  end
@@ -9,21 +9,45 @@ module OmniAuth
9
9
  # include SecurePassword. The only difference is that instead of
10
10
  # using ActiveSupport::Concern, it checks to see if there is already
11
11
  # a has_secure_password method.
12
+ #
13
+ # Provides secure password hashing and authentication using BCrypt.
14
+ #
15
+ # @example Basic Usage
16
+ # class User
17
+ # include OmniAuth::Identity::SecurePassword
18
+ #
19
+ # has_secure_password
20
+ # end
21
+ #
22
+ # user = User.new(password: 'secret')
23
+ # user.authenticate('secret') # => user
12
24
  module SecurePassword
25
+ # Called when this module is included in a model class.
26
+ #
27
+ # Extends the base class with ClassMethods unless it already responds to has_secure_password.
28
+ #
29
+ # @param base [Class] the model class including this module
30
+ # @return [void]
13
31
  def self.included(base)
14
32
  base.extend(ClassMethods) unless base.respond_to?(:has_secure_password)
15
33
  end
16
34
 
35
+ # @!attribute [r] MAX_PASSWORD_LENGTH_ALLOWED
17
36
  # BCrypt hash function can handle maximum 72 bytes, and if we pass
18
37
  # password of length more than 72 bytes it ignores extra characters.
19
38
  # Hence need to put a restriction on password length.
39
+ # @return [Integer] The maximum allowed password length in bytes.
20
40
  MAX_PASSWORD_LENGTH_ALLOWED = BCrypt::Engine::MAX_SECRET_BYTESIZE
21
41
 
22
42
  class << self
43
+ # @!attribute [rw] min_cost
44
+ # Controls whether to use minimum cost for BCrypt hashing (for testing).
45
+ # @return [true, false]
23
46
  attr_accessor :min_cost # :nodoc:
24
47
  end
25
48
  self.min_cost = false
26
49
 
50
+ # Class-level methods for secure password functionality.
27
51
  module ClassMethods
28
52
  # Adds methods to set and authenticate against a BCrypt password.
29
53
  # This mechanism requires you to have a +XXX_digest+ attribute.
@@ -82,6 +106,10 @@ module OmniAuth
82
106
  # user.authenticate_recovery_password('42password') # => user
83
107
  # User.find_by(name: 'david')&.authenticate('notright') # => false
84
108
  # User.find_by(name: 'david')&.authenticate('mUc3m00RsqyRe') # => user
109
+ #
110
+ # @param attribute [Symbol, String] the attribute name for the password (default: :password)
111
+ # @param validations [true, false] whether to add validations (default: true)
112
+ # @return [void]
85
113
  def has_secure_password(attribute = :password, validations: true)
86
114
  # Load bcrypt gem only when has_secure_password is used.
87
115
  # This is to avoid ActiveModel (and by extension the entire framework)
@@ -121,7 +149,12 @@ module OmniAuth
121
149
  end
122
150
  end
123
151
 
152
+ # A module that defines instance methods for password handling.
153
+ # Methods are defined dynamically based on the attribute name.
124
154
  class InstanceMethodsOnActivation < Module
155
+ # Initializes the module with the password attribute name.
156
+ #
157
+ # @param attribute [Symbol, String] the password attribute name
125
158
  def initialize(attribute)
126
159
  attr_reader(attribute)
127
160
 
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Contains version information for the OmniAuth Identity gem.
3
4
  module OmniAuth
4
5
  module Identity
5
6
  module Version
6
- VERSION = "3.1.4"
7
+ # @!attribute [r] VERSION
8
+ # The current version of the omniauth-identity gem.
9
+ # @return [String]
10
+ VERSION = "3.1.5"
7
11
  end
8
12
  end
9
13
  end
@@ -18,19 +18,49 @@ end
18
18
 
19
19
  require "omniauth"
20
20
 
21
+ # The main OmniAuth module.
21
22
  module OmniAuth
23
+ # Container for OmniAuth strategy classes.
22
24
  module Strategies
25
+ # Autoload the Identity strategy.
23
26
  autoload :Identity, "omniauth/strategies/identity"
24
27
  end
25
28
 
29
+ # OmniAuth Identity provides a way to authenticate users using a username and password
30
+ # stored in your application's database. It supports multiple ORMs and provides
31
+ # secure password hashing.
32
+ #
33
+ # @example Basic Setup
34
+ # # In your Gemfile
35
+ # gem 'omniauth-identity'
36
+ #
37
+ # # In your OmniAuth configuration
38
+ # use OmniAuth::Strategies::Identity,
39
+ # fields: [:email],
40
+ # model: User
41
+ #
42
+ # @see OmniAuth::Strategies::Identity
43
+ # @see OmniAuth::Identity::Model
44
+ # @see OmniAuth::Identity::SecurePassword
26
45
  module Identity
46
+ # Autoload the Model module.
27
47
  autoload :Model, "omniauth/identity/model"
48
+ # Autoload the SecurePassword module.
28
49
  autoload :SecurePassword, "omniauth/identity/secure_password"
50
+
51
+ # Container for ORM-specific model adapters.
29
52
  module Models
53
+ # Autoload the ActiveRecord adapter.
30
54
  autoload :ActiveRecord, "omniauth/identity/models/active_record"
55
+ # Autoload the Mongoid adapter.
31
56
  autoload :Mongoid, "omniauth/identity/models/mongoid"
57
+ # Autoload the CouchPotato adapter.
32
58
  autoload :CouchPotatoModule, "omniauth/identity/models/couch_potato"
59
+ # Autoload the NoBrainer adapter.
33
60
  autoload :NoBrainer, "omniauth/identity/models/nobrainer"
61
+ # Autoload the ROM adapter.
62
+ autoload :Rom, "omniauth/identity/models/rom"
63
+ # Autoload the Sequel adapter.
34
64
  autoload :Sequel, "omniauth/identity/models/sequel"
35
65
  end
36
66
  end
@@ -5,27 +5,96 @@ module OmniAuth
5
5
  # The identity strategy allows you to provide simple internal
6
6
  # user authentication using the same process flow that you
7
7
  # use for external OmniAuth providers.
8
+ #
9
+ # @example Basic Setup
10
+ # use OmniAuth::Strategies::Identity,
11
+ # fields: [:email],
12
+ # model: User
13
+ #
14
+ # @example With Registration
15
+ # use OmniAuth::Strategies::Identity,
16
+ # fields: [:email, :name],
17
+ # model: User,
18
+ # enable_registration: true
19
+ #
20
+ # @see https://github.com/omniauth/omniauth-identity
8
21
  class Identity
22
+ # @!attribute [r] DEFAULT_REGISTRATION_FIELDS
23
+ # Default fields required for registration.
24
+ # @return [Array<Symbol>]
9
25
  DEFAULT_REGISTRATION_FIELDS = %i[password password_confirmation].freeze
10
26
  include OmniAuth::Strategy
27
+
28
+ # @!attribute [rw] fields
29
+ # The fields to collect for user registration.
30
+ # @return [Array<Symbol>]
11
31
  option :fields, %i[name email]
12
32
 
13
- # Primary Feature Switches:
33
+ # @!attribute [rw] enable_registration
34
+ # Whether to enable user registration functionality.
35
+ # @return [true, false]
14
36
  option :enable_registration, true # See #other_phase and #request_phase
37
+
38
+ # @!attribute [rw] enable_login
39
+ # Whether to enable login functionality.
40
+ # @return [true, false]
15
41
  option :enable_login, true # See #other_phase
16
42
 
17
- # Customization Options:
43
+ # @!attribute [rw] on_login
44
+ # Custom login handler. If provided, called instead of showing the default login form.
45
+ # @return [Proc, nil]
18
46
  option :on_login, nil # See #request_phase
47
+
48
+ # @!attribute [rw] on_validation
49
+ # Custom validation handler for registration.
50
+ # @return [Proc, nil]
19
51
  option :on_validation, nil # See #registration_phase
52
+
53
+ # @!attribute [rw] on_registration
54
+ # Custom registration handler. If provided, called instead of showing the default registration form.
55
+ # @return [Proc, nil]
20
56
  option :on_registration, nil # See #registration_phase
57
+
58
+ # @!attribute [rw] on_failed_registration
59
+ # Custom handler for failed registration.
60
+ # @return [Proc, nil]
21
61
  option :on_failed_registration, nil # See #registration_phase
62
+
63
+ # @!attribute [rw] locate_conditions
64
+ # Conditions for locating an identity during login.
65
+ # @return [Proc, Hash]
22
66
  option :locate_conditions, ->(req) { {model.auth_key => req.params["auth_key"]} }
67
+
68
+ # @!attribute [rw] create_identity_link_text
69
+ # Text for the link to create a new identity.
70
+ # @return [String]
23
71
  option :create_identity_link_text, "Create an Identity"
72
+
73
+ # @!attribute [rw] registration_failure_message
74
+ # Message to display on registration failure.
75
+ # @return [String]
24
76
  option :registration_failure_message, "One or more fields were invalid"
77
+
78
+ # @!attribute [rw] validation_failure_message
79
+ # Message to display on validation failure.
80
+ # @return [String]
25
81
  option :validation_failure_message, "Validation failed"
82
+
83
+ # @!attribute [rw] title
84
+ # Title for the login form.
85
+ # @return [String]
26
86
  option :title, "Identity Verification" # Title for Login Form
87
+
88
+ # @!attribute [rw] registration_form_title
89
+ # Title for the registration form.
90
+ # @return [String]
27
91
  option :registration_form_title, "Register Identity" # Title for Registration Form
28
92
 
93
+ # Handles the initial request phase.
94
+ #
95
+ # Shows the login form or calls the custom on_login handler.
96
+ #
97
+ # @return [Rack::Response] the response to send
29
98
  def request_phase
30
99
  if options[:on_login]
31
100
  options[:on_login].call(env)
@@ -34,12 +103,22 @@ module OmniAuth
34
103
  end
35
104
  end
36
105
 
106
+ # Handles the callback phase after login.
107
+ #
108
+ # Authenticates the user and calls super if successful.
109
+ #
110
+ # @return [void]
37
111
  def callback_phase
38
112
  return fail!(:invalid_credentials) unless identity
39
113
 
40
114
  super
41
115
  end
42
116
 
117
+ # Handles other phases like registration.
118
+ #
119
+ # Routes to registration or login based on the path and options.
120
+ #
121
+ # @return [void]
43
122
  def other_phase
44
123
  if options[:enable_registration] && on_registration_path?
45
124
  if request.get?
@@ -61,6 +140,10 @@ module OmniAuth
61
140
  end
62
141
  end
63
142
 
143
+ # Shows the registration form or calls the custom on_registration handler.
144
+ #
145
+ # @param validation_message [String, nil] message to display if validation failed
146
+ # @return [Rack::Response] the response to send
64
147
  def registration_form(validation_message = nil)
65
148
  if options[:on_registration]
66
149
  options[:on_registration].call(env)
@@ -69,6 +152,11 @@ module OmniAuth
69
152
  end
70
153
  end
71
154
 
155
+ # Handles the registration phase.
156
+ #
157
+ # Creates a new identity and saves it.
158
+ #
159
+ # @return [void]
72
160
  def registration_phase
73
161
  attributes = (options[:fields] + DEFAULT_REGISTRATION_FIELDS).each_with_object({}) do |k, h|
74
162
  h[k] = request.params[k.to_s]
@@ -92,17 +180,33 @@ module OmniAuth
92
180
  end
93
181
  end
94
182
 
183
+ # @!method uid
184
+ # Returns the unique identifier for the authenticated identity.
185
+ # @return [String]
95
186
  uid { identity.uid }
187
+
188
+ # @!method info
189
+ # Returns the info hash for the authenticated identity.
190
+ # @return [Hash]
96
191
  info { identity.info }
97
192
 
193
+ # Returns the path for registration.
194
+ #
195
+ # @return [String] the registration path
98
196
  def registration_path
99
197
  options[:registration_path] || "#{script_name}#{path_prefix}/#{name}/register"
100
198
  end
101
199
 
200
+ # Checks if the current request is for the registration path.
201
+ #
202
+ # @return [true, false]
102
203
  def on_registration_path?
103
204
  on_path?(registration_path)
104
205
  end
105
206
 
207
+ # Finds and authenticates the identity based on the request parameters.
208
+ #
209
+ # @return [Object, nil] the authenticated identity or nil
106
210
  def identity
107
211
  conditions = options[:locate_conditions]
108
212
  conditions = conditions.is_a?(Proc) ? instance_exec(request, &conditions).to_hash : conditions.to_hash
@@ -110,12 +214,18 @@ module OmniAuth
110
214
  @identity ||= model.authenticate(conditions, request.params["password"])
111
215
  end
112
216
 
217
+ # Returns the model class to use for identities.
218
+ #
219
+ # @return [Class] the identity model class
113
220
  def model
114
221
  options[:model] || ::Identity
115
222
  end
116
223
 
117
224
  private
118
225
 
226
+ # Builds the login form.
227
+ #
228
+ # @return [OmniAuth::Form] the login form
119
229
  def build_omniauth_login_form
120
230
  OmniAuth::Form.build(
121
231
  title: options[:title],
@@ -129,6 +239,10 @@ module OmniAuth
129
239
  end
130
240
  end
131
241
 
242
+ # Builds the registration form.
243
+ #
244
+ # @param validation_message [String, nil] message to display
245
+ # @return [OmniAuth::Form] the registration form
132
246
  def build_omniauth_registration_form(validation_message)
133
247
  OmniAuth::Form.build(title: options[:registration_form_title]) do |f|
134
248
  f.html("<p style='color:red'>#{validation_message}</p>") if validation_message
@@ -140,22 +254,26 @@ module OmniAuth
140
254
  end
141
255
  end
142
256
 
143
- # Validates the model before it is persisted
257
+ # Checks if validation is enabled.
144
258
  #
145
- # @return [truthy or falsey] :on_validation option is truthy or falsey
259
+ # @return [true, false]
146
260
  def validating?
147
261
  !!options[:on_validation]
148
262
  end
149
263
 
150
- # Validates the model before it is persisted
264
+ # Validates the identity using the custom validation handler.
151
265
  #
152
- # @return [true or false] result of :on_validation call
266
+ # @return [true, false] result of validation
153
267
  def valid?
154
268
  # on_validation may run a Captcha or other validation mechanism
155
269
  # Must return true when validation passes, false otherwise
156
270
  !!options[:on_validation].call(env: env)
157
271
  end
158
272
 
273
+ # Handles registration failure.
274
+ #
275
+ # @param message [String] the failure message
276
+ # @return [void]
159
277
  def registration_failure(message)
160
278
  if options[:on_failed_registration]
161
279
  options[:on_failed_registration].call(env)
@@ -164,6 +282,9 @@ module OmniAuth
164
282
  end
165
283
  end
166
284
 
285
+ # Handles the result of registration.
286
+ #
287
+ # @return [void]
167
288
  def registration_result
168
289
  if @identity.persisted?
169
290
  env["PATH_INFO"] = "#{path_prefix}/#{name}/callback"
data.tar.gz.sig CHANGED
Binary file