[CST-6110] Remove check for password length

This commit is contained in:
Giuseppe Digilio
2022-09-19 18:09:05 +02:00
parent ee46594b5b
commit 4ca5571a2b
13 changed files with 23 additions and 131 deletions

View File

@@ -21,7 +21,6 @@
[FORM_PREFIX]="'forgot-password.form.'" [FORM_PREFIX]="'forgot-password.form.'"
(isInvalid)="setInValid($event)" (isInvalid)="setInValid($event)"
(passwordValue)="setPasswordValue($event)" (passwordValue)="setPasswordValue($event)"
[isRobustPasswordError]="isRobustPasswordError | async"
></ds-profile-page-security-form> ></ds-profile-page-security-form>
</div> </div>
</div> </div>

View File

@@ -1,4 +1,4 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { RouterStub } from '../../shared/testing/router.stub'; import { RouterStub } from '../../shared/testing/router.stub';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
@@ -109,21 +109,6 @@ describe('ForgotPasswordFormComponent', () => {
expect(notificationsService.error).toHaveBeenCalled(); expect(notificationsService.error).toHaveBeenCalled();
}); });
it('should submit a patch request for the user uuid and get robust password error stay on page', () => {
(ePersonDataService.patchPasswordWithToken as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$('Error', 422));
comp.password = 'password';
comp.isInValid = false;
comp.submit();
expect(ePersonDataService.patchPasswordWithToken).toHaveBeenCalledWith('test-uuid', 'test-token', 'password');
expect(store.dispatch).not.toHaveBeenCalled();
expect(router.navigate).not.toHaveBeenCalled();
expect(comp.isRobustPasswordError.value).toBeTrue();
});
it('should submit a patch request for the user uuid when the form is invalid', () => { it('should submit a patch request for the user uuid when the form is invalid', () => {
comp.password = 'password'; comp.password = 'password';

View File

@@ -2,7 +2,7 @@ import { Component } from '@angular/core';
import { EPersonDataService } from '../../core/eperson/eperson-data.service'; import { EPersonDataService } from '../../core/eperson/eperson-data.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { BehaviorSubject, Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Registration } from '../../core/shared/registration.model'; import { Registration } from '../../core/shared/registration.model';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
@@ -10,10 +10,7 @@ import { AuthenticateAction } from '../../core/auth/auth.actions';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { RemoteData } from '../../core/data/remote-data'; import { RemoteData } from '../../core/data/remote-data';
import { EPerson } from '../../core/eperson/models/eperson.model'; import { EPerson } from '../../core/eperson/models/eperson.model';
import { import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload, } from '../../core/shared/operators';
getFirstCompletedRemoteData,
getFirstSucceededRemoteDataPayload,
} from '../../core/shared/operators';
import { CoreState } from '../../core/core-state.model'; import { CoreState } from '../../core/core-state.model';
@Component({ @Component({
@@ -39,7 +36,6 @@ export class ForgotPasswordFormComponent {
* Prefix for the notification messages of this component * Prefix for the notification messages of this component
*/ */
NOTIFICATIONS_PREFIX = 'forgot-password.form.notification'; NOTIFICATIONS_PREFIX = 'forgot-password.form.notification';
isRobustPasswordError: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(private ePersonDataService: EPersonDataService, constructor(private ePersonDataService: EPersonDataService,
private translateService: TranslateService, private translateService: TranslateService,
@@ -68,7 +64,6 @@ export class ForgotPasswordFormComponent {
setPasswordValue($event: string) { setPasswordValue($event: string) {
this.password = $event; this.password = $event;
this.isRobustPasswordError.next(false);
} }
/** /**
@@ -80,9 +75,7 @@ export class ForgotPasswordFormComponent {
this.ePersonDataService.patchPasswordWithToken(this.user, this.token, this.password).pipe( this.ePersonDataService.patchPasswordWithToken(this.user, this.token, this.password).pipe(
getFirstCompletedRemoteData() getFirstCompletedRemoteData()
).subscribe((response: RemoteData<EPerson>) => { ).subscribe((response: RemoteData<EPerson>) => {
if (response.statusCode === 422) { if (response.hasSucceeded) {
this.isRobustPasswordError.next(true);
} else if (response.hasSucceeded) {
this.notificationsService.success( this.notificationsService.success(
this.translateService.instant(this.NOTIFICATIONS_PREFIX + '.success.title'), this.translateService.instant(this.NOTIFICATIONS_PREFIX + '.success.title'),
this.translateService.instant(this.NOTIFICATIONS_PREFIX + '.success.content') this.translateService.instant(this.NOTIFICATIONS_PREFIX + '.success.content')

View File

@@ -6,7 +6,5 @@
[displaySubmit]="false" [displaySubmit]="false"
[displayCancel]="false"> [displayCancel]="false">
</ds-form> </ds-form>
<div id="notLongEnough" class="container-fluid text-danger" *ngIf="formGroup.hasError('notLongEnough')">{{FORM_PREFIX + 'error.password-length' | translate}}</div>
<div id="notSame" class="container-fluid text-danger" *ngIf="formGroup.hasError('notSame')">{{FORM_PREFIX + 'error.matching-passwords' | translate}}</div> <div id="notSame" class="container-fluid text-danger" *ngIf="formGroup.hasError('notSame')">{{FORM_PREFIX + 'error.matching-passwords' | translate}}</div>
<div id="emptyPassword" class="container-fluid text-danger" *ngIf="(formGroup.dirty || formGroup.touched) && formGroup.hasError('emptyPassword')">{{FORM_PREFIX + 'error.empty-password' | translate}}</div> <div id="emptyPassword" class="container-fluid text-danger" *ngIf="(formGroup.dirty || formGroup.touched) && formGroup.hasError('emptyPassword')">{{FORM_PREFIX + 'error.empty-password' | translate}}</div>
<div data-test="robust-password-error" class="container-fluid text-danger" *ngIf="isRobustPasswordError">{{'password.error.robust-password' | translate}}</div>

View File

@@ -1,4 +1,4 @@
import { waitForAsync, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { VarDirective } from '../../shared/utils/var.directive'; import { VarDirective } from '../../shared/utils/var.directive';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
@@ -9,7 +9,6 @@ import { FormBuilderService } from '../../shared/form/builder/form-builder.servi
import { ProfilePageSecurityFormComponent } from './profile-page-security-form.component'; import { ProfilePageSecurityFormComponent } from './profile-page-security-form.component';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { RestResponse } from '../../core/cache/response.models'; import { RestResponse } from '../../core/cache/response.models';
import { By } from '@angular/platform-browser';
describe('ProfilePageSecurityFormComponent', () => { describe('ProfilePageSecurityFormComponent', () => {
let component: ProfilePageSecurityFormComponent; let component: ProfilePageSecurityFormComponent;
@@ -77,16 +76,4 @@ describe('ProfilePageSecurityFormComponent', () => {
})); }));
}); });
}); });
describe('On robust password Error', () => {
it('should show/hide robust password error', () => {
component.isRobustPasswordError = true;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('[data-test="robust-password-error"]'))).toBeTruthy();
component.isRobustPasswordError = false;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('[data-test="robust-password-error"]'))).toBeFalsy();
});
});
}); });

View File

@@ -61,11 +61,6 @@ export class ProfilePageSecurityFormComponent implements OnInit {
@Input() @Input()
FORM_PREFIX: string; FORM_PREFIX: string;
/**
* monitor to password is weak or not from server response
*/
@Input()
isRobustPasswordError: boolean;
private subs: Subscription[] = []; private subs: Subscription[] = [];
constructor(protected formService: DynamicFormService, constructor(protected formService: DynamicFormService,
@@ -77,10 +72,10 @@ export class ProfilePageSecurityFormComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
if (this.passwordCanBeEmpty) { if (this.passwordCanBeEmpty) {
this.formGroup = this.formService.createFormGroup(this.formModel, this.formGroup = this.formService.createFormGroup(this.formModel,
{validators: [this.checkPasswordsEqual, this.checkPasswordLength]}); { validators: [this.checkPasswordsEqual] });
} else { } else {
this.formGroup = this.formService.createFormGroup(this.formModel, this.formGroup = this.formService.createFormGroup(this.formModel,
{validators: [this.checkPasswordsEqual, this.checkPasswordLength, this.checkPasswordEmpty]}); { validators: [this.checkPasswordsEqual, this.checkPasswordEmpty] });
} }
this.updateFieldTranslations(); this.updateFieldTranslations();
this.translate.onLangChange this.translate.onLangChange
@@ -88,15 +83,11 @@ export class ProfilePageSecurityFormComponent implements OnInit {
this.updateFieldTranslations(); this.updateFieldTranslations();
}); });
this.subs.push(this.formGroup.statusChanges.pipe( this.subs.push(
debounceTime(300), this.formGroup.statusChanges.pipe(
map((status: string) => { debounceTime(300),
if (status !== 'VALID') { map((status: string) => status !== 'VALID')
return true; ).subscribe((status) => this.isInvalid.emit(status))
} else {
return false;
}
})).subscribe((status) => this.isInvalid.emit(status))
); );
this.subs.push(this.formGroup.valueChanges.pipe( this.subs.push(this.formGroup.valueChanges.pipe(
@@ -125,17 +116,7 @@ export class ProfilePageSecurityFormComponent implements OnInit {
const pass = group.get('password').value; const pass = group.get('password').value;
const repeatPass = group.get('passwordrepeat').value; const repeatPass = group.get('passwordrepeat').value;
return pass === repeatPass ? null : {notSame: true}; return pass === repeatPass ? null : { notSame: true };
}
/**
* Check if the password is at least 8 characters long
* @param group The FormGroup to validate
*/
checkPasswordLength(group: FormGroup) {
const pass = group.get('password').value;
return isEmpty(pass) || pass.length >= 8 ? null : {notLongEnough: true};
} }
/** /**
@@ -144,7 +125,7 @@ export class ProfilePageSecurityFormComponent implements OnInit {
*/ */
checkPasswordEmpty(group: FormGroup) { checkPasswordEmpty(group: FormGroup) {
const pass = group.get('password').value; const pass = group.get('password').value;
return isEmpty(pass) ? {emptyPassword: true} : null; return isEmpty(pass) ? { emptyPassword: true } : null;
} }
/** /**

View File

@@ -24,7 +24,6 @@
[FORM_PREFIX]="'profile.security.form.'" [FORM_PREFIX]="'profile.security.form.'"
(isInvalid)="setInvalid($event)" (isInvalid)="setInvalid($event)"
(passwordValue)="setPasswordValue($event)" (passwordValue)="setPasswordValue($event)"
[isRobustPasswordError]="isRobustPasswordError | async"
></ds-profile-page-security-form> ></ds-profile-page-security-form>
</div> </div>
</div> </div>

View File

@@ -228,23 +228,6 @@ describe('ProfilePageComponent', () => {
expect(epersonService.patch).toHaveBeenCalledWith(user, operations); expect(epersonService.patch).toHaveBeenCalledWith(user, operations);
}); });
}); });
describe('when password is filled in, and is weak', () => {
let result;
let operations;
it('should return call epersonService.patch', () => {
(epersonService.patch as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$('Error', 422));
component.setPasswordValue('testest');
component.setInvalid(false);
operations = [{ op: 'add', path: '/password', value: 'testest' }];
result = component.updateSecurity();
expect(result).toEqual(true);
expect(epersonService.patch).toHaveBeenCalledWith(user, operations);
expect(component.isRobustPasswordError.value).toBeTrue();
});
});
}); });
describe('canChangePassword$', () => { describe('canChangePassword$', () => {

View File

@@ -73,7 +73,6 @@ export class ProfilePageComponent implements OnInit {
*/ */
private currentUser: EPerson; private currentUser: EPerson;
canChangePassword$: Observable<boolean>; canChangePassword$: Observable<boolean>;
isRobustPasswordError: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
isResearcherProfileEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); isResearcherProfileEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
@@ -148,9 +147,7 @@ export class ProfilePageComponent implements OnInit {
this.epersonService.patch(this.currentUser, [operation]).pipe( this.epersonService.patch(this.currentUser, [operation]).pipe(
getFirstCompletedRemoteData() getFirstCompletedRemoteData()
).subscribe((response: RemoteData<EPerson>) => { ).subscribe((response: RemoteData<EPerson>) => {
if (response.statusCode === 422) { if (response.hasSucceeded) {
this.isRobustPasswordError.next(true);
} else if (response.hasSucceeded) {
this.notificationsService.success( this.notificationsService.success(
this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'success.title'), this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'success.title'),
this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'success.content') this.translate.instant(this.PASSWORD_NOTIFICATIONS_PREFIX + 'success.content')
@@ -171,7 +168,6 @@ export class ProfilePageComponent implements OnInit {
*/ */
setPasswordValue($event: string) { setPasswordValue($event: string) {
this.password = $event; this.password = $event;
this.isRobustPasswordError.next(false);
} }
/** /**

View File

@@ -73,7 +73,6 @@
[FORM_PREFIX]="'register-page.create-profile.security.'" [FORM_PREFIX]="'register-page.create-profile.security.'"
(isInvalid)="setInValid($event)" (isInvalid)="setInValid($event)"
(passwordValue)="setPasswordValue($event)" (passwordValue)="setPasswordValue($event)"
[isRobustPasswordError]="isRobustPasswordError | async"
></ds-profile-page-security-form> ></ds-profile-page-security-form>
</div> </div>
</div> </div>

View File

@@ -239,23 +239,6 @@ describe('CreateProfileComponent', () => {
expect(notificationsService.error).toHaveBeenCalled(); expect(notificationsService.error).toHaveBeenCalled();
}); });
it('should submit an eperson for creation but password is weak', () => {
(ePersonDataService.createEPersonForToken as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$('Error', 422));
comp.firstName.patchValue('First');
comp.lastName.patchValue('Last');
comp.contactPhone.patchValue('Phone');
comp.language.patchValue('en');
comp.password = 'password';
comp.isInValidPassword = false;
comp.submitEperson();
expect(ePersonDataService.createEPersonForToken).toHaveBeenCalledWith(eperson, 'test-token');
expect(comp.isRobustPasswordError.value).toBeTrue();
});
it('should submit not create an eperson when the user info form is invalid', () => { it('should submit not create an eperson when the user info form is invalid', () => {
(ePersonDataService.createEPersonForToken as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$('Error', 500)); (ePersonDataService.createEPersonForToken as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$('Error', 500));

View File

@@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { Registration } from '../../core/shared/registration.model'; import { Registration } from '../../core/shared/registration.model';
import { BehaviorSubject, Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { EPersonDataService } from '../../core/eperson/eperson-data.service'; import { EPersonDataService } from '../../core/eperson/eperson-data.service';
@@ -40,7 +40,7 @@ export class CreateProfileComponent implements OnInit {
userInfoForm: FormGroup; userInfoForm: FormGroup;
activeLangs: LangConfig[]; activeLangs: LangConfig[];
isRobustPasswordError: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor( constructor(
private translateService: TranslateService, private translateService: TranslateService,
private ePersonDataService: EPersonDataService, private ePersonDataService: EPersonDataService,
@@ -93,7 +93,6 @@ export class CreateProfileComponent implements OnInit {
setPasswordValue($event: string) { setPasswordValue($event: string) {
this.password = $event; this.password = $event;
this.isInValidPassword = this.isInValidPassword || isEmpty(this.password); this.isInValidPassword = this.isInValidPassword || isEmpty(this.password);
this.isRobustPasswordError.next(false);
} }
get firstName() { get firstName() {
@@ -161,9 +160,7 @@ export class CreateProfileComponent implements OnInit {
this.ePersonDataService.createEPersonForToken(eperson, this.token).pipe( this.ePersonDataService.createEPersonForToken(eperson, this.token).pipe(
getFirstCompletedRemoteData(), getFirstCompletedRemoteData(),
).subscribe((rd: RemoteData<EPerson>) => { ).subscribe((rd: RemoteData<EPerson>) => {
if (rd.statusCode === 422) { if (rd.hasSucceeded) {
this.isRobustPasswordError.next(true);
} else if (rd.hasSucceeded) {
this.notificationsService.success(this.translateService.get('register-page.create-profile.submit.success.head'), this.notificationsService.success(this.translateService.get('register-page.create-profile.submit.success.head'),
this.translateService.get('register-page.create-profile.submit.success.content')); this.translateService.get('register-page.create-profile.submit.success.content'));
this.store.dispatch(new AuthenticateAction(this.email, this.password)); this.store.dispatch(new AuthenticateAction(this.email, this.password));

View File

@@ -1490,7 +1490,7 @@
"forgot-password.form.head": "Forgot Password", "forgot-password.form.head": "Forgot Password",
"forgot-password.form.info": "Enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least eight characters long.", "forgot-password.form.info": "Enter a new password in the box below, and confirm it by typing it again into the second box.",
"forgot-password.form.card.security": "Security", "forgot-password.form.card.security": "Security",
@@ -1506,8 +1506,6 @@
"forgot-password.form.error.matching-passwords": "The passwords do not match.", "forgot-password.form.error.matching-passwords": "The passwords do not match.",
"forgot-password.form.error.password-length": "The password should be at least 8 characters long.",
"forgot-password.form.notification.error.title": "Error when trying to submit new password", "forgot-password.form.notification.error.title": "Error when trying to submit new password",
"forgot-password.form.notification.success.content": "The password reset was successful. You have been logged in as the created user.", "forgot-password.form.notification.success.content": "The password reset was successful. You have been logged in as the created user.",
@@ -1516,8 +1514,6 @@
"forgot-password.form.submit": "Submit password", "forgot-password.form.submit": "Submit password",
"password.error.robust-password": "New password is invalid. Valid passwords must be between 8-15 characters long and must include a minimum of: one uppercase letter, one lowercase letter, one number, and one special character (!?$@#$%^&+=).",
"form.add": "Add more", "form.add": "Add more",
@@ -2985,7 +2981,7 @@
"process.detail.create" : "Create similar process", "process.detail.create" : "Create similar process",
"process.detail.actions": "Actions", "process.detail.actions": "Actions",
"process.detail.delete.button": "Delete process", "process.detail.delete.button": "Delete process",
"process.detail.delete.header": "Delete process", "process.detail.delete.header": "Delete process",
@@ -3038,7 +3034,7 @@
"process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted", "process.bulk.delete.success": "{{count}} process(es) have been succesfully deleted",
"profile.breadcrumbs": "Update Profile", "profile.breadcrumbs": "Update Profile",
@@ -3078,9 +3074,7 @@
"profile.security.form.error.matching-passwords": "The passwords do not match.", "profile.security.form.error.matching-passwords": "The passwords do not match.",
"profile.security.form.error.password-length": "The password should be at least 8 characters long.", "profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box.",
"profile.security.form.info": "Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least eight characters long.",
"profile.security.form.label.password": "Password", "profile.security.form.label.password": "Password",
@@ -3180,7 +3174,7 @@
"register-page.create-profile.security.header": "Security", "register-page.create-profile.security.header": "Security",
"register-page.create-profile.security.info": "Please enter a password in the box below, and confirm it by typing it again into the second box. It should be at least eight characters long.", "register-page.create-profile.security.info": "Please enter a password in the box below, and confirm it by typing it again into the second box.",
"register-page.create-profile.security.label.password": "Password *", "register-page.create-profile.security.label.password": "Password *",
@@ -3190,8 +3184,6 @@
"register-page.create-profile.security.error.matching-passwords": "The passwords do not match.", "register-page.create-profile.security.error.matching-passwords": "The passwords do not match.",
"register-page.create-profile.security.error.password-length": "The password should be at least 8 characters long.",
"register-page.create-profile.submit": "Complete Registration", "register-page.create-profile.submit": "Complete Registration",
"register-page.create-profile.submit.error.content": "Something went wrong while registering a new user.", "register-page.create-profile.submit.error.content": "Something went wrong while registering a new user.",