omniauth-identity 3.1.4 → 3.2.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +152 -4
- data/CITATION.cff +20 -0
- data/CODE_OF_CONDUCT.md +3 -4
- data/CONTRIBUTING.md +177 -116
- data/FUNDING.md +74 -0
- data/LICENSE.md +10 -0
- data/README.md +349 -195
- data/RUBOCOP.md +71 -0
- data/SECURITY.md +7 -31
- data/certs/pboling.pem +27 -0
- data/lib/omniauth/identity/model.rb +51 -11
- data/lib/omniauth/identity/models/active_record.rb +55 -9
- data/lib/omniauth/identity/models/couch_potato.rb +75 -19
- data/lib/omniauth/identity/models/mongoid.rb +63 -14
- data/lib/omniauth/identity/models/nobrainer.rb +63 -15
- data/lib/omniauth/identity/models/rom.rb +164 -0
- data/lib/omniauth/identity/models/sequel.rb +104 -40
- data/lib/omniauth/identity/secure_password.rb +41 -6
- data/lib/omniauth/identity/version.rb +10 -2
- data/lib/omniauth/identity.rb +41 -0
- data/lib/omniauth/strategies/identity.rb +127 -6
- data/sig/omniauth/identity/version.rbs +8 -0
- data.tar.gz.sig +0 -0
- metadata +202 -49
- metadata.gz.sig +0 -0
- data/LICENSE.txt +0 -24
data/RUBOCOP.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# RuboCop Usage Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A tale of two RuboCop plugin gems.
|
|
6
|
+
|
|
7
|
+
### RuboCop Gradual
|
|
8
|
+
|
|
9
|
+
This project uses `rubocop_gradual` instead of vanilla RuboCop for code style checking. The `rubocop_gradual` tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file.
|
|
10
|
+
|
|
11
|
+
### RuboCop LTS
|
|
12
|
+
|
|
13
|
+
This project uses `rubocop-lts` to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2.
|
|
14
|
+
RuboCop rules are meticulously configured by the `rubocop-lts` family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more.
|
|
15
|
+
|
|
16
|
+
## Checking RuboCop Violations
|
|
17
|
+
|
|
18
|
+
To check for RuboCop violations in this project, always use:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
bundle exec rake rubocop_gradual:check
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Do not use** the standard RuboCop commands like:
|
|
25
|
+
- `bundle exec rubocop`
|
|
26
|
+
- `rubocop`
|
|
27
|
+
|
|
28
|
+
## Understanding the Lock File
|
|
29
|
+
|
|
30
|
+
The `.rubocop_gradual.lock` file tracks all current RuboCop violations in the project. This allows the team to:
|
|
31
|
+
|
|
32
|
+
1. Prevent new violations while gradually fixing existing ones
|
|
33
|
+
2. Track progress on code style improvements
|
|
34
|
+
3. Ensure CI builds don't fail due to pre-existing violations
|
|
35
|
+
|
|
36
|
+
## Common Commands
|
|
37
|
+
|
|
38
|
+
- **Check violations**
|
|
39
|
+
- `bundle exec rake rubocop_gradual`
|
|
40
|
+
- `bundle exec rake rubocop_gradual:check`
|
|
41
|
+
- **(Safe) Autocorrect violations, and update lockfile if no new violations**
|
|
42
|
+
- `bundle exec rake rubocop_gradual:autocorrect`
|
|
43
|
+
- **Force update the lock file (w/o autocorrect) to match violations present in code**
|
|
44
|
+
- `bundle exec rake rubocop_gradual:force_update`
|
|
45
|
+
|
|
46
|
+
## Workflow
|
|
47
|
+
|
|
48
|
+
1. Before submitting a PR, run `bundle exec rake rubocop_gradual:autocorrect`
|
|
49
|
+
a. or just the default `bundle exec rake`, as autocorrection is a pre-requisite of the default task.
|
|
50
|
+
2. If there are new violations, either:
|
|
51
|
+
- Fix them in your code
|
|
52
|
+
- Run `bundle exec rake rubocop_gradual:force_update` to update the lock file (only for violations you can't fix immediately)
|
|
53
|
+
3. Commit the updated `.rubocop_gradual.lock` file along with your changes
|
|
54
|
+
|
|
55
|
+
## Never add inline RuboCop disables
|
|
56
|
+
|
|
57
|
+
Do not add inline `rubocop:disable` / `rubocop:enable` comments anywhere in the codebase (including specs, except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways:
|
|
58
|
+
|
|
59
|
+
- Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in `.rubocop.yml`) to exclude a rule for a path or file pattern when it makes sense project-wide.
|
|
60
|
+
- Temporary exceptions while improving code: record the current violations in `.rubocop_gradual.lock` via the gradual workflow:
|
|
61
|
+
- `bundle exec rake rubocop_gradual:autocorrect` (preferred; will autocorrect what it can and update the lock only if no new violations were introduced)
|
|
62
|
+
- If needed, `bundle exec rake rubocop_gradual:force_update` (as a last resort when you cannot fix the newly reported violations immediately)
|
|
63
|
+
|
|
64
|
+
In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect `described_class` to be used in specs that target a specific class under test.
|
|
65
|
+
|
|
66
|
+
## Benefits of rubocop_gradual
|
|
67
|
+
|
|
68
|
+
- Allows incremental adoption of code style rules
|
|
69
|
+
- Prevents CI failures due to pre-existing violations
|
|
70
|
+
- Provides a clear record of code style debt
|
|
71
|
+
- Enables focused efforts on improving code quality over time
|
data/SECURITY.md
CHANGED
|
@@ -2,13 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Supported Versions
|
|
4
4
|
|
|
5
|
-
| Version
|
|
6
|
-
|
|
7
|
-
| 3.1.
|
|
8
|
-
| 3.0.x | ❌ |
|
|
9
|
-
| 2.x | ❌ |
|
|
10
|
-
| 1.x | ❌ |
|
|
11
|
-
| 0.x | ❌ |
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
|----------|-----------|
|
|
7
|
+
| 3.1.latest | ✅ |
|
|
12
8
|
|
|
13
9
|
## Security contact information
|
|
14
10
|
|
|
@@ -18,28 +14,8 @@ Tidelift will coordinate the fix and disclosure.
|
|
|
18
14
|
|
|
19
15
|
## Additional Support
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
If you are interested in support for versions older than the latest release,
|
|
18
|
+
please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
|
|
19
|
+
or find other sponsorship links in the [README].
|
|
23
20
|
|
|
24
|
-
[
|
|
25
|
-
|
|
26
|
-
[⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay
|
|
27
|
-
[⛳liberapay]: https://liberapay.com/pboling/donate
|
|
28
|
-
[🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
|
|
29
|
-
[🖇sponsor]: https://github.com/sponsors/pboling
|
|
30
|
-
[🖇polar-img]: https://img.shields.io/badge/polar-donate-yellow.svg
|
|
31
|
-
[🖇polar]: https://polar.sh/pboling
|
|
32
|
-
[🖇kofi-img]: https://img.shields.io/badge/a_more_different_coffee-✓-yellow.svg
|
|
33
|
-
[🖇kofi]: https://ko-fi.com/O5O86SNP4
|
|
34
|
-
[🖇patreon-img]: https://img.shields.io/badge/patreon-donate-yellow.svg
|
|
35
|
-
[🖇patreon]: https://patreon.com/galtzo
|
|
36
|
-
[🖇buyme]: https://www.buymeacoffee.com/pboling
|
|
37
|
-
[🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-yellow.svg?style=flat
|
|
38
|
-
|
|
39
|
-
## Enterprise Support
|
|
40
|
-
|
|
41
|
-
Available as part of the Tidelift Subscription.
|
|
42
|
-
|
|
43
|
-
The maintainers of this library and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers for the exact packages you use. [Learn more.][tidelift-ref]
|
|
44
|
-
|
|
45
|
-
[tidelift-ref]: https://tidelift.com/subscription/pkg/rubygems-omniauth-identity?utm_source=rubygems-omniauth-identity&utm_medium=referral&utm_campaign=enterprise&utm_term=repo
|
|
21
|
+
[README]: README.md
|
data/certs/pboling.pem
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
|
|
3
|
+
ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
|
|
4
|
+
A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
|
|
5
|
+
DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
|
|
6
|
+
LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
|
|
7
|
+
uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
|
|
8
|
+
LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
|
|
9
|
+
mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
|
|
10
|
+
coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
|
|
11
|
+
FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
|
|
12
|
+
yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
|
|
13
|
+
to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
|
|
14
|
+
qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
|
|
15
|
+
fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
|
|
16
|
+
HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
|
|
17
|
+
A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
|
|
18
|
+
ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
|
|
19
|
+
wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
|
|
20
|
+
L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
|
|
21
|
+
GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
|
|
22
|
+
kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
|
|
23
|
+
QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
|
|
24
|
+
0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
|
|
25
|
+
DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
|
|
26
|
+
L9nRqA==
|
|
27
|
+
-----END CERTIFICATE-----
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "auth_sanitizer/loader"
|
|
4
|
+
|
|
3
5
|
module OmniAuth
|
|
4
6
|
module Identity
|
|
7
|
+
AUTH_SANITIZER = AuthSanitizer::Loader.load_isolated unless const_defined?(:AUTH_SANITIZER, false)
|
|
8
|
+
|
|
5
9
|
# This module provides an include-able interface for implementing the
|
|
6
10
|
# necessary API for OmniAuth Identity to properly locate identities
|
|
7
11
|
# and provide all necessary information.
|
|
@@ -9,22 +13,41 @@ module OmniAuth
|
|
|
9
13
|
# All methods marked as abstract must be implemented in the
|
|
10
14
|
# including class for things to work properly.
|
|
11
15
|
#
|
|
12
|
-
### Singleton API
|
|
16
|
+
# ### Singleton API
|
|
13
17
|
#
|
|
14
18
|
# * locate(key)
|
|
15
19
|
# * create(*args) - Deprecated in v3.0.5; Will be removed in v4.0
|
|
16
20
|
#
|
|
17
|
-
### Instance API
|
|
21
|
+
# ### Instance API
|
|
18
22
|
#
|
|
19
23
|
# * save
|
|
20
24
|
# * persisted?
|
|
21
25
|
# * authenticate(password)
|
|
22
26
|
#
|
|
27
|
+
# @example Including the Model
|
|
28
|
+
# class User
|
|
29
|
+
# include OmniAuth::Identity::Model
|
|
30
|
+
# # Implement required methods...
|
|
31
|
+
# end
|
|
23
32
|
module Model
|
|
33
|
+
# @!attribute [r] SCHEMA_ATTRIBUTES
|
|
34
|
+
# Standard OmniAuth schema attributes that may be stored in the model.
|
|
35
|
+
# @return [Array<String>] List of attribute names.
|
|
24
36
|
SCHEMA_ATTRIBUTES = %w[name email nickname first_name last_name location description image phone].freeze
|
|
37
|
+
FILTERED_INSPECT_ATTRIBUTES = %i[password password_confirmation password_digest].freeze
|
|
25
38
|
|
|
26
39
|
class << self
|
|
40
|
+
# Called when this module is included in a model class.
|
|
41
|
+
#
|
|
42
|
+
# Extends the base class with ClassMethods and includes necessary APIs
|
|
43
|
+
# if they are not already defined.
|
|
44
|
+
#
|
|
45
|
+
# @param base [Class] the model class including this module
|
|
46
|
+
# @return [void]
|
|
27
47
|
def included(base)
|
|
48
|
+
base.include(OmniAuth::Identity::AUTH_SANITIZER::FilteredAttributes)
|
|
49
|
+
base.prepend(OmniAuth::Identity::AUTH_SANITIZER::FilteredAttributes)
|
|
50
|
+
base.filtered_attributes(*FILTERED_INSPECT_ATTRIBUTES)
|
|
28
51
|
base.extend(ClassMethods)
|
|
29
52
|
base.extend(ClassCreateApi) unless base.respond_to?(:create)
|
|
30
53
|
i_methods = base.instance_methods
|
|
@@ -33,12 +56,16 @@ module OmniAuth
|
|
|
33
56
|
end
|
|
34
57
|
end
|
|
35
58
|
|
|
59
|
+
# Class-level methods for OmniAuth Identity models.
|
|
36
60
|
module ClassMethods
|
|
61
|
+
AUTH_KEY_MUTEX = Mutex.new
|
|
62
|
+
private_constant :AUTH_KEY_MUTEX
|
|
63
|
+
|
|
37
64
|
# Authenticate a user with the given key and password.
|
|
38
65
|
#
|
|
39
66
|
# @param [String] conditions The unique login key provided for a given identity.
|
|
40
67
|
# @param [String] password The presumed password for the identity.
|
|
41
|
-
# @return [Model, false] An instance of the identity model class.
|
|
68
|
+
# @return [Model, false] An instance of the identity model class or false if authentication fails.
|
|
42
69
|
def authenticate(conditions, password)
|
|
43
70
|
instance = locate(conditions)
|
|
44
71
|
return false unless instance
|
|
@@ -46,19 +73,28 @@ module OmniAuth
|
|
|
46
73
|
instance.authenticate(password)
|
|
47
74
|
end
|
|
48
75
|
|
|
76
|
+
def inherited(subclass)
|
|
77
|
+
super if defined?(super)
|
|
78
|
+
subclass.filtered_attributes(*filtered_attribute_names) if subclass.respond_to?(:filtered_attributes)
|
|
79
|
+
end
|
|
80
|
+
|
|
49
81
|
# Used to set or retrieve the method that will be used to get
|
|
50
82
|
# and set the user-supplied authentication key.
|
|
83
|
+
#
|
|
84
|
+
# @param method [String, Symbol, false] The method name to set, or false to retrieve.
|
|
51
85
|
# @return [String] The method name.
|
|
52
86
|
def auth_key(method = false)
|
|
53
|
-
|
|
54
|
-
|
|
87
|
+
AUTH_KEY_MUTEX.synchronize do
|
|
88
|
+
@auth_key = method.to_s unless method == false
|
|
89
|
+
@auth_key = nil if !defined?(@auth_key) || @auth_key == ""
|
|
55
90
|
|
|
56
|
-
|
|
91
|
+
@auth_key || "email"
|
|
92
|
+
end
|
|
57
93
|
end
|
|
58
94
|
|
|
59
95
|
# Locate an identity given its unique login key.
|
|
60
96
|
#
|
|
61
|
-
# @abstract
|
|
97
|
+
# @abstract Subclasses must implement this method.
|
|
62
98
|
# @param [String] _key The unique login key.
|
|
63
99
|
# @return [Model] An instance of the identity model class.
|
|
64
100
|
def locate(_key)
|
|
@@ -66,6 +102,7 @@ module OmniAuth
|
|
|
66
102
|
end
|
|
67
103
|
end
|
|
68
104
|
|
|
105
|
+
# Provides a create method for models that don't have one.
|
|
69
106
|
module ClassCreateApi
|
|
70
107
|
# Persists a new Identity object to the ORM.
|
|
71
108
|
# Only included if the class doesn't define create, as a reminder to define create.
|
|
@@ -81,6 +118,7 @@ module OmniAuth
|
|
|
81
118
|
end
|
|
82
119
|
end
|
|
83
120
|
|
|
121
|
+
# Provides a save method for models that don't have one.
|
|
84
122
|
module InstanceSaveApi
|
|
85
123
|
# Persists a new Identity object to the ORM.
|
|
86
124
|
# Default raises an error. Override as needed per ORM.
|
|
@@ -88,6 +126,7 @@ module OmniAuth
|
|
|
88
126
|
# since it is a pattern many ORMs follow
|
|
89
127
|
#
|
|
90
128
|
# @abstract
|
|
129
|
+
# @param _options [Hash] Options for saving.
|
|
91
130
|
# @return [Model] An instance of the identity model class.
|
|
92
131
|
# @since 3.0.5
|
|
93
132
|
def save(**_options, &_block)
|
|
@@ -95,12 +134,13 @@ module OmniAuth
|
|
|
95
134
|
end
|
|
96
135
|
end
|
|
97
136
|
|
|
137
|
+
# Provides a persisted? method for models that don't have one.
|
|
98
138
|
module InstancePersistedApi
|
|
99
139
|
# Checks if the Identity object is persisted in the ORM.
|
|
100
140
|
# Default raises an error. Override as needed per ORM.
|
|
101
141
|
#
|
|
102
142
|
# @abstract
|
|
103
|
-
# @return [true
|
|
143
|
+
# @return [true, false] true if object exists, false if not.
|
|
104
144
|
# @since 3.0.5
|
|
105
145
|
def persisted?
|
|
106
146
|
raise NotImplementedError
|
|
@@ -110,9 +150,9 @@ module OmniAuth
|
|
|
110
150
|
# Returns self if the provided password is correct, false
|
|
111
151
|
# otherwise.
|
|
112
152
|
#
|
|
113
|
-
# @abstract
|
|
153
|
+
# @abstract Subclasses must implement this method.
|
|
114
154
|
# @param [String] _password The password to check.
|
|
115
|
-
# @return [self
|
|
155
|
+
# @return [self, false] Self if authenticated, false if not.
|
|
116
156
|
def authenticate(_password)
|
|
117
157
|
raise NotImplementedError
|
|
118
158
|
end
|
|
@@ -152,7 +192,7 @@ module OmniAuth
|
|
|
152
192
|
# @param [String] value The value to which the auth key should be
|
|
153
193
|
# set.
|
|
154
194
|
def auth_key=(value)
|
|
155
|
-
auth_key_setter = "#{self.class.auth_key}="
|
|
195
|
+
auth_key_setter = :"#{self.class.auth_key}="
|
|
156
196
|
if respond_to?(auth_key_setter)
|
|
157
197
|
send(auth_key_setter, value)
|
|
158
198
|
else
|
|
@@ -6,8 +6,34 @@ module OmniAuth
|
|
|
6
6
|
module Identity
|
|
7
7
|
module Models
|
|
8
8
|
# ActiveRecord is an ORM for MySQL, PostgreSQL, and SQLite3:
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# https://guides.rubyonrails.org/active_record_basics.html
|
|
10
|
+
#
|
|
11
|
+
# This class provides a base for OmniAuth Identity models using ActiveRecord,
|
|
12
|
+
# including secure password handling and authentication key management.
|
|
13
|
+
#
|
|
14
|
+
# @example Usage
|
|
15
|
+
# class User < OmniAuth::Identity::Models::ActiveRecord
|
|
16
|
+
# # Add your fields here, e.g.:
|
|
17
|
+
# # self.table_name = 'users'
|
|
18
|
+
# # has_many :posts
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# # Migration example:
|
|
22
|
+
# # create_table :users do |t|
|
|
23
|
+
# # t.string :email, null: false
|
|
24
|
+
# # t.string :password_digest, null: false
|
|
25
|
+
# # t.timestamps
|
|
26
|
+
# # end
|
|
27
|
+
#
|
|
28
|
+
# user = User.new(email: 'user@example.com', password: 'password')
|
|
29
|
+
# user.save
|
|
30
|
+
#
|
|
31
|
+
# # Authenticate a user
|
|
32
|
+
# authenticated_user = User.locate(email: 'user@example.com')
|
|
33
|
+
# authenticated_user.authenticate('password') # => user or false
|
|
34
|
+
#
|
|
35
|
+
# @note ActiveRecord is based on ActiveModel, so validations are enabled by default.
|
|
36
|
+
# @note This is an abstract class; inherit from it to create your user model.
|
|
11
37
|
class ActiveRecord < ::ActiveRecord::Base
|
|
12
38
|
include ::OmniAuth::Identity::Model
|
|
13
39
|
include ::OmniAuth::Identity::SecurePassword
|
|
@@ -16,14 +42,34 @@ module OmniAuth
|
|
|
16
42
|
# validations: true (default) incurs a dependency on ActiveModel, but ActiveRecord is ActiveModel based.
|
|
17
43
|
has_secure_password
|
|
18
44
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
45
|
+
# @!method self.auth_key=(key)
|
|
46
|
+
# Sets the authentication key for the model and adds uniqueness validation.
|
|
47
|
+
#
|
|
48
|
+
# @param key [Symbol, String] the attribute to use as the authentication key
|
|
49
|
+
# @return [void]
|
|
50
|
+
# @example
|
|
51
|
+
# class User < OmniAuth::Identity::Models::ActiveRecord
|
|
52
|
+
# self.auth_key = :email
|
|
53
|
+
# end
|
|
54
|
+
class << self
|
|
55
|
+
def auth_key=(key)
|
|
56
|
+
super
|
|
57
|
+
validates_uniqueness_of(key, case_sensitive: false)
|
|
58
|
+
end
|
|
23
59
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
60
|
+
# @!method self.locate(search_hash)
|
|
61
|
+
# Finds a record by the given search criteria.
|
|
62
|
+
#
|
|
63
|
+
# If the model has a 'provider' column, it defaults to 'identity'.
|
|
64
|
+
#
|
|
65
|
+
# @param search_hash [Hash] the attributes to search for
|
|
66
|
+
# @return [ActiveRecord::Base, nil] the first matching record or nil
|
|
67
|
+
# @example
|
|
68
|
+
# User.locate(email: 'user@example.com')
|
|
69
|
+
def locate(search_hash)
|
|
70
|
+
search_hash = search_hash.reverse_merge!("provider" => "identity") if column_names.include?("provider")
|
|
71
|
+
where(search_hash).first
|
|
72
|
+
end
|
|
27
73
|
end
|
|
28
74
|
end
|
|
29
75
|
end
|
|
@@ -6,30 +6,86 @@ module OmniAuth
|
|
|
6
6
|
module Identity
|
|
7
7
|
module Models
|
|
8
8
|
# CouchPotato is an ORM adapter for CouchDB:
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
9
|
+
# https://github.com/langalex/couch_potato
|
|
10
|
+
#
|
|
11
|
+
# This module provides OmniAuth Identity functionality for CouchPotato models,
|
|
12
|
+
# including secure password handling and authentication key management.
|
|
13
|
+
#
|
|
14
|
+
# @example Usage
|
|
15
|
+
# class User
|
|
16
|
+
# include CouchPotato::Persistence
|
|
17
|
+
#
|
|
18
|
+
# include OmniAuth::Identity::Models::CouchPotatoModule
|
|
19
|
+
#
|
|
20
|
+
# property :email
|
|
21
|
+
# property :password_digest
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# user = User.new(email: 'user@example.com', password: 'password')
|
|
25
|
+
# user.save
|
|
26
|
+
#
|
|
27
|
+
# # Authenticate a user
|
|
28
|
+
# authenticated_user = User.locate(email: 'user@example.com')
|
|
29
|
+
# authenticated_user.authenticate('password') # => user or false
|
|
30
|
+
#
|
|
31
|
+
# @note CouchPotato is based on ActiveModel, so validations are enabled by default.
|
|
32
|
+
# @note CouchPotato::Persistence must be included before OmniAuth::Identity::Models::CouchPotatoModule.
|
|
33
|
+
# @note Includes "Module" in the name for invalid legacy reasons. Rename only with a major version bump.
|
|
13
34
|
module CouchPotatoModule
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
35
|
+
class << self
|
|
36
|
+
# Called when this module is included in a model class.
|
|
37
|
+
#
|
|
38
|
+
# This method extends the base class with OmniAuth Identity functionality,
|
|
39
|
+
# including secure password support and authentication key validation.
|
|
40
|
+
#
|
|
41
|
+
# @param base [Class] the model class including this module
|
|
42
|
+
# @return [void]
|
|
43
|
+
def included(base)
|
|
44
|
+
base.class_eval do
|
|
45
|
+
include(::OmniAuth::Identity::Model)
|
|
46
|
+
include(::OmniAuth::Identity::SecurePassword)
|
|
18
47
|
|
|
19
|
-
|
|
20
|
-
|
|
48
|
+
# validations: true (default) incurs a dependency on ActiveModel, but CouchPotato is ActiveModel based.
|
|
49
|
+
has_secure_password
|
|
21
50
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
51
|
+
class << self
|
|
52
|
+
# @!method self.auth_key=(key)
|
|
53
|
+
# Sets the authentication key for the model and adds uniqueness validation.
|
|
54
|
+
#
|
|
55
|
+
# @param key [Symbol, String] the attribute to use as the authentication key
|
|
56
|
+
# @return [void]
|
|
57
|
+
# @example
|
|
58
|
+
# class User
|
|
59
|
+
# include OmniAuth::Identity::Models::CouchPotatoModule
|
|
60
|
+
# self.auth_key = :email
|
|
61
|
+
# end
|
|
62
|
+
def auth_key=(key)
|
|
63
|
+
super
|
|
64
|
+
validates_uniqueness_of(key, case_sensitive: false)
|
|
65
|
+
end
|
|
26
66
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
67
|
+
# @!method self.locate(search_hash)
|
|
68
|
+
# Finds a record by the given search criteria.
|
|
69
|
+
#
|
|
70
|
+
# @param search_hash [Hash] the attributes to search for
|
|
71
|
+
# @return [Object, nil] the first matching record or nil
|
|
72
|
+
# @example
|
|
73
|
+
# User.locate(email: 'user@example.com')
|
|
74
|
+
def locate(search_hash)
|
|
75
|
+
where(search_hash).first
|
|
76
|
+
end
|
|
77
|
+
end
|
|
30
78
|
|
|
31
|
-
|
|
32
|
-
|
|
79
|
+
# @!method save
|
|
80
|
+
# Saves the document to the CouchDB database.
|
|
81
|
+
#
|
|
82
|
+
# @return [Boolean] true if saved successfully, false otherwise
|
|
83
|
+
# @example
|
|
84
|
+
# user = User.new(email: 'user@example.com', password: 'password')
|
|
85
|
+
# user.save # => true
|
|
86
|
+
def save
|
|
87
|
+
CouchPotato.database.save_document(self)
|
|
88
|
+
end
|
|
33
89
|
end
|
|
34
90
|
end
|
|
35
91
|
end
|
|
@@ -6,24 +6,73 @@ module OmniAuth
|
|
|
6
6
|
module Identity
|
|
7
7
|
module Models
|
|
8
8
|
# Mongoid is an ORM adapter for MongoDB:
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# https://github.com/mongodb/mongoid
|
|
10
|
+
#
|
|
11
|
+
# This module provides OmniAuth Identity functionality for Mongoid models,
|
|
12
|
+
# including secure password handling and authentication key management.
|
|
13
|
+
#
|
|
14
|
+
# @example Usage
|
|
15
|
+
# class User
|
|
16
|
+
# include Mongoid::Document
|
|
17
|
+
#
|
|
18
|
+
# include OmniAuth::Identity::Models::Mongoid
|
|
19
|
+
#
|
|
20
|
+
# field :email, type: String
|
|
21
|
+
# field :password_digest, type: String
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# user = User.new(email: 'user@example.com', password: 'password')
|
|
25
|
+
# user.save
|
|
26
|
+
#
|
|
27
|
+
# # Authenticate a user
|
|
28
|
+
# authenticated_user = User.locate(email: 'user@example.com')
|
|
29
|
+
# authenticated_user.authenticate('password') # => user or false
|
|
30
|
+
#
|
|
31
|
+
# @note Mongoid is based on ActiveModel, so validations are enabled by default.
|
|
11
32
|
module Mongoid
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
33
|
+
class << self
|
|
34
|
+
# Called when this module is included in a model class.
|
|
35
|
+
#
|
|
36
|
+
# This method extends the base class with OmniAuth Identity functionality,
|
|
37
|
+
# including secure password support and authentication key validation.
|
|
38
|
+
#
|
|
39
|
+
# @param base [Class] the model class including this module
|
|
40
|
+
# @return [void]
|
|
41
|
+
def included(base)
|
|
42
|
+
base.class_eval do
|
|
43
|
+
include(::OmniAuth::Identity::Model)
|
|
44
|
+
include(::OmniAuth::Identity::SecurePassword)
|
|
16
45
|
|
|
17
|
-
|
|
18
|
-
|
|
46
|
+
# validations: true (default) incurs a dependency on ActiveModel, but Mongoid is ActiveModel based.
|
|
47
|
+
has_secure_password
|
|
19
48
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
49
|
+
class << self
|
|
50
|
+
# @!method self.auth_key=(key)
|
|
51
|
+
# Sets the authentication key for the model and adds uniqueness validation.
|
|
52
|
+
#
|
|
53
|
+
# @param key [Symbol, String] the attribute to use as the authentication key
|
|
54
|
+
# @return [void]
|
|
55
|
+
# @example
|
|
56
|
+
# class User
|
|
57
|
+
# include OmniAuth::Identity::Models::Mongoid
|
|
58
|
+
# self.auth_key = :email
|
|
59
|
+
# end
|
|
60
|
+
def auth_key=(key)
|
|
61
|
+
super
|
|
62
|
+
validates_uniqueness_of(key, case_sensitive: false)
|
|
63
|
+
end
|
|
24
64
|
|
|
25
|
-
|
|
26
|
-
|
|
65
|
+
# @!method self.locate(search_hash)
|
|
66
|
+
# Finds a record by the given search criteria.
|
|
67
|
+
#
|
|
68
|
+
# @param search_hash [Hash] the attributes to search for
|
|
69
|
+
# @return [Mongoid::Document, nil] the first matching record or nil
|
|
70
|
+
# @example
|
|
71
|
+
# User.locate(email: 'user@example.com')
|
|
72
|
+
def locate(search_hash)
|
|
73
|
+
where(search_hash).first
|
|
74
|
+
end
|
|
75
|
+
end
|
|
27
76
|
end
|
|
28
77
|
end
|
|
29
78
|
end
|