fix(admin): require current password for self password change and fix field ordering
- initialize `newPassword` in form state on load - add `needsCurrentPassword` flag triggered by email or password change when editing self - route self password change to profile endpoint with current password verification - move role tag input above password section and update current password field visibility logic
This commit is contained in:
@@ -46,6 +46,7 @@ const UserEditModal = ({ userId, currentUserId, isOpen, onClose, onSaved }) => {
|
||||
name: userJson.user.name || '',
|
||||
email: userJson.user.email || '',
|
||||
currentPassword: '',
|
||||
newPassword: '',
|
||||
});
|
||||
} else {
|
||||
toast.error(userJson.message || 'Utilisateur introuvable');
|
||||
@@ -90,10 +91,12 @@ const UserEditModal = ({ userId, currentUserId, isOpen, onClose, onSaved }) => {
|
||||
|
||||
const emailChanged = userData && formData.email !== userData.email;
|
||||
|
||||
const needsCurrentPassword = isSelf && (emailChanged || !!formData.newPassword);
|
||||
|
||||
const validate = () => {
|
||||
const newErrors = {};
|
||||
if (!formData.name?.trim()) newErrors.name = 'Le nom est requis';
|
||||
if (emailChanged && isSelf && !formData.currentPassword) newErrors.currentPassword = 'Le mot de passe est requis pour changer le courriel';
|
||||
if (needsCurrentPassword && !formData.currentPassword) newErrors.currentPassword = 'Le mot de passe actuel est requis';
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
@@ -175,11 +178,16 @@ const UserEditModal = ({ userId, currentUserId, isOpen, onClose, onSaved }) => {
|
||||
}
|
||||
|
||||
if (formData.newPassword) {
|
||||
const pwdRes = await fetch(`/zen/api/users/${userId}/password`, {
|
||||
method: 'PUT',
|
||||
const pwdUrl = isSelf ? '/zen/api/users/profile/password' : `/zen/api/users/${userId}/password`;
|
||||
const pwdMethod = isSelf ? 'POST' : 'PUT';
|
||||
const pwdBody = isSelf
|
||||
? { currentPassword: formData.currentPassword, newPassword: formData.newPassword }
|
||||
: { newPassword: formData.newPassword };
|
||||
const pwdRes = await fetch(pwdUrl, {
|
||||
method: pwdMethod,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ newPassword: formData.newPassword }),
|
||||
body: JSON.stringify(pwdBody),
|
||||
});
|
||||
const pwdData = await pwdRes.json();
|
||||
if (!pwdRes.ok) {
|
||||
@@ -242,17 +250,17 @@ const UserEditModal = ({ userId, currentUserId, isOpen, onClose, onSaved }) => {
|
||||
placeholder="courriel@exemple.com"
|
||||
/>
|
||||
</div>
|
||||
{isSelf && emailChanged && (
|
||||
<Input
|
||||
label="Mot de passe actuel *"
|
||||
type="password"
|
||||
value={formData.currentPassword}
|
||||
onChange={(value) => handleInputChange('currentPassword', value)}
|
||||
placeholder="Votre mot de passe"
|
||||
error={errors.currentPassword}
|
||||
description="Requis pour confirmer le changement de courriel"
|
||||
/>
|
||||
|
||||
<TagInput
|
||||
label="Rôles attribués"
|
||||
options={roleOptions}
|
||||
value={selectedRoleIds}
|
||||
onChange={setSelectedRoleIds}
|
||||
placeholder="Rechercher un rôle..."
|
||||
renderTag={(opt, onRemove) => (
|
||||
<RoleBadge key={opt.value} name={opt.label} color={opt.color} onRemove={onRemove} />
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="border-t border-neutral-200 dark:border-neutral-700 pt-4 flex flex-col gap-3">
|
||||
<Input
|
||||
@@ -275,16 +283,17 @@ const UserEditModal = ({ userId, currentUserId, isOpen, onClose, onSaved }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TagInput
|
||||
label="Rôles attribués"
|
||||
options={roleOptions}
|
||||
value={selectedRoleIds}
|
||||
onChange={setSelectedRoleIds}
|
||||
placeholder="Rechercher un rôle..."
|
||||
renderTag={(opt, onRemove) => (
|
||||
<RoleBadge key={opt.value} name={opt.label} color={opt.color} onRemove={onRemove} />
|
||||
)}
|
||||
{needsCurrentPassword && (
|
||||
<Input
|
||||
label="Mot de passe actuel *"
|
||||
type="password"
|
||||
value={formData.currentPassword}
|
||||
onChange={(value) => handleInputChange('currentPassword', value)}
|
||||
placeholder="Votre mot de passe"
|
||||
error={errors.currentPassword}
|
||||
description={emailChanged && formData.newPassword ? 'Requis pour confirmer le changement de courriel et de mot de passe' : emailChanged ? 'Requis pour confirmer le changement de courriel' : 'Requis pour confirmer le changement de mot de passe'}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user