Skip to content

Commit 860657b

Browse files
committed
Allow internal users to change their password
Also, admins are allowed to change the password of other internal users.
1 parent 6a61cb0 commit 860657b

File tree

11 files changed

+213
-12
lines changed

11 files changed

+213
-12
lines changed

app/controllers/internal_users_controller.rb

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class InternalUsersController < ApplicationController
66
before_action :require_user!, except: %i[activate forgot_password reset_password]
77
before_action :require_activation_token, only: :activate
88
before_action :require_reset_password_token, only: :reset_password
9-
before_action :set_user, only: MEMBER_ACTIONS
9+
before_action :set_user, only: MEMBER_ACTIONS + %i[change_password]
1010
before_action :collect_set_and_unset_study_group_memberships, only: MEMBER_ACTIONS + %i[create]
1111
after_action :verify_authorized, except: %i[activate forgot_password reset_password]
1212

@@ -58,13 +58,28 @@ def reset_password
5858

5959
def update
6060
# Let's skip the password validation if the user is edited through
61-
# the form by another user. Otherwise, the update might fail if an
61+
# the form here. Otherwise, the update might fail if an
6262
# activation_token or password_reset_token is present
63-
@user.validate_password = current_user == @user
63+
@user.validate_password = false
6464
@user.platform_admin = platform_admin_param if current_user.admin?
6565
update_and_respond(object: @user, params: internal_user_params)
6666
end
6767

68+
def change_password
69+
return render :change_password unless request.patch? || request.put?
70+
71+
if @user != current_user || @user.valid_password?(params[:internal_user].delete(:current_password))
72+
# Always validate the password strength when changing the password
73+
@user.validate_password = true
74+
update_password
75+
else
76+
respond_to do |format|
77+
@user.errors.add(:base, :current_password_invalid)
78+
respond_with_invalid_object(format, object: @user, template: :change_password)
79+
end
80+
end
81+
end
82+
6883
def destroy
6984
destroy_and_respond(object: @user)
7085
end
@@ -75,14 +90,15 @@ def authorize!
7590
authorize(@user || @users)
7691
end
7792

78-
def change_password
93+
def update_password
7994
respond_to do |format|
8095
if @user.update(params[:internal_user].permit(:password, :password_confirmation))
8196
@user.change_password!(params[:internal_user][:password])
82-
format.html { redirect_to(sign_in_path, notice: t('internal_users.reset_password.success')) }
97+
redirect_target = current_user ? internal_user_path(@user) : sign_in_path
98+
format.html { redirect_to(redirect_target, notice: t('internal_users.reset_password.success')) }
8399
format.json { head :ok }
84100
else
85-
respond_with_invalid_object(format, object: @user, template: :reset_password)
101+
respond_with_invalid_object(format, object: @user, template: action_name.to_sym)
86102
end
87103
end
88104
end

app/models/internal_user.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ class InternalUser < User
88
attr_accessor :validate_password
99

1010
validates :email, presence: true, uniqueness: true
11-
validates :password, confirmation: true, if: -> { password_void? && validate_password? }, on: :update, presence: true
12-
validate :password_strength, if: -> { password_void? && validate_password? }, on: :update
11+
validates :password, confirmation: true, if: -> { password_void? || validate_password? }, on: :update, presence: true
12+
validate :password_strength, if: -> { password_void? || validate_password? }, on: :update
1313

1414
accepts_nested_attributes_for :study_group_memberships
1515

@@ -23,7 +23,7 @@ def password_void?
2323
private :password_void?
2424

2525
def validate_password?
26-
return true if @validate_password.nil?
26+
return false if @validate_password.nil?
2727

2828
@validate_password
2929
end

app/policies/internal_user_policy.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ def show?
1313
admin? || @record == @user || teacher_in_study_group?
1414
end
1515

16-
def change_codeharbor_link?
17-
admin? || @record == @user
16+
%i[change_codeharbor_link? change_password?].each do |action|
17+
define_method(action) { admin? || @record == @user }
1818
end
1919

2020
class Scope < Scope
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
h1 = t('.headline')
2+
3+
= form_for(@user, url: change_password_internal_user_path) do |f|
4+
= render('shared/form_errors', object: @user)
5+
.mb-3
6+
= f.label(:password, class: 'form-label')
7+
= f.password_field(:password, class: 'form-control', required: true, autocomplete: 'new-password')
8+
.mb-3
9+
= f.label(:password_confirmation, class: 'form-label')
10+
= f.password_field(:password_confirmation, class: 'form-control', required: true, autocomplete: 'new-password')
11+
- if @user == current_user
12+
.mb-3
13+
= f.label(:current_password, class: 'form-label')
14+
= f.password_field(:current_password, class: 'form-control', required: true, autocomplete: 'current-password')
15+
.help-block.form-text = t('.hints.current_password')
16+
.actions = submit_tag(t('.submit'), class: 'btn btn-primary')

app/views/internal_users/show.html.slim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ h1
3030

3131
- if @user == current_user || current_user.admin?
3232
= row(label: 'codeharbor_link.profile_label', value: @user.codeharbor_link.nil? ? link_to(t('codeharbor_link.new'), polymorphic_path([@user, CodeharborLink], action: :new), class: 'btn btn-secondary') : link_to(t('codeharbor_link.edit'), polymorphic_path([@user, @user.codeharbor_link], action: :edit), class: 'btn btn-secondary'))
33+
= row(label: 'internal_user.password', value: link_to(t('.change_password'), change_password_internal_user_path(@user), class: 'btn btn-secondary'))

config/locales/de/internal_user.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ de:
66
activated: Aktiviert
77
consumer: Konsument
88
consumer_id: Konsument
9+
current_password: Aktuelles Passwort
910
email: E-Mail
1011
name: Name
1112
password: Passwort
@@ -20,6 +21,12 @@ de:
2021
headline: Registrierung abschließen
2122
submit: Passwort speichern
2223
success: Sie haben Ihre Registrierung erfolgreich abgeschlossen.
24+
change_password:
25+
headline: Passwort ändern
26+
hints:
27+
current_password: Bitte geben Sie Ihr aktuelles Passwort ein, um Ihre Identität zu bestätigen.
28+
submit: Passwort ändern
29+
success: Sie haben Ihr Passwort erfolgreich geändert.
2330
forgot_password:
2431
headline: Passwort zurücksetzen
2532
submit: Anweisungen zum Zurücksetzen senden
@@ -29,11 +36,13 @@ de:
2936
study_groups: Lerngruppen
3037
index:
3138
activate: Aktivieren
39+
change_password: Passwort ändern
3240
forgot_password: Passwort zurücksetzen
3341
reset_password: Passwort zurücksetzen
3442
reset_password:
3543
headline: Passwort zurücksetzen
3644
submit: Passwort speichern
3745
success: Sie haben Ihr Passwort erfolgreich geändert.
3846
show:
47+
change_password: Passwort ändern
3948
link: Profil

config/locales/de/meta/activerecord.errors.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ de:
1717
attributes:
1818
password:
1919
weak: ist zu schwach. Versuchen Sie es mit einem langen Passwort, welches Groß-, Kleinbuchstaben, Zahlen und Sonderzeichen enthält.
20+
current_password_invalid: Das aktuelle Passwort ist nicht korrekt.
2021
programming_group:
2122
invalid_partner_id: Die Personen-ID '%{partner_id}' ist ungültig und wurde entfernt. Bitte überprüfen Sie die Personen-IDs der Programmierpartner:innen.
2223
size_too_large: Die Größe dieser Programmiergruppe ist zu groß. Geben Sie nur eine andere Personen-ID an.

config/locales/en/internal_user.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ en:
66
activated: Activated
77
consumer: Consumer
88
consumer_id: Consumer
9+
current_password: Current Password
910
email: Email
1011
name: Name
1112
password: Password
12-
password_confirmation: Passwort Confirmation
13+
password_confirmation: Password Confirmation
1314
platform_admin: Platform Admin
1415
models:
1516
internal_user:
@@ -20,6 +21,12 @@ en:
2021
headline: Complete Registration
2122
submit: Set Password
2223
success: You successfully completed your registration.
24+
change_password:
25+
headline: Change Password
26+
hints:
27+
current_password: Please enter your current password to confirm your identity.
28+
submit: Change Password
29+
success: You successfully changed your password.
2330
forgot_password:
2431
headline: Reset Password
2532
submit: Send Password Reset Instructions
@@ -29,11 +36,13 @@ en:
2936
study_groups: Study Groups
3037
index:
3138
activate: Activate
39+
change_password: Change Password
3240
forgot_password: Reset Password
3341
reset_password: Reset Password
3442
reset_password:
3543
headline: Reset Password
3644
submit: Set Password
3745
success: You successfully changed your password.
3846
show:
47+
change_password: Change Password
3948
link: Profile

config/locales/en/meta/activerecord.errors.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ en:
1717
attributes:
1818
password:
1919
weak: is too weak. Try to use a long password with upper and lower case letters, numbers and special characters.
20+
current_password_invalid: The current password is not correct.
2021
programming_group:
2122
invalid_partner_id: The user ID '%{partner_id}' is invalid and was removed. Please check the user IDs of your programming partners.
2223
size_too_large: The size of this programming group is too large. Enter at most one other user ID to work with.

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
member do
139139
match 'activate', to: 'internal_users#activate', via: %i[get patch put]
140140
match 'reset_password', to: 'internal_users#reset_password', via: %i[get patch put]
141+
match 'change_password', to: 'internal_users#change_password', via: %i[get patch put]
141142
end
142143
resources :codeharbor_links, only: %i[new create edit update destroy]
143144
end

0 commit comments

Comments
 (0)