diff --git a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts index 213a83b86e..ba758b1203 100644 --- a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts +++ b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.spec.ts @@ -74,6 +74,19 @@ describe('ProfilePageSecurityFormComponent', () => { expect(component.passwordValue.emit).toHaveBeenCalledWith('new-password'); })); + + it('should emit the value on password change with current password for profile-page', fakeAsync(() => { + spyOn(component.passwordValue, 'emit'); + spyOn(component.currentPasswordValue, 'emit'); + component.FORM_PREFIX = 'profile.security.form.'; + component.ngOnInit(); + component.formGroup.patchValue({password: 'new-password'}); + component.formGroup.patchValue({'current-password': 'current-password'}); + tick(300); + + expect(component.passwordValue.emit).toHaveBeenCalledWith('new-password'); + expect(component.currentPasswordValue.emit).toHaveBeenCalledWith('current-password'); + })) }); }); }); diff --git a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts index 4f310204e3..ab39ca1929 100644 --- a/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts +++ b/src/app/profile-page/profile-page-security-form/profile-page-security-form.component.ts @@ -27,6 +27,10 @@ export class ProfilePageSecurityFormComponent implements OnInit { * Emits the value of the password */ @Output() passwordValue = new EventEmitter(); + /** + * Emits the value of the current-password + */ + @Output() currentPasswordValue = new EventEmitter(); /** * The form's input models @@ -69,6 +73,14 @@ export class ProfilePageSecurityFormComponent implements OnInit { } ngOnInit(): void { + if (this.FORM_PREFIX === 'profile.security.form.') { + this.formModel.unshift(new DynamicInputModel({ + id: 'current-password', + name: 'current-password', + inputType: 'password', + required: true + })); + } if (this.passwordCanBeEmpty) { this.formGroup = this.formService.createFormGroup(this.formModel, {validators: [this.checkPasswordsEqual, this.checkPasswordLength]}); @@ -85,11 +97,7 @@ export class ProfilePageSecurityFormComponent implements OnInit { this.subs.push(this.formGroup.statusChanges.pipe( debounceTime(300), map((status: string) => { - if (status !== 'VALID') { - return true; - } else { - return false; - } + return status !== 'VALID'; })).subscribe((status) => this.isInvalid.emit(status)) ); @@ -97,6 +105,9 @@ export class ProfilePageSecurityFormComponent implements OnInit { debounceTime(300), ).subscribe((valueChange) => { this.passwordValue.emit(valueChange.password); + if (this.FORM_PREFIX === 'profile.security.form.') { + this.currentPasswordValue.emit(valueChange['current-password']); + } })); } diff --git a/src/app/profile-page/profile-page.component.html b/src/app/profile-page/profile-page.component.html index 6e22f73a75..b6f53b08bf 100644 --- a/src/app/profile-page/profile-page.component.html +++ b/src/app/profile-page/profile-page.component.html @@ -24,6 +24,7 @@ [FORM_PREFIX]="'profile.security.form.'" (isInvalid)="setInvalid($event)" (passwordValue)="setPasswordValue($event)" + (currentPasswordValue)="setCurrentPasswordValue($event)" > diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 6893ac2437..71537e9c32 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -180,7 +180,7 @@ describe('ProfilePageComponent', () => { beforeEach(() => { component.setPasswordValue(''); - + component.setCurrentPasswordValue('current-password'); result = component.updateSecurity(); }); @@ -199,6 +199,7 @@ describe('ProfilePageComponent', () => { beforeEach(() => { component.setPasswordValue('test'); component.setInvalid(true); + component.setCurrentPasswordValue('current-password'); result = component.updateSecurity(); }); @@ -215,8 +216,12 @@ describe('ProfilePageComponent', () => { beforeEach(() => { component.setPasswordValue('testest'); component.setInvalid(false); + component.setCurrentPasswordValue('current-password'); - operations = [{ op: 'add', path: '/password', value: 'testest' }]; + operations = [ + { op: 'add', path: '/password', value: 'testest' }, + { op: 'add', path: '/challenge', value: 'current-password' } + ]; result = component.updateSecurity(); }); diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index 5629a1ae18..15811ee77f 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -67,6 +67,10 @@ export class ProfilePageComponent implements OnInit { * The password filled in, in the security form */ private password: string; + /** + * The current-password filled in, in the security form + */ + private currentPassword: string; /** * The authenticated user @@ -138,15 +142,15 @@ export class ProfilePageComponent implements OnInit { */ updateSecurity() { const passEntered = isNotEmpty(this.password); - if (this.invalidSecurity) { this.notificationsService.error(this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'error.general')); } if (!this.invalidSecurity && passEntered) { - const operation = {op: 'add', path: '/password', value: this.password} as Operation; - this.epersonService.patch(this.currentUser, [operation]).pipe( - getFirstCompletedRemoteData() - ).subscribe((response: RemoteData) => { + const operations = [ + { op: 'add', path: '/password', value: this.password }, + { op: 'add', path: '/challenge', value: this.currentPassword } + ] as Operation[]; + this.epersonService.patch(this.currentUser, operations).pipe(getFirstCompletedRemoteData()).subscribe((response: RemoteData) => { if (response.hasSucceeded) { this.notificationsService.success( this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'success.title'), @@ -170,6 +174,14 @@ export class ProfilePageComponent implements OnInit { this.password = $event; } + /** + * Set the current-password value based on the value emitted from the security form + * @param $event + */ + setCurrentPasswordValue($event: string) { + this.currentPassword = $event; + } + /** * Submit of the security form that triggers the updateProfile method */ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 3d5f15b4f2..860db5aac6 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -3046,6 +3046,8 @@ "profile.security.form.label.passwordrepeat": "Retype to confirm", + "profile.security.form.label.current-password": "Current password", + "profile.security.form.notifications.success.content": "Your changes to the password were saved.", "profile.security.form.notifications.success.title": "Password saved",