Class: PasskeyAuth::MagicLink
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- PasskeyAuth::MagicLink
- Defined in:
- app/models/passkey_auth/magic_link.rb,
app/models/passkey_auth/magic_link/short_code.rb
Defined Under Namespace
Classes: ShortCode
Constant Summary collapse
- PURPOSES =
%w[login recovery email_confirmation].freeze
Class Method Summary collapse
- .cleanup_expired ⇒ Object
- .consume_by_email_and_code(email, code, ip:, user_agent:) ⇒ Object
- .consume_by_token(token, ip:, user_agent:) ⇒ Object
- .generate_short_code ⇒ Object
Instance Method Summary collapse
- #expired? ⇒ Boolean
- #invalid_reason ⇒ Object
- #use!(ip: nil, user_agent: nil) ⇒ Object
- #used? ⇒ Boolean
- #valid_for_use? ⇒ Boolean
Class Method Details
.cleanup_expired ⇒ Object
71 72 73 |
# File 'app/models/passkey_auth/magic_link.rb', line 71 def self.cleanup_expired expired.destroy_all end |
.consume_by_email_and_code(email, code, ip:, user_agent:) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'app/models/passkey_auth/magic_link.rb', line 54 def self.consume_by_email_and_code(email, code, ip:, user_agent:) cleaned_code = code&.upcase&.strip cleaned_email = email&.downcase&.strip # Use configured email attribute email_attr = PasskeyAuth.user_email_attribute link = includes(:user).find_by(short_code: cleaned_code, user: { email_attr => cleaned_email }) return unless link link.use!(ip: ip, user_agent: user_agent) ? link : nil end |
.consume_by_token(token, ip:, user_agent:) ⇒ Object
46 47 48 49 50 51 52 |
# File 'app/models/passkey_auth/magic_link.rb', line 46 def self.consume_by_token(token, ip:, user_agent:) link = find_by(token: token) return unless link link.use!(ip: ip, user_agent: user_agent) ? link : nil end |
.generate_short_code ⇒ Object
67 68 69 |
# File 'app/models/passkey_auth/magic_link.rb', line 67 def self.generate_short_code ShortCode.generate end |
Instance Method Details
#expired? ⇒ Boolean
22 23 24 |
# File 'app/models/passkey_auth/magic_link.rb', line 22 def expired? expires_at <= Time.current end |
#invalid_reason ⇒ Object
75 76 77 78 79 80 81 82 83 |
# File 'app/models/passkey_auth/magic_link.rb', line 75 def invalid_reason if expired? :expired elsif used? :used else :generic end end |
#use!(ip: nil, user_agent: nil) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 |
# File 'app/models/passkey_auth/magic_link.rb', line 34 def use!(ip: nil, user_agent: nil) with_lock do return false unless valid_for_use? update!( used_at: Time.current, ip_address: ip, user_agent: user_agent ) end end |
#used? ⇒ Boolean
26 27 28 |
# File 'app/models/passkey_auth/magic_link.rb', line 26 def used? used_at.present? end |
#valid_for_use? ⇒ Boolean
30 31 32 |
# File 'app/models/passkey_auth/magic_link.rb', line 30 def valid_for_use? !expired? && !used? end |