Skip to content
Snippets Groups Projects
Commit 5e50497b authored by Guillaume Heurtier's avatar Guillaume Heurtier
Browse files

FEAT #8841 TIME 4:00 begin password rules front

parent 48d2404b
No related branches found
No related tags found
No related merge requests found
...@@ -270,6 +270,27 @@ ...@@ -270,6 +270,27 @@
"note" : "Note", "note" : "Note",
"collapseNote" : "Réduire la note", "collapseNote" : "Réduire la note",
"expandNote" : "Ouvrir la note", "expandNote" : "Ouvrir la note",
"convertingDocument" : "Document en cours de conversion" "convertingDocument" : "Document en cours de conversion",
"manage_password_rulesAdmin" : "Administrer les règles de mots de passes",
"manage_password_rules" : "Sécurités",
"manage_password_rulesDesc" : "Administrer les règles de mots de passes",
"passwordRulesUpdated" : "Règle de mot de passe mise à jour",
"password_complexityNumberRequired": "Chiffre requis",
"password_complexitySpecial": "1 caractère spécial au minimum",
"password_complexitySpecialRequired": "Caractère spécial requis",
"password_complexityUpper": "1 majuscule au minimum",
"password_complexityUpperRequired": "Majuscule requise",
"password_historyLastUseDesc": "Vous ne pouvez pas utiliser les",
"password_historyLastUseDesc2": "dernier(s) mot(s) de passe",
"password_historyLastUseRequired": "Nombre de mots de passe sauvegardés",
"password_lockAttemptsRequired": "Nombre de tentatives de connexions",
"password_lockTimeRequired": "Temps de blocage",
"password_minLength": "caractère(s) au minimum",
"password_minLengthRequired": "Longueur minimale",
"password_renewal": "Veuillez noter que ce nouveau mot de passe ne sera valide que",
"password_renewalRequired": "Expiration du mot de passe",
"chars": "caractère(s)",
"days": "jour(s)",
"minutes": "minute(s)"
} }
} }
<mat-sidenav-container autosize class="maarch-container">
<mat-sidenav #snav [disableClose]="!signaturesService.mobileMode"
[mode]="signaturesService.mobileMode ? 'over': 'side'" fixedInViewport="true"
[opened]="!signaturesService.mobileMode" [style.width.px]="350">
<app-admin-sidebar [snavLeftComponent]="this.snav" [snavRightComponent]="this.snavRight"></app-admin-sidebar>
</mat-sidenav>
<mat-sidenav-content>
<header class="header">
<div class="header-title">
<button *ngIf="signaturesService.mobileMode" mat-icon-button (click)="this.snav.toggle();">
<mat-icon fontSet="fas" fontIcon="fa-bars" style="font-size: 24px;"></mat-icon>
</button>
<span *ngIf="!loading">{{'lang.manage_password_rules' | translate}}</span>
</div>
</header>
<div class="container">
<div *ngIf="loading" style="display:flex;height:100%;">
<mat-spinner style="margin:auto;"></mat-spinner>
</div>
<mat-card *ngIf="!loading" class="card-app-content">
<mat-tab-group>
<mat-tab label="{{'lang.password' | translate}}">
<form (ngSubmit)="onSubmit()" #passwordForm="ngForm">
<mat-list>
<p style="margin-bottom: 40px;text-align: center;">
<mat-slide-toggle [name]="passwordRules['complexityUpper'].label"
[checked]="passwordRules['complexityUpper'].enabled" color="primary"
(change)="toggleRule(passwordRules['complexityUpper']);"
style="padding-left:10px;padding-right:10px;">
{{passwordRules['complexityUpper'].label}}</mat-slide-toggle>
<mat-slide-toggle [name]="passwordRules['complexityNumber'].label"
[checked]="passwordRules['complexityNumber'].enabled" color="primary"
(change)="toggleRule(passwordRules['complexityNumber']);"
style="padding-left:10px;padding-right:10px;">
{{passwordRules['complexityNumber'].label}}</mat-slide-toggle>
<mat-slide-toggle [name]="passwordRules['complexitySpecial'].label"
[checked]="passwordRules['complexitySpecial'].enabled" color="primary"
(change)="toggleRule(passwordRules['complexitySpecial']);"
style="padding-left:10px;padding-right:10px;">
{{passwordRules['complexitySpecial'].label}}</mat-slide-toggle>
</p>
<mat-list-item style="margin-top: 15px;margin-bottom: 15px;">
<mat-icon mat-list-icon>
<mat-slide-toggle style="position: relative;top:-10px;"
[checked]="passwordRules['minLength'].enabled" color="primary"
(change)="toggleRule(passwordRules['minLength']);"></mat-slide-toggle>
</mat-icon>
<p mat-line>
<mat-form-field style="width: 100%">
<input type="number" [disabled]="!passwordRules['minLength'].enabled"
[name]="passwordRules['minLength'].label"
[(ngModel)]="passwordRules['minLength'].value" min="1"
pattern="^[1-9][0-9]*" matInput
placeholder="{{passwordRules['minLength'].label}}" required>
<span matSuffix>&nbsp;{{'lang.chars' | translate}}</span>
</mat-form-field>
</p>
</mat-list-item>
<mat-list-item style="margin-top: 15px;margin-bottom: 15px;">
<mat-icon mat-list-icon>
<mat-slide-toggle style="position: relative;top:-10px;"
[checked]="passwordRules['lockAttempts'].enabled" color="primary"
(change)="toggleRule(passwordRules['lockAttempts']);">
</mat-slide-toggle>
</mat-icon>
<p mat-line style="display:flex;">
<mat-form-field style="flex:1;padding-right: 10px;">
<input type="number" [disabled]="!passwordRules['lockAttempts'].enabled"
[name]="passwordRules['lockAttempts'].label"
[(ngModel)]="passwordRules['lockAttempts'].value" min="1"
pattern="^[1-9][0-9]*" matInput
placeholder="{{passwordRules['lockAttempts'].label}}" required>
</mat-form-field>
<mat-form-field style="flex:1;">
<input type="number" [disabled]="!passwordRules['lockTime'].enabled"
[name]="passwordRules['lockTime'].label"
[(ngModel)]="passwordRules['lockTime'].value" min="1"
pattern="^[1-9][0-9]*" matInput
placeholder="{{passwordRules['lockTime'].label}}" required>
<span matSuffix>&nbsp;{{'lang.minutes' | translate}}</span>
</mat-form-field>
</p>
</mat-list-item>
<mat-list-item style="margin-top: 15px;margin-bottom: 15px;">
<mat-icon mat-list-icon>
<mat-slide-toggle style="position: relative;top:-10px;"
[checked]="passwordRules['renewal'].enabled" color="primary"
(change)="toggleRule(passwordRules['renewal']);"></mat-slide-toggle>
</mat-icon>
<p mat-line>
<mat-form-field style="width: 100%">
<input type="number" [disabled]="!passwordRules['renewal'].enabled"
[name]="passwordRules['renewal'].label"
[(ngModel)]="passwordRules['renewal'].value" min="1"
pattern="^[1-9][0-9]*" matInput
placeholder="{{passwordRules['renewal'].label}}" required>
<span matSuffix>&nbsp;{{'lang.days' | translate}}</span>
</mat-form-field>
</p>
</mat-list-item>
<mat-list-item style="margin-top: 15px;margin-bottom: 15px;">
<mat-icon mat-list-icon>
<mat-slide-toggle style="position: relative;top:-10px;"
[checked]="passwordRules['historyLastUse'].enabled" color="primary"
(change)="toggleRule(passwordRules['historyLastUse']);">
</mat-slide-toggle>
</mat-icon>
<p mat-line>
<mat-form-field style="width: 100%;">
<input type="number"
[disabled]="!passwordRules['historyLastUse'].enabled"
[name]="passwordRules['historyLastUse'].label"
[(ngModel)]="passwordRules['historyLastUse'].value" min="1"
pattern="^[1-9][0-9]*" matInput
placeholder="{{passwordRules['historyLastUse'].label}}" required>
</mat-form-field>
</p>
</mat-list-item>
</mat-list>
<div class="col-md-12 text-center" style="padding:10px; text-align: center">
<button mat-raised-button type="submit" color="primary" style="margin: 10px"
[disabled]="(!passwordForm.valid && !disabledForm()) || checkModif()">{{'lang.validate' | translate}}</button>
<button mat-raised-button type="button" color="default" [disabled]="checkModif()"
(click)="cancelModification()">{{'lang.cancel' | translate}}</button>
</div>
</form>
</mat-tab>
</mat-tab-group>
</mat-card>
</div>
</mat-sidenav-content>
<mat-sidenav #snavRight disableClose [mode]="signaturesService.mobileMode ? 'over': 'side'" [opened]="false"
fixedInViewport="true" position='end'>
</mat-sidenav>
</mat-sidenav-container>
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {TranslateService} from '@ngx-translate/core';
import {NotificationService} from '../../service/notification.service';
import {SignaturesContentService} from '../../service/signatures.service';
@Component({
templateUrl: 'securities-administration.component.html',
styleUrls: ['../administration.scss']
})
export class SecuritiesAdministrationComponent implements OnInit {
loading: boolean = false;
passwordRules: any = {
minLength: { enabled: false, value: 0 },
complexityUpper: { enabled: false, value: 0 },
complexityNumber: { enabled: false, value: 0 },
complexitySpecial: { enabled: false, value: 0 },
renewal: { enabled: false, value: 0 },
historyLastUse: { enabled: false, value: 0 },
lockTime: { enabled: false, value: 0 },
lockAttempts: { enabled: false, value: 0 },
};
passwordRulesClone: any = {};
passwordRulesList: any[] = [];
constructor(
public http: HttpClient,
private translate: TranslateService,
private notify: NotificationService,
public signaturesService: SignaturesContentService
) { }
ngOnInit(): void {
this.loading = true;
this.http.get('../rest/passwordRules')
.subscribe((data: any) => {
this.passwordRulesList = data.rules;
data.rules.forEach((rule: any) => {
this.passwordRules[rule.label].enabled = rule.enabled;
this.passwordRules[rule.label].value = rule.value;
this.passwordRules[rule.label].label = this.translate.instant('lang.password_' + rule.label + 'Required');
this.passwordRules[rule.label].id = rule.label;
this.loading = false;
});
this.passwordRulesClone = JSON.parse(JSON.stringify(this.passwordRules));
}, (err) => {
this.notify.error(err.error.errors);
});
}
cancelModification() {
this.passwordRules = JSON.parse(JSON.stringify(this.passwordRulesClone));
this.passwordRulesList.forEach((rule: any) => {
rule.enabled = this.passwordRules[rule.label].enabled;
rule.value = this.passwordRules[rule.label].value;
});
}
checkModif() {
return JSON.stringify(this.passwordRules) === JSON.stringify(this.passwordRulesClone);
}
disabledForm() {
return !this.passwordRules['lockTime'].enabled && !this.passwordRules['minLength'].enabled && !this.passwordRules['lockAttempts'].enabled && !this.passwordRules['renewal'].enabled && !this.passwordRules['historyLastUse'].enabled;
}
toggleRule(rule: any) {
rule.enabled = !rule.enabled;
this.passwordRulesList.forEach((rule2: any) => {
if (rule.id === 'lockAttempts' && (rule2.label === 'lockTime' || rule2.label === 'lockAttempts')) {
rule2.enabled = rule.enabled;
this.passwordRules['lockTime'].enabled = rule.enabled;
} else if (rule.id === rule2.label) {
rule2.enabled = rule.enabled;
}
});
}
onSubmit() {
this.passwordRulesList.forEach((rule: any) => {
rule.enabled = this.passwordRules[rule.label].enabled;
rule.value = this.passwordRules[rule.label].value;
});
this.http.put('../rest/passwordRules', { rules: this.passwordRulesList })
.subscribe(() => {
this.passwordRulesClone = JSON.parse(JSON.stringify(this.passwordRules));
this.notify.success('lang.passwordRulesUpdated');
}, (err: any) => {
this.notify.error(err.error.errors);
});
}
}
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { AuthGuard } from './service/auth.guard'; import { AuthGuard } from './service/auth.guard';
import { AdministrationComponent } from './administration/home/administration.component'; import { AdministrationComponent } from './administration/home/administration.component';
import { UsersListComponent } from './administration/user/users-list.component'; import { UsersListComponent } from './administration/user/users-list.component';
...@@ -15,6 +15,7 @@ import { DocumentComponent } from './document/document.component'; ...@@ -15,6 +15,7 @@ import { DocumentComponent } from './document/document.component';
import { LoginComponent } from './login/login.component'; import { LoginComponent } from './login/login.component';
import { ForgotPasswordComponent } from './login/forgotPassword/forgotPassword.component'; import { ForgotPasswordComponent } from './login/forgotPassword/forgotPassword.component';
import { UpdatePasswordComponent } from './login/updatePassword/updatePassword.component'; import { UpdatePasswordComponent } from './login/updatePassword/updatePassword.component';
import {SecuritiesAdministrationComponent} from './administration/security/securities-administration.component';
@NgModule({ @NgModule({
imports: [ imports: [
...@@ -31,6 +32,7 @@ import { UpdatePasswordComponent } from './login/updatePassword/updatePassword.c ...@@ -31,6 +32,7 @@ import { UpdatePasswordComponent } from './login/updatePassword/updatePassword.c
{ path: 'administration/connections/ldaps/new', canActivate: [AuthGuard], component: LdapComponent }, { path: 'administration/connections/ldaps/new', canActivate: [AuthGuard], component: LdapComponent },
{ path: 'administration/connections/ldaps/:id', canActivate: [AuthGuard], component: LdapComponent }, { path: 'administration/connections/ldaps/:id', canActivate: [AuthGuard], component: LdapComponent },
{ path: 'administration/emailConfiguration', canActivate: [AuthGuard], component: SendmailComponent }, { path: 'administration/emailConfiguration', canActivate: [AuthGuard], component: SendmailComponent },
{ path: 'administration/passwordRules', canActivate: [AuthGuard], component: SecuritiesAdministrationComponent },
{ path: 'documents/:id', canActivate: [AuthGuard], component: DocumentComponent }, { path: 'documents/:id', canActivate: [AuthGuard], component: DocumentComponent },
{ path: 'documents', canActivate: [AuthGuard], component: DocumentComponent }, { path: 'documents', canActivate: [AuthGuard], component: DocumentComponent },
{ path: 'login', component: LoginComponent }, { path: 'login', component: LoginComponent },
......
...@@ -64,6 +64,7 @@ import { LdapComponent } from './administration/connection/ldap/ldap.component'; ...@@ -64,6 +64,7 @@ import { LdapComponent } from './administration/connection/ldap/ldap.component';
import { SendmailComponent } from './administration/sendmail/sendmail.component'; import { SendmailComponent } from './administration/sendmail/sendmail.component';
import { GroupsListComponent } from './administration/group/groups-list.component'; import { GroupsListComponent } from './administration/group/groups-list.component';
import { GroupComponent } from './administration/group/group.component'; import { GroupComponent } from './administration/group/group.component';
import {SecuritiesAdministrationComponent} from './administration/security/securities-administration.component';
// SERVICES // SERVICES
...@@ -117,7 +118,8 @@ import { SortPipe } from './plugins/sorting.pipe'; ...@@ -117,7 +118,8 @@ import { SortPipe } from './plugins/sorting.pipe';
GroupsListComponent, GroupsListComponent,
GroupComponent, GroupComponent,
PluginAutocompleteComponent, PluginAutocompleteComponent,
SortPipe SortPipe,
SecuritiesAdministrationComponent
], ],
imports: [ imports: [
FormsModule, FormsModule,
......
...@@ -34,7 +34,7 @@ export class AuthInterceptor implements HttpInterceptor { ...@@ -34,7 +34,7 @@ export class AuthInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
// We don't want to intercept some routes // We don't want to intercept some routes
if (this.excludeUrls.indexOf(request.url) > -1 || request.url.indexOf('/password') > -1) { if ((this.excludeUrls.indexOf(request.url) > -1 || request.url.indexOf('/password') > -1) && request.url.indexOf('/passwordRules') === -1 && request.method.indexOf('PUT') === -1) {
return next.handle(request); return next.handle(request);
} else { } else {
// Add current token in header request // Add current token in header request
......
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