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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
# frozen-string-literal: true
module Rodauth
Feature.define(:verify_login_change, :VerifyLoginChange) do
depends :change_login, :email_base
error_flash "Unable to verify login change"
error_flash "Unable to change login as there is already an account with the new login", 'verify_login_change_duplicate_account'
error_flash "There was an error verifying your login change: invalid verify login change key", 'no_matching_verify_login_change_key'
notice_flash "Your login change has been verified"
notice_flash "An email has been sent to you with a link to verify your login change", 'change_login_needs_verification'
loaded_templates %w'verify-login-change verify-login-change-email'
view 'verify-login-change', 'Verify Login Change'
additional_form_tags
after
after 'verify_login_change_email'
before
before 'verify_login_change_email'
button 'Verify Login Change'
redirect
response
redirect(:verify_login_change_duplicate_account){require_login_redirect}
auth_value_method :verify_login_change_autologin?, false
auth_value_method :verify_login_change_deadline_column, :deadline
auth_value_method :verify_login_change_deadline_interval, {:days=>1}.freeze
translatable_method :verify_login_change_email_subject, 'Verify Login Change'
auth_value_method :verify_login_change_id_column, :id
auth_value_method :verify_login_change_key_column, :key
auth_value_method :verify_login_change_key_param, 'key'
auth_value_method :verify_login_change_login_column, :login
session_key :verify_login_change_session_key, :verify_login_change_key
auth_value_method :verify_login_change_table, :account_login_change_keys
auth_methods(
:create_verify_login_change_email,
:create_verify_login_change_key,
:get_verify_login_change_login_and_key,
:remove_verify_login_change_key,
:send_verify_login_change_email,
:verify_login_change,
:verify_login_change_email_body,
:verify_login_change_email_link,
:verify_login_change_key_insert_hash,
:verify_login_change_key_value,
:verify_login_change_new_login,
:verify_login_change_old_login
)
auth_private_methods(
:account_from_verify_login_change_key
)
internal_request_method
route do |r|
before_verify_login_change_route
r.get do
if key = param_or_nil(verify_login_change_key_param)
set_session_value(verify_login_change_session_key, key)
redirect(r.path)
end
if (key = session[verify_login_change_session_key]) && account_from_verify_login_change_key(key)
verify_login_change_view
else
remove_session_value(verify_login_change_session_key)
set_redirect_error_flash no_matching_verify_login_change_key_error_flash
redirect require_login_redirect
end
end
r.post do
key = session[verify_login_change_session_key] || param(verify_login_change_key_param)
unless account_from_verify_login_change_key(key)
set_redirect_error_status(invalid_key_error_status)
set_error_reason :invalid_verify_login_change_key
set_redirect_error_flash verify_login_change_error_flash
redirect verify_login_change_redirect
end
transaction do
before_verify_login_change
unless verify_login_change
set_redirect_error_status(invalid_key_error_status)
set_error_reason :already_an_account_with_this_login
set_redirect_error_flash verify_login_change_duplicate_account_error_flash
redirect verify_login_change_duplicate_account_redirect
end
remove_verify_login_change_key
after_verify_login_change
end
if verify_login_change_autologin?
autologin_session('verify_login_change')
end
remove_session_value(verify_login_change_session_key)
verify_login_change_response
end
end
def require_login_confirmation?
false
end
def remove_verify_login_change_key
verify_login_change_ds.delete
end
def verify_login_change
unless res = _update_login(verify_login_change_new_login)
remove_verify_login_change_key
end
res
end
def account_from_verify_login_change_key(key)
@account = _account_from_verify_login_change_key(key)
end
def send_verify_login_change_email(login)
send_email(create_verify_login_change_email(login))
end
def verify_login_change_email_link
token_link(verify_login_change_route, verify_login_change_key_param, verify_login_change_key_value)
end
def get_verify_login_change_login_and_key(id)
verify_login_change_ds(id).get([verify_login_change_login_column, verify_login_change_key_column])
end
def change_login_notice_flash
change_login_needs_verification_notice_flash
end
def verify_login_change_old_login
account_ds.get(login_column)
end
attr_reader :verify_login_change_key_value
attr_reader :verify_login_change_new_login
def clear_tokens(reason)
super
remove_verify_login_change_key
end
private
def update_login(login)
if _account_from_login(login)
set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
return false
end
transaction do
before_verify_login_change_email
generate_verify_login_change_key_value
@verify_login_change_new_login = login
create_verify_login_change_key(login)
send_verify_login_change_email(login)
after_verify_login_change_email
end
true
end
def generate_verify_login_change_key_value
@verify_login_change_key_value = random_key
end
def create_verify_login_change_key(login)
ds = verify_login_change_ds
transaction do
ds.where((Sequel::CURRENT_TIMESTAMP > verify_login_change_deadline_column) | ~Sequel.expr(verify_login_change_login_column=>login)).delete
if e = raised_uniqueness_violation{ds.insert(verify_login_change_key_insert_hash(login))}
old_login, key = get_verify_login_change_login_and_key(account_id)
# If inserting into the verify login change table causes a violation, we can pull the
# key from the verify login change table if the logins match, or reraise.
@verify_login_change_key_value = if old_login.downcase == login.downcase
key
end
raise e unless @verify_login_change_key_value
end
end
end
def verify_login_change_key_insert_hash(login)
hash = {verify_login_change_id_column=>account_id, verify_login_change_key_column=>verify_login_change_key_value, verify_login_change_login_column=>login}
set_deadline_value(hash, verify_login_change_deadline_column, verify_login_change_deadline_interval)
hash
end
def create_verify_login_change_email(login)
create_email_to(login, verify_login_change_email_subject, verify_login_change_email_body)
end
def verify_login_change_email_body
render('verify-login-change-email')
end
def verify_login_change_ds(id=account_id)
db[verify_login_change_table].where(verify_login_change_id_column=>id)
end
def _account_from_verify_login_change_key(token)
account_from_key(token) do |id|
@verify_login_change_new_login, key = get_verify_login_change_login_and_key(id)
key
end
end
end
end
|