-
Notifications
You must be signed in to change notification settings - Fork 35
/
magic_link_authenticatable.rb
135 lines (116 loc) · 4.64 KB
/
magic_link_authenticatable.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
require 'devise/strategies/magic_link_authenticatable'
require 'devise/hooks/magic_link_authenticatable'
module Devise
module Models
module MagicLinkAuthenticatable
extend ActiveSupport::Concern
# Models using the :database_authenticatable strategy will already
# have #password_required? and #password defined - we will defer
# to those methods if they already exist so that people can use
# both strategies together. Otherwise, for :magic_link_authenticatable-
# only users, we define them in order to disable password validations:
unless instance_methods.include?(:password_required?)
def password_required?
false
end
end
unless instance_methods.include?(:password)
# Not having a #password method breaks the :validatable module
#
# NOTE I proposed a change to Devise to fix this:
# https://github.com/heartcombo/devise/issues/5346#issuecomment-822022834
# As of yet it hasn't been accepted due to unknowns of the legacy code's purpose
def password
nil
end
end
def encode_passwordless_token(*args, **kwargs)
self.class.passwordless_tokenizer_class.encode(self, *args, **kwargs)
end
def send_magic_link(remember_me: false, **kwargs)
token = self.encode_passwordless_token
send_devise_notification(:magic_link, token, remember_me, **kwargs)
end
# A callback initiated after successfully authenticating. This can be
# used to insert your own logic that is only run after the user successfully
# authenticates.
#
# Example:
#
# def after_magic_link_authentication
# self.update_attribute(:invite_code, nil)
# end
#
def after_magic_link_authentication
end
# Set this to false to disable magic link auth for this model instance.
# Magic links will still be generated by the sign-in page, but visiting
# them will instead display an error message.
def active_for_magic_link_authentication?
true
end
# This method determines which error message to display when magic link
# auth is disabled for this model instance.
def magic_link_inactive_message
:magic_link_invalid
end
protected
module ClassMethods
def passwordless_tokenizer_class
@passwordless_tokenizer_class ||= self.passwordless_tokenizer.is_a?(Class) ? (
self.passwordless_tokenizer
) : (
self.passwordless_tokenizer.start_with?("::") ? (
self.passwordless_tokenizer.constantize
) : (
"Devise::Passwordless::#{self.passwordless_tokenizer}".constantize
)
)
end
def decode_passwordless_token(*args, **kwargs)
passwordless_tokenizer_class.decode(*args, **kwargs)
end
# We assume this method already gets the sanitized values from the
# MagicLinkAuthenticatable strategy. If you are using this method on
# your own, be sure to sanitize the conditions hash to only include
# the proper fields.
def find_for_magic_link_authentication(conditions)
find_for_authentication(conditions)
end
Devise::Models.config(self,
:passwordless_tokenizer,
:passwordless_login_within,
#:passwordless_secret_key,
:passwordless_expire_old_tokens_on_sign_in
)
end
end
end
end
module Devise
mattr_accessor :passwordless_tokenizer
@@passwordless_tokenizer = nil
def self.passwordless_tokenizer
if @@passwordless_tokenizer.blank?
Devise::Passwordless.deprecator.warn <<-DEPRECATION.strip_heredoc
[Devise-Passwordless] `Devise.passwordless_tokenizer` is a required
config option. If you are upgrading to Devise-Passwordless 1.0 from
a previous install, you should use "MessageEncryptorTokenizer" for
backwards compatibility. New installs are templated with
"SignedGlobalIDTokenizer". Read the README for a comparison of
options and UPGRADING for upgrade instructions. Execution will
now proceed with a value of "MessageEncryptorTokenizer" but future
releases will raise an error if this option is unset.
DEPRECATION
"MessageEncryptorTokenizer"
else
@@passwordless_tokenizer
end
end
mattr_accessor :passwordless_login_within
@@passwordless_login_within = 20.minutes
mattr_accessor :passwordless_secret_key
@@passwordless_secret_key = nil
mattr_accessor :passwordless_expire_old_tokens_on_sign_in
@@passwordless_expire_old_tokens_on_sign_in = false
end