users: refactor password reset flow.
The old password reset flow: * User requests a password reset. * Danbooru generates a password reset nonce. * Danbooru emails user a password reset confirmation link. * User follows link to password reset confirmation page. * The link contains a nonce authenticating the user. * User confirms password reset. * Danbooru resets user's password to a random string. * Danbooru emails user their new password in plaintext. The new password reset flow: * User requests a password reset. * Danbooru emails user a password reset link. * User follows link to password edit page. * The link contains a signed_user_id param authenticating the user. * User changes their own password.
This commit is contained in:
@@ -121,8 +121,7 @@ class Dmail < ApplicationRecord
|
||||
end
|
||||
|
||||
def valid_key?(key)
|
||||
decoded_id = verifier.verified(key)
|
||||
id == decoded_id
|
||||
id == verifier.verify(key)
|
||||
end
|
||||
|
||||
def visible_to?(user, key)
|
||||
|
||||
@@ -68,7 +68,7 @@ class User < ApplicationRecord
|
||||
|
||||
has_bit_flags BOOLEAN_ATTRIBUTES, :field => "bit_prefs"
|
||||
|
||||
attr_accessor :password, :old_password
|
||||
attr_accessor :password, :old_password, :signed_user_id
|
||||
|
||||
after_initialize :initialize_attributes, if: :new_record?
|
||||
validates :name, user_name: true, on: :create
|
||||
@@ -185,36 +185,15 @@ class User < ApplicationRecord
|
||||
|
||||
def encrypt_password_on_update
|
||||
return if password.blank?
|
||||
return if old_password.blank?
|
||||
|
||||
if bcrypt_password == User.sha1(old_password)
|
||||
if signed_user_id.present? && id == Danbooru::MessageVerifier.new(:login).verify(signed_user_id)
|
||||
self.bcrypt_password_hash = User.bcrypt(password)
|
||||
elsif old_password.present? && bcrypt_password == User.sha1(old_password)
|
||||
self.bcrypt_password_hash = User.bcrypt(password)
|
||||
return true
|
||||
else
|
||||
errors[:old_password] << "is incorrect"
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def reset_password
|
||||
consonants = "bcdfghjklmnpqrstvqxyz"
|
||||
vowels = "aeiou"
|
||||
pass = ""
|
||||
|
||||
6.times do
|
||||
pass << consonants[rand(21), 1]
|
||||
pass << vowels[rand(5), 1]
|
||||
end
|
||||
|
||||
pass << rand(100).to_s
|
||||
update_column(:bcrypt_password_hash, User.bcrypt(pass))
|
||||
pass
|
||||
end
|
||||
|
||||
def reset_password_and_deliver_notice
|
||||
new_password = reset_password
|
||||
Maintenance::User::PasswordResetMailer.confirmation(self, new_password).deliver_now
|
||||
end
|
||||
end
|
||||
|
||||
module AuthenticationMethods
|
||||
@@ -637,14 +616,6 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
module SearchMethods
|
||||
def with_email(email)
|
||||
if email.blank?
|
||||
where("FALSE")
|
||||
else
|
||||
where("email = ?", email)
|
||||
end
|
||||
end
|
||||
|
||||
def search(params)
|
||||
q = super
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
class UserPasswordResetNonce < ApplicationRecord
|
||||
has_secure_token :key
|
||||
validates_presence_of :email
|
||||
validate :validate_existence_of_email
|
||||
after_create :deliver_notice
|
||||
|
||||
def self.prune!
|
||||
where("created_at < ?", 1.week.ago).destroy_all
|
||||
end
|
||||
|
||||
def deliver_notice
|
||||
Maintenance::User::PasswordResetMailer.reset_request(user, self).deliver_now
|
||||
end
|
||||
|
||||
def validate_existence_of_email
|
||||
if !User.with_email(email).exists?
|
||||
errors[:email] << "is invalid"
|
||||
end
|
||||
end
|
||||
|
||||
def reset_user!
|
||||
user.reset_password_and_deliver_notice
|
||||
end
|
||||
|
||||
def user
|
||||
@user ||= User.with_email(email).first
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user