mirror of
https://github.com/discourse/discourse.git
synced 2025-06-23 03:11:31 +08:00
Added button to remove password from account (#32200)
Added button to remove password from account if user has a linked external account or passkey The button only displays if the user has at least one associated account or a passkey set up. Uses the ConfirmSession dialog in addition to a warning about deleting the password. Users can still reset their password via the Reset Password button (which will now display "Set Password" if they've removed it). Also prevent user from removing their last remaining associated account or passkey if they have no password set. Replaces PR #31489 from my personal repo, with some fixes for conflicts since then.
This commit is contained in:
@ -758,7 +758,7 @@ class UsersController < ApplicationController
|
||||
|
||||
# just assign a password if we have an authenticator and no password
|
||||
# this is the case for Twitter
|
||||
user.password = SecureRandom.hex if user.password.blank? &&
|
||||
user.password = SecureRandom.hex if user.password_required? && user.password.blank? &&
|
||||
(authentication.has_authenticator? || associations.present?)
|
||||
|
||||
if user.save
|
||||
@ -858,6 +858,23 @@ class UsersController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def remove_password
|
||||
RateLimiter.new(nil, "remove-password-hr-#{request.remote_ip}", 6, 1.hour).performed!
|
||||
RateLimiter.new(nil, "remove-password-min-#{request.remote_ip}", 3, 1.hour).performed!
|
||||
|
||||
user = fetch_user_from_params
|
||||
guardian.ensure_can_edit!(user)
|
||||
RateLimiter.new(nil, "remove-password-hr-#{user.username}", 6, 1.hour).performed!
|
||||
|
||||
raise Discourse::NotFound if !user || !user.user_password
|
||||
raise Discourse::ReadOnly if staff_writes_only_mode? && !user.staff?
|
||||
raise Discourse::InvalidAccess if !secure_session_confirmed?
|
||||
|
||||
user.remove_password
|
||||
|
||||
render json: success_json
|
||||
end
|
||||
|
||||
def password_reset_update
|
||||
expires_now
|
||||
token = params[:token]
|
||||
@ -1675,7 +1692,15 @@ class UsersController < ApplicationController
|
||||
def delete_passkey
|
||||
raise Discourse::NotFound unless SiteSetting.enable_passkeys
|
||||
|
||||
current_user.security_keys.find_by(id: params[:id].to_i)&.destroy!
|
||||
security_key = current_user.security_keys.find_by(id: params[:id].to_i)
|
||||
|
||||
if security_key&.first_factor? && current_user.passkey_credential_ids.length == 1
|
||||
if !current_user.has_password? && current_user.associated_accounts.blank?
|
||||
return render json: { success: false, message: I18n.t("user.cannot_remove_all_auth") }
|
||||
end
|
||||
end
|
||||
|
||||
security_key&.destroy!
|
||||
|
||||
render json: success_json
|
||||
end
|
||||
@ -1798,6 +1823,12 @@ class UsersController < ApplicationController
|
||||
authenticator = Discourse.authenticators.find { |a| a.name == provider_name }
|
||||
raise Discourse::NotFound if authenticator.nil? || !authenticator.can_revoke?
|
||||
|
||||
if user.associated_accounts&.length == 1
|
||||
if !user.has_password? && user.passkey_credential_ids.blank?
|
||||
return render json: { success: false, message: I18n.t("user.cannot_remove_all_auth") }
|
||||
end
|
||||
end
|
||||
|
||||
skip_remote = params.permit(:skip_remote)
|
||||
|
||||
# We're likely going to contact the remote auth provider, so hijack request
|
||||
|
Reference in New Issue
Block a user