From e8779511ad30d123366ca32baf83aedf41b758e1 Mon Sep 17 00:00:00 2001
From: Akshita Goyal <36129505+gakshita@users.noreply.github.com>
Date: Fri, 28 Mar 2025 13:35:42 +0530
Subject: [PATCH] [WEB-3673] fix: password change form (#6839)
* fix: change password
* fix: added store action for change password
* fix: type
* fix: store refactor
---
.../plane/authentication/views/common.py | 19 ++++-
.../i18n/src/locales/cs/translations.json | 1 +
.../i18n/src/locales/de/translations.json | 2 +
.../i18n/src/locales/en/translations.json | 1 +
.../i18n/src/locales/es/translations.json | 1 +
.../i18n/src/locales/fr/translations.json | 1 +
.../i18n/src/locales/id/translations.json | 1 +
.../i18n/src/locales/it/translations.json | 2 +
.../i18n/src/locales/ja/translations.json | 1 +
.../i18n/src/locales/ko/translations.json | 1 +
.../i18n/src/locales/pl/translations.json | 2 +
.../i18n/src/locales/ro/translations.json | 1 +
.../i18n/src/locales/ru/translations.json | 1 +
.../i18n/src/locales/sk/translations.json | 1 +
.../i18n/src/locales/ua/translations.json | 1 +
.../i18n/src/locales/zh-CN/translations.json | 1 +
.../i18n/src/locales/zh-TW/translations.json | 1 +
web/app/profile/security/page.tsx | 80 ++++++++++---------
web/core/services/user.service.ts | 2 +-
web/core/store/user/index.ts | 22 +++++
20 files changed, 101 insertions(+), 41 deletions(-)
diff --git a/apiserver/plane/authentication/views/common.py b/apiserver/plane/authentication/views/common.py
index cdcf6bc96..7a18072ae 100644
--- a/apiserver/plane/authentication/views/common.py
+++ b/apiserver/plane/authentication/views/common.py
@@ -44,10 +44,21 @@ class ChangePasswordEndpoint(APIView):
def post(self, request):
user = User.objects.get(pk=request.user.id)
- old_password = request.data.get("old_password", False)
+ # If the user password is not autoset then we need to check the old passwords
+ if not user.is_password_autoset:
+ old_password = request.data.get("old_password", False)
+ if not old_password:
+ exc = AuthenticationException(
+ error_code=AUTHENTICATION_ERROR_CODES["MISSING_PASSWORD"],
+ error_message="MISSING_PASSWORD",
+ payload={"error": "Old password is missing"},
+ )
+ return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
+
+ # Get the new password
new_password = request.data.get("new_password", False)
- if not old_password or not new_password:
+ if not new_password:
exc = AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["MISSING_PASSWORD"],
error_message="MISSING_PASSWORD",
@@ -55,7 +66,9 @@ class ChangePasswordEndpoint(APIView):
)
return Response(exc.get_error_dict(), status=status.HTTP_400_BAD_REQUEST)
- if not user.check_password(old_password):
+
+ # If the user password is not autoset then we need to check the old passwords
+ if not user.is_password_autoset and not user.check_password(old_password):
exc = AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["INCORRECT_OLD_PASSWORD"],
error_message="INCORRECT_OLD_PASSWORD",
diff --git a/packages/i18n/src/locales/cs/translations.json b/packages/i18n/src/locales/cs/translations.json
index 0e2764ec4..51c0aa0e3 100644
--- a/packages/i18n/src/locales/cs/translations.json
+++ b/packages/i18n/src/locales/cs/translations.json
@@ -499,6 +499,7 @@
"re_generate_key": "Znovu generovat klíč",
"export": "Exportovat",
"member": "{count, plural, one{# člen} few{# členové} other{# členů}}",
+ "new_password_must_be_different_from_old_password": "Nové heslo musí být odlišné od starého hesla",
"project_view": {
"sort_by": {
diff --git a/packages/i18n/src/locales/de/translations.json b/packages/i18n/src/locales/de/translations.json
index 872fc1746..77ab42515 100644
--- a/packages/i18n/src/locales/de/translations.json
+++ b/packages/i18n/src/locales/de/translations.json
@@ -499,6 +499,8 @@
"re_generate_key": "Schlüssel neu generieren",
"export": "Exportieren",
"member": "{count, plural, one{# Mitglied} few{# Mitglieder} other{# Mitglieder}}",
+ "new_password_must_be_different_from_old_password": "Das neue Passwort muss von dem alten Passwort abweichen",
+
"project_view": {
"sort_by": {
"created_at": "Erstellt am",
diff --git a/packages/i18n/src/locales/en/translations.json b/packages/i18n/src/locales/en/translations.json
index 9191eab12..0be5219be 100644
--- a/packages/i18n/src/locales/en/translations.json
+++ b/packages/i18n/src/locales/en/translations.json
@@ -331,6 +331,7 @@
"re_generate_key": "Re-generate key",
"export": "Export",
"member": "{count, plural, one{# member} other{# members}}",
+ "new_password_must_be_different_from_old_password": "New password must be different from old password",
"edited": "edited",
"bot": "Bot",
diff --git a/packages/i18n/src/locales/es/translations.json b/packages/i18n/src/locales/es/translations.json
index 446c49b40..d3a0c1f6c 100644
--- a/packages/i18n/src/locales/es/translations.json
+++ b/packages/i18n/src/locales/es/translations.json
@@ -503,6 +503,7 @@
"re_generate_key": "Regenerar clave",
"export": "Exportar",
"member": "{count, plural, one{# miembro} other{# miembros}}",
+ "new_password_must_be_different_from_old_password": "La nueva contraseña debe ser diferente a la contraseña anterior",
"edited": "Modificado",
"bot": "Bot",
diff --git a/packages/i18n/src/locales/fr/translations.json b/packages/i18n/src/locales/fr/translations.json
index dfd3e9310..0cda79656 100644
--- a/packages/i18n/src/locales/fr/translations.json
+++ b/packages/i18n/src/locales/fr/translations.json
@@ -501,6 +501,7 @@
"re_generate_key": "Régénérer la clé",
"export": "Exporter",
"member": "{count, plural, one{# membre} other{# membres}}",
+ "new_password_must_be_different_from_old_password": "Le nouveau mot de passe doit être différent du mot de passe précédent",
"edited": "Modifié",
"bot": "Bot",
diff --git a/packages/i18n/src/locales/id/translations.json b/packages/i18n/src/locales/id/translations.json
index 84841d0f1..64338a04f 100644
--- a/packages/i18n/src/locales/id/translations.json
+++ b/packages/i18n/src/locales/id/translations.json
@@ -501,6 +501,7 @@
"re_generate_key": "Hasilkan kembali kunci",
"export": "Ekspor",
"member": "{count, plural, one{# anggota} other{# anggota}}",
+ "new_password_must_be_different_from_old_password": "Kata sandi baru harus berbeda dari kata sandi lama",
"project_view": {
"sort_by": {
diff --git a/packages/i18n/src/locales/it/translations.json b/packages/i18n/src/locales/it/translations.json
index 0e1ebfea5..352d7fce4 100644
--- a/packages/i18n/src/locales/it/translations.json
+++ b/packages/i18n/src/locales/it/translations.json
@@ -500,6 +500,8 @@
"re_generate_key": "Rigenera chiave",
"export": "Esporta",
"member": "{count, plural, one {# membro} other {# membri}}",
+ "new_password_must_be_different_from_old_password": "La nuova password deve essere diversa dalla password precedente",
+
"edited": "Modificato",
"bot": "Bot",
diff --git a/packages/i18n/src/locales/ja/translations.json b/packages/i18n/src/locales/ja/translations.json
index 9997a8a3c..7d0d09175 100644
--- a/packages/i18n/src/locales/ja/translations.json
+++ b/packages/i18n/src/locales/ja/translations.json
@@ -501,6 +501,7 @@
"re_generate_key": "キーを再生成",
"export": "エクスポート",
"member": "{count, plural, other{# メンバー}}",
+ "new_password_must_be_different_from_old_password": "新しいパスワードは古いパスワードと異なる必要があります",
"edited": "編集済み",
"bot": "ボット",
diff --git a/packages/i18n/src/locales/ko/translations.json b/packages/i18n/src/locales/ko/translations.json
index 656eb5ded..d6b88df27 100644
--- a/packages/i18n/src/locales/ko/translations.json
+++ b/packages/i18n/src/locales/ko/translations.json
@@ -501,6 +501,7 @@
"re_generate_key": "키 다시 생성",
"export": "내보내기",
"member": "{count, plural, one{# 멤버} other{# 멤버}}",
+ "new_password_must_be_different_from_old_password": "새 비밀번호는 이전 비밀번호와 다르게 설정해야 합니다",
"edited": "수정됨",
"bot": "봇",
diff --git a/packages/i18n/src/locales/pl/translations.json b/packages/i18n/src/locales/pl/translations.json
index daef77671..08543fcde 100644
--- a/packages/i18n/src/locales/pl/translations.json
+++ b/packages/i18n/src/locales/pl/translations.json
@@ -499,6 +499,8 @@
"re_generate_key": "Wygeneruj klucz ponownie",
"export": "Eksportuj",
"member": "{count, plural, one{# członek} few{# członkowie} other{# członków}}",
+ "new_password_must_be_different_from_old_password": "Nowe hasło musi być innym niż stare hasło",
+
"edited": "Edytowano",
"bot": "Bot",
diff --git a/packages/i18n/src/locales/ro/translations.json b/packages/i18n/src/locales/ro/translations.json
index 43ac9eb28..67a642292 100644
--- a/packages/i18n/src/locales/ro/translations.json
+++ b/packages/i18n/src/locales/ro/translations.json
@@ -501,6 +501,7 @@
"re_generate_key": "Regenerează cheia",
"export": "Exportă",
"member": "{count, plural, one{# membru} other{# membri}}",
+ "new_password_must_be_different_from_old_password": "Parola nouă trebuie să fie diferită de parola veche",
"project_view": {
"sort_by": {
diff --git a/packages/i18n/src/locales/ru/translations.json b/packages/i18n/src/locales/ru/translations.json
index c12e1ab0e..753d82cd9 100644
--- a/packages/i18n/src/locales/ru/translations.json
+++ b/packages/i18n/src/locales/ru/translations.json
@@ -499,6 +499,7 @@
"re_generate_key": "Перегенерировать ключ",
"export": "Экспорт",
"member": "{count, plural, one{# участник} few{# участника} other{# участников}}",
+ "new_password_must_be_different_from_old_password": "Новое пароль должен отличаться от старого пароля",
"edited": "Редактировано",
"bot": "Бот",
diff --git a/packages/i18n/src/locales/sk/translations.json b/packages/i18n/src/locales/sk/translations.json
index a70bc3427..5964af5f4 100644
--- a/packages/i18n/src/locales/sk/translations.json
+++ b/packages/i18n/src/locales/sk/translations.json
@@ -499,6 +499,7 @@
"re_generate_key": "Znova generovať kľúč",
"export": "Exportovať",
"member": "{count, plural, one{# člen} few{# členovia} other{# členov}}",
+ "new_password_must_be_different_from_old_password": "Nové heslo musí byť odlišné od starého hesla",
"edited": "Upravené",
"bot": "Bot",
diff --git a/packages/i18n/src/locales/ua/translations.json b/packages/i18n/src/locales/ua/translations.json
index 10f3cc640..3d4048612 100644
--- a/packages/i18n/src/locales/ua/translations.json
+++ b/packages/i18n/src/locales/ua/translations.json
@@ -499,6 +499,7 @@
"re_generate_key": "Повторно згенерувати ключ",
"export": "Експортувати",
"member": "{count, plural, one{# учасник} few{# учасники} other{# учасників}}",
+ "new_password_must_be_different_from_old_password": "Новий пароль повинен бути відмінним від старого пароля",
"edited": "Редагувано",
"bot": "Бот",
diff --git a/packages/i18n/src/locales/zh-CN/translations.json b/packages/i18n/src/locales/zh-CN/translations.json
index f83c20909..536c5eb9b 100644
--- a/packages/i18n/src/locales/zh-CN/translations.json
+++ b/packages/i18n/src/locales/zh-CN/translations.json
@@ -501,6 +501,7 @@
"re_generate_key": "重新生成密钥",
"export": "导出",
"member": "{count, plural, other{# 成员}}",
+ "new_password_must_be_different_from_old_password": "新密码必须不同于旧密码",
"edited": "已编辑",
"bot": "机器人",
diff --git a/packages/i18n/src/locales/zh-TW/translations.json b/packages/i18n/src/locales/zh-TW/translations.json
index e4bf984ad..c78ad8138 100644
--- a/packages/i18n/src/locales/zh-TW/translations.json
+++ b/packages/i18n/src/locales/zh-TW/translations.json
@@ -501,6 +501,7 @@
"re_generate_key": "重新產生金鑰",
"export": "匯出",
"member": "{count, plural, one{# 位成員} other{# 位成員}}",
+ "new_password_must_be_different_from_old_password": "新密碼必須與舊密碼不同",
"edited": "已編輯",
"bot": "機器人",
diff --git a/web/app/profile/security/page.tsx b/web/app/profile/security/page.tsx
index 86098f122..8477d70d9 100644
--- a/web/app/profile/security/page.tsx
+++ b/web/app/profile/security/page.tsx
@@ -14,9 +14,10 @@ import { ProfileSettingContentHeader, ProfileSettingContentWrapper } from "@/com
// helpers
import { authErrorHandler } from "@/helpers/authentication.helper";
import { E_PASSWORD_STRENGTH, getPasswordStrength } from "@/helpers/password.helper";
+// hooks
+import { useUser } from "@/hooks/store";
// services
import { AuthService } from "@/services/auth.service";
-import { UserService } from "@/services/user.service";
export interface FormValues {
old_password: string;
@@ -30,7 +31,6 @@ const defaultValues: FormValues = {
confirm_password: "",
};
-const userService = new UserService();
const authService = new AuthService();
const defaultShowPassword = {
@@ -40,10 +40,13 @@ const defaultShowPassword = {
};
const SecurityPage = observer(() => {
+ // store
+ const { data: currentUser, changePassword } = useUser();
// states
const [showPassword, setShowPassword] = useState(defaultShowPassword);
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
const [isRetryPasswordInputFocused, setIsRetryPasswordInputFocused] = useState(false);
+
// use form
const {
control,
@@ -56,6 +59,7 @@ const SecurityPage = observer(() => {
const oldPassword = watch("old_password");
const password = watch("new_password");
const confirmPassword = watch("confirm_password");
+ const oldPasswordRequired = !currentUser?.is_password_autoset;
// i18n
const { t } = useTranslation();
@@ -70,8 +74,8 @@ const SecurityPage = observer(() => {
const csrfToken = await authService.requestCSRFToken().then((data) => data?.csrf_token);
if (!csrfToken) throw new Error("csrf token not found");
- await userService.changePassword(csrfToken, {
- old_password,
+ await changePassword(csrfToken, {
+ ...(oldPasswordRequired && { old_password }),
new_password,
});
@@ -95,7 +99,7 @@ const SecurityPage = observer(() => {
const isButtonDisabled =
getPasswordStrength(password) != E_PASSWORD_STRENGTH.STRENGTH_VALID ||
- oldPassword.trim() === "" ||
+ (oldPasswordRequired && oldPassword.trim() === "") ||
password.trim() === "" ||
confirmPassword.trim() === "" ||
password !== confirmPassword ||
@@ -115,41 +119,43 @@ const SecurityPage = observer(() => {