Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit 14e41899 authored by Joze RIHTARSIC's avatar Joze RIHTARSIC
Browse files

Pull request #118: [EDELIVERY-13839] Reset password policy validation fix

Merge in EDELIVERY/smp from bugfix/EDELIVERY-13839-user-management-password-complexity-is-not-applied-on-reset-password-screen to development

* commit '8652a830':
  [EDELIVERY-13839] Reset password policy validation fix
parents f97bca8d 8652a830
No related branches found
No related tags found
No related merge requests found
......@@ -13,6 +13,7 @@ import {SecurityEventService} from "../security/security-event.service";
import {DateAdapter} from "@angular/material/core";
import {NgxMatDateAdapter} from "@angular-material-components/datetime-picker";
import {DomainRo} from "./model/domain-ro.model";
import {Subject} from "rxjs";
/**
* Purpose of object is to fetch lookups as domains and users
......@@ -20,6 +21,9 @@ import {DomainRo} from "./model/domain-ro.model";
@Injectable()
export class GlobalLookups {
// global data observers. The components will subscribe to these Subject to get
// data updates.
private smpInfoUpdateSubject: Subject<SmpInfo> = new Subject<SmpInfo>();
domainObserver: Observable<SearchTableResult>
userObserver: Observable<SearchTableResult>
......@@ -92,12 +96,14 @@ export class GlobalLookups {
this.http.get<SmpInfo>(SmpConstants.REST_PUBLIC_APPLICATION_INFO)
.subscribe({
next: (res: SmpInfo) => {
next: (res: SmpInfo): void => {
this.cachedApplicationInfo = res;
}, error: (error: any) => {
console.log("getSmpInfo:" + error);
this.smpInfoUpdateSubject.next(res);
},
error: (err: any): void => {
console.log("getSmpInfo:" + err);
}
});
});
}
......@@ -108,15 +114,13 @@ export class GlobalLookups {
console.log("Refresh application configuration is authenticated " + isAuthenticated)
if (isAuthenticated) {
this.http.get<SmpConfig>(SmpConstants.REST_PUBLIC_APPLICATION_CONFIG)
.subscribe({
next: (res: SmpConfig) => {
this.cachedApplicationConfig = res;
}
, error: (error: any) => {
console.log("getSmpConfig:" + error);
}
}
);
.subscribe({next: (res :SmpConfig):void => {
this.cachedApplicationConfig = res;
},
error: (err: any)=> {
console.log("getSmpConfig:" + err);
}
});
}
});
}
......@@ -155,4 +159,8 @@ export class GlobalLookups {
this.cachedApplicationConfig = null;
this.cachedDomainList = [];
}
public onSmpInfoUpdateEvent(): Observable<SmpInfo> {
return this.smpInfoUpdateSubject.asObservable();
}
}
......@@ -2,8 +2,11 @@
import {ActivatedRoute, Router} from '@angular/router';
import {FormGroup, UntypedFormControl, Validators} from "@angular/forms";
import {GlobalLookups} from "../../common/global-lookups";
import {equal} from "../../common/dialogs/password-change-dialog/password-change-dialog.component";
import {
equal
} from "../../common/dialogs/password-change-dialog/password-change-dialog.component";
import {SecurityService} from "../security.service";
import {SmpInfo} from "../../app-info/smp-info.model";
@Component({
templateUrl: './reset-credential.component.html',
......@@ -26,18 +29,38 @@ export class ResetCredentialComponent implements OnInit {
ngOnInit() {
this.initForm();
this.lookups.onSmpInfoUpdateEvent().subscribe((data: SmpInfo): void => {
this.resetPasswordValidator(data);
})
this.resetToken = this.activatedRoute.snapshot.params['resetToken'];
}
/**
* Reset password validator from the application info data object
* @param data - SmpInfo
*/
private resetPasswordValidator(data: SmpInfo): void {
this.resetForm.controls['new-password'].setValidators([Validators.required, Validators.pattern(data.passwordValidationRegExp)]);
}
private initForm() {
let newPasswdFormControl: UntypedFormControl = new UntypedFormControl({value: null, readonly: false},
let newPasswdFormControl: UntypedFormControl = new UntypedFormControl({
value: null,
readonly: false
},
[Validators.required, Validators.pattern(this.passwordValidationRegExp)]);
let confirmNewPasswdFormControl: UntypedFormControl = new UntypedFormControl({value: null, readonly: false},
let confirmNewPasswdFormControl: UntypedFormControl = new UntypedFormControl({
value: null,
readonly: false
},
[Validators.required, equal(newPasswdFormControl, true)]);
this.resetForm = new FormGroup({
'resetUsername': new UntypedFormControl({value: null, readonly: true}, null),
'resetUsername': new UntypedFormControl({
value: null,
readonly: true
}, null),
'new-password': newPasswdFormControl,
'confirm-new-password': confirmNewPasswdFormControl
});
......
......@@ -56,6 +56,7 @@ import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.regex.Pattern;
import static java.util.Locale.US;
......@@ -354,12 +355,16 @@ public class CredentialService {
return;
}
DBCredential dbCredential = optCredential.get();
if (!resetToken.equals(dbCredential.getResetToken())) {
LOG.warn("User [{}] reset token does not match the active reset token! The request is ignored", username);
return;
}
Pattern pattern = configurationService.getPasswordPolicyRexExp();
if (pattern != null && !pattern.matcher(newPassword).matches()) {
throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "PasswordChange", configurationService.getPasswordPolicyValidationMessage());
}
OffsetDateTime now = OffsetDateTime.now();
dbCredential.setValue(BCrypt.hashpw(newPassword, BCrypt.gensalt()));
dbCredential.setResetToken(null);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment