Skip to content

Commit cf883fc

Browse files
committed
frontend: Add confirm password field when changing the password or creating an accoung
fix #200
1 parent 62a2cc6 commit cf883fc

File tree

5 files changed

+73
-10
lines changed

5 files changed

+73
-10
lines changed

frontend/src/components/password_component.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Eye, EyeOff } from "react-feather";
44
import { useTranslation } from "react-i18next";
55

66
interface PasswordComponentProps {
7-
onChange: (e: Event) => void,
7+
onChange: (e: string) => void,
88
isInvalid?: boolean,
99
invalidMessage?: string,
1010
}
@@ -16,7 +16,7 @@ export function PasswordComponent(props: PasswordComponentProps) {
1616
<Form.Control
1717
placeholder={t("password")}
1818
type={showPassword ? "text" : "password"}
19-
onChange={props.onChange}
19+
onChange={(e) => props.onChange((e.target as HTMLInputElement).value)}
2020
isInvalid={props.isInvalid} />
2121
<Button
2222
variant="outline-primary"

frontend/src/components/register.tsx

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ interface RegisterState {
2424
accepted: boolean,
2525
password: string,
2626
passwordValid: boolean,
27+
confirmPassword: string,
28+
confirmPasswordValid: boolean,
2729
name: string,
2830
nameValid: boolean,
2931
email: string,
@@ -44,6 +46,8 @@ export class Register extends Component<{}, RegisterState> {
4446
accepted: false,
4547
password: "",
4648
passwordValid: true,
49+
confirmPassword: "",
50+
confirmPasswordValid: true,
4751
name: "",
4852
nameValid: true,
4953
email: "",
@@ -63,13 +67,24 @@ export class Register extends Component<{}, RegisterState> {
6367
showModal: Signal<boolean>;
6468

6569
checkPassword() {
70+
let res = true;
6671

67-
const res = PASSWORD_PATTERN.test(this.state.password);
68-
if (!res) {
72+
const passwordPatternValid = PASSWORD_PATTERN.test(this.state.password);
73+
if (!passwordPatternValid) {
6974
this.setState({passwordValid: false});
75+
res = false;
7076
} else {
7177
this.setState({passwordValid: true});
7278
}
79+
80+
const passwordsMatch = this.state.password === this.state.confirmPassword;
81+
if (!passwordsMatch) {
82+
this.setState({confirmPasswordValid: false});
83+
res = false;
84+
} else {
85+
this.setState({confirmPasswordValid: true});
86+
}
87+
7388
return res;
7489
}
7590

@@ -210,10 +225,27 @@ export class Register extends Component<{}, RegisterState> {
210225
<Form.Group className="mb-3" controlId="registerPassword">
211226
<Form.Label>{t("password")}</Form.Label>
212227
<PasswordComponent isInvalid={!this.state.passwordValid} onChange={(e) => {
213-
this.setState({password: (e.target as HTMLInputElement).value});
228+
const password = e;
229+
this.setState({password}, () => {
230+
if (!this.state.confirmPasswordValid || !this.state.passwordValid) {
231+
this.checkPassword();
232+
}
233+
});
214234
}}
215235
invalidMessage={t("password_error_message")} />
216236
</Form.Group>
237+
<Form.Group className="mb-3" controlId="registerConfirmPassword">
238+
<Form.Label>{t("confirm_password")}</Form.Label>
239+
<PasswordComponent isInvalid={!this.state.confirmPasswordValid} onChange={(e) => {
240+
const confirmPassword = e;
241+
this.setState({confirmPassword}, () => {
242+
if (!this.state.confirmPasswordValid || !this.state.passwordValid) {
243+
this.checkPassword();
244+
}
245+
});
246+
}}
247+
invalidMessage={t("confirm_password_error_message")} />
248+
</Form.Group>
217249
<Form.Group className="mb-3" onClick={() => this.setState({acceptPrivacyChecked: !this.state.acceptPrivacyChecked})}>
218250
<Form.Check checked={this.state.acceptPrivacyChecked} type="checkbox" label={<Trans i18nKey="register.accept_privacy_notice" ><a target="__blank" href={privacy_notice}>link</a></Trans>} isInvalid={!this.state.acceptPrivacyValid}/>
219251
</Form.Group>

frontend/src/locales/de.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export const de ={
1919
"current_password_error_message": "Darf nicht leer sein.",
2020
"new_password": "Neues Passwort",
2121
"new_password_error_message": "Muss mindestens 8 Zeichen lang sein und jeweils mindestens einen Klein- und Großbuchstaben sowie ein Sonderzeichen enthalten.",
22+
"confirm_new_password": "Neues Passwort bestätigen",
23+
"confirm_new_password_error_message": "Passwörter stimmen nicht überein",
2224
"close": "Schließen",
2325
"delete_user": "Konto löschen",
2426
"password": "Passwort",
@@ -99,6 +101,8 @@ export const de ={
99101
"email_error_message": "Die E-Mail-Adresse, darf nicht leer sein",
100102
"password": "Passwort",
101103
"password_error_message": "Muss mindestens 8 Zeichen lang sein und jeweils mindestens einen Klein- und Großbuchstaben sowie eine Zahl enthalten.",
104+
"confirm_password": "Passwort bestätigen",
105+
"confirm_password_error_message": "Passwörter stimmen nicht überein",
102106
"accept_privacy_notice": "Ich habe die <0>Datenschutzerklärung</0> gelesen, verstanden und stimme zu.",
103107
"accept_terms_and_conditions": "Ich habe die <0>AGB</0> gelesen, verstanden und stimme zu.",
104108
"accept_privacy_notice_alpha": "Ich verstehe, dass dies eine Alpha-Version ist und stimme der verarbeitung meiner Daten wie <0>hier</0> beschrieben zu.",

frontend/src/locales/en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export const en = {
1818
"current_password_error_message": "Must not be empty.",
1919
"new_password": "New password",
2020
"new_password_error_message": "Must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters",
21+
"confirm_new_password": "Confirm new password",
22+
"confirm_new_password_error_message": "Passwords do not match",
2123
"close": "Close",
2224
"delete_user": "Delete account",
2325
"password": "Password",
@@ -103,6 +105,8 @@ export const en = {
103105
"email_error_message": "The email-address must not be empty",
104106
"password": "Password",
105107
"password_error_message": "Must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters",
108+
"confirm_password": "Confirm password",
109+
"confirm_password_error_message": "Passwords do not match",
106110
"accept_privacy_notice": "I have read, understood and I am accepting the <0>privacy notice</0>.",
107111
"accept_terms_and_conditions": "I have read, understood and I am accepting the <0>terms and conditions</0>.",
108112
"accept_privacy_notice_alpha": "I understand that this is an alpha-version and accept the usage of my data as described <0>here</0>.",

frontend/src/pages/user.tsx

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,16 @@ export function User() {
149149
const [currentPasswordIsValid, setCurrentPasswordIsValid] = useState(true);
150150
const [newPassword, setNewPassword] = useState("");
151151
const [newPasswordIsValid, setNewPasswordIsValid] = useState(true);
152+
const [confirmNewPassword, setConfirmNewPassword] = useState("");
153+
const [confirmNewPasswordIsValid, setConfirmNewPasswordIsValid] = useState(true);
152154
const validated = signal(false);
153155

154156
const handleUpdatePasswordClose = () => setShowPasswordReset(false);
155157
const handleUpdatePasswordShow = () => setShowPasswordReset(true);
156158
const handleDelteUserClose = () => setDeleteUser({...deleteUser, show: false});
157159
const handleDeleteUserShow = () => setDeleteUser({...deleteUser, show: true});
158160

159-
const checkPasswords = () => {
161+
const checkPasswords = (newPassword: string, confirmNewPassword: string) => {
160162
let ret = true;
161163
if (!PASSWORD_PATTERN.test(newPassword)) {
162164
setNewPasswordIsValid(false);
@@ -165,6 +167,13 @@ export function User() {
165167
setNewPasswordIsValid(true);
166168
}
167169

170+
if (newPassword !== confirmNewPassword) {
171+
setConfirmNewPasswordIsValid(false);
172+
ret = false;
173+
} else {
174+
setConfirmNewPasswordIsValid(true);
175+
}
176+
168177
if (currentPassword.length === 0) {
169178
setCurrentPasswordIsValid(false);
170179
ret = false;
@@ -181,7 +190,7 @@ export function User() {
181190
e.preventDefault();
182191
e.stopPropagation();
183192

184-
if (!checkPasswords()) {
193+
if (!checkPasswords(newPassword, confirmNewPassword)) {
185194
return;
186195
}
187196

@@ -323,7 +332,7 @@ export function User() {
323332
<Modal.Body>
324333
<Form.Group className="pb-3" controlId="deleteUserPassword">
325334
<Form.Label>{t("password")}</Form.Label>
326-
<PasswordComponent onChange={(e) => setDeleteUser({...deleteUser, password: (e.target as HTMLInputElement).value})} isInvalid={!deleteUser.password_valid} invalidMessage={t("password_invalid")} />
335+
<PasswordComponent onChange={(e) => setDeleteUser({...deleteUser, password: e})} isInvalid={!deleteUser.password_valid} invalidMessage={t("password_invalid")} />
327336
</Form.Group>
328337
</Modal.Body>
329338
<Modal.Footer>
@@ -349,12 +358,26 @@ export function User() {
349358
<Form.Group className="pb-3" controlId="oldPassword">
350359
<Form.Label>{t("current_password")}</Form.Label>
351360
<PasswordComponent isInvalid={!currentPasswordIsValid} onChange={(e) => {
352-
setCurrentPassword((e.target as HTMLInputElement).value);
361+
setCurrentPassword(e);
353362
}} />
354363
</Form.Group>
355364
<Form.Group className="pb-3" controlId="newPassword">
356365
<Form.Label>{t("new_password")}</Form.Label>
357-
<PasswordComponent onChange={(e) => setNewPassword((e.target as HTMLInputElement).value)} isInvalid={!newPasswordIsValid} invalidMessage={t("new_password_error_message")} />
366+
<PasswordComponent onChange={(e) => {
367+
setNewPassword(e);
368+
if (!confirmNewPasswordIsValid || !newPasswordIsValid) {
369+
checkPasswords(e, confirmNewPassword);
370+
}
371+
}} isInvalid={!newPasswordIsValid} invalidMessage={t("new_password_error_message")} />
372+
</Form.Group>
373+
<Form.Group className="pb-3" controlId="confirmNewPassword">
374+
<Form.Label>{t("confirm_new_password")}</Form.Label>
375+
<PasswordComponent onChange={(e) => {
376+
setConfirmNewPassword(e);
377+
if (!confirmNewPasswordIsValid) {
378+
checkPasswords(newPassword, e);
379+
}
380+
}} isInvalid={!confirmNewPasswordIsValid} invalidMessage={t("confirm_new_password_error_message")} />
358381
</Form.Group>
359382
</Modal.Body>
360383
<Modal.Footer>

0 commit comments

Comments
 (0)