mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-28 16:36:48 +09:00
Ask for the current password to change it
Changing the password now ends every other session, so whoever holds
one could shut the owner out of their own account with a new password.
The profile asks for the current password whenever the password
changes; without it, or with a wrong one, nothing is saved and the page
says why. Other profile edits don't need it, and the admin
reset-password script still works without it.
Attempts are rate limited like signing in, 10 in 3 minutes per address,
so the current password can't be guessed here instead.
From #371. The cached-response test it touches isn't in 1.5.2.
(cherry picked from commit 44a92ff6c6)
This commit is contained in:
1 parent
58a25c6281
commit
417f087964
6 files changed
+133
-9
No files matched your search
@@ -1,16 +1,23 @@
|
||||
class Users::ProfilesController < ApplicationController
|
||||
before_action :set_user
|
||||
|
||||
# Limited like signing in, so the current password can't be guessed here instead.
|
||||
rate_limit to: 10, within: 3.minutes, only: :update, if: :changing_password?,
|
||||
with: -> { redirect_to user_profile_url, alert: "Too many attempts. Try again in a few minutes." }
|
||||
|
||||
def show
|
||||
@direct_memberships, @shared_memberships =
|
||||
Current.user.memberships.with_ordered_room.partition { |m| m.room.direct? }
|
||||
end
|
||||
|
||||
def update
|
||||
@user.update user_params
|
||||
start_new_session_for @user if @user.saved_change_to_password_digest?
|
||||
if @user.update user_params
|
||||
start_new_session_for @user if @user.saved_change_to_password_digest?
|
||||
|
||||
redirect_to user_profile_url, notice: update_notice
|
||||
redirect_to user_profile_url, notice: update_notice
|
||||
else
|
||||
redirect_to user_profile_url, alert: update_alert
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
@@ -19,10 +26,31 @@ class Users::ProfilesController < ApplicationController
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:name, :avatar, :email_address, :password, :bio).compact
|
||||
permitted = params.require(:user).permit(:name, :avatar, :email_address, :password, :bio).compact
|
||||
|
||||
if changing_password?
|
||||
permitted.merge(password_challenge: params[:user][:password_challenge].to_s)
|
||||
else
|
||||
permitted
|
||||
end
|
||||
end
|
||||
|
||||
# As has_secure_password reads it: an empty password leaves the current one alone.
|
||||
def changing_password?
|
||||
!params.dig(:user, :password).to_s.empty?
|
||||
end
|
||||
|
||||
def update_notice
|
||||
params[:user][:avatar] ? "It may take up to 30 minutes to change everywhere." : "✓"
|
||||
end
|
||||
|
||||
def update_alert
|
||||
if !@user.errors.include?(:password_challenge)
|
||||
@user.errors.full_messages.to_sentence
|
||||
elsif params[:user][:password_challenge].blank?
|
||||
"Enter your current password to change it."
|
||||
else
|
||||
"That isn't your current password."
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user