From 61cb5c82417f327242e1334b040a4a30f4366352 Mon Sep 17 00:00:00 2001 From: Damien <damien.burel@maarch.org> Date: Mon, 9 Jul 2018 10:41:55 +0200 Subject: [PATCH] FEAT #7659 Renewal + password modification --- .../password-modification.component.html | 24 ++++++++ apps/maarch_entreprise/index.php | 6 +- .../js/angular/app/app-routing.module.ts | 12 ++-- .../js/angular/app/app.module.ts | 4 +- .../app/password-modification.component.ts | 60 +++++++++++++++++++ core/class/class_security.php | 18 +++++- sql/data_fr.sql | 2 +- sql/develop.sql | 4 +- sql/structure.sql | 2 +- src/core/models/PasswordModel.php | 4 +- 10 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 apps/maarch_entreprise/Views/password-modification.component.html create mode 100644 apps/maarch_entreprise/js/angular/app/password-modification.component.ts diff --git a/apps/maarch_entreprise/Views/password-modification.component.html b/apps/maarch_entreprise/Views/password-modification.component.html new file mode 100644 index 00000000000..8b607ef09a8 --- /dev/null +++ b/apps/maarch_entreprise/Views/password-modification.component.html @@ -0,0 +1,24 @@ +<div class="admin-container" [class.admin-is-mobile]="mobileQuery.matches"> + <mat-toolbar color="primary" class="admin-toolbar"> + <button mat-button (click)="snav.toggle()"> + <mat-icon class="maarchLogo" [svgIcon]="mobileQuery.matches ? 'maarchLogoOnly' : 'maarchLogo'"></mat-icon> + </button> + <h1 class="admin-toolbar-title">{{lang.myProfile}} + <small [class.hide-for-mobile]="mobileQuery.matches">{{user.firstname}} {{user.lastname}}</small> + </h1> + <span style="flex: 1 1 auto;"></span> + <menu-top></menu-top> + <button mat-icon-button (click)="snav2.toggle()"> + <mat-icon class="fa fa-cog fa-2x"></mat-icon> + </button> + </mat-toolbar> + <mat-sidenav-container class="admin-sidenav-container" [style.marginTop.px]="mobileQuery.matches ? 56 : 0"> + <mat-sidenav-content> + <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-card> + </mat-sidenav-content> + </mat-sidenav-container> +</div> \ No newline at end of file diff --git a/apps/maarch_entreprise/index.php b/apps/maarch_entreprise/index.php index 9dc0081bc56..837374dda96 100755 --- a/apps/maarch_entreprise/index.php +++ b/apps/maarch_entreprise/index.php @@ -335,7 +335,7 @@ if (file_exists($path)) { && $_SESSION['abs_user_status'] == true) { include 'modules/basket/advert_missing.php'; - } else { + } elseif (empty($_REQUEST['trigger'])) { $core->insert_page(); } ?> @@ -359,7 +359,9 @@ if (file_exists($path)) { </div> </body> <?php - if ($_SESSION['user']['UserId'] == 'superadmin' && !empty($_REQUEST['administration'])) { + if (!empty($_REQUEST['trigger']) && $_REQUEST['trigger'] == 'changePass') { + ?><script>triggerAngular('#/password-modification')</script><?php + } elseif ($_SESSION['user']['UserId'] == 'superadmin' && !empty($_REQUEST['administration'])) { ?> <script>triggerAngular('#/administration')</script> <?php diff --git a/apps/maarch_entreprise/js/angular/app/app-routing.module.ts b/apps/maarch_entreprise/js/angular/app/app-routing.module.ts index 52fa0a3905c..edca9400eef 100755 --- a/apps/maarch_entreprise/js/angular/app/app-routing.module.ts +++ b/apps/maarch_entreprise/js/angular/app/app-routing.module.ts @@ -1,15 +1,17 @@ -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; -import { ProfileComponent } from './profile.component'; -import { SignatureBookComponent } from './signature-book.component'; -import { SaveNumericPackageComponent } from './save-numeric-package.component'; +import { ProfileComponent } from './profile.component'; +import { PasswordModificationComponent } from './password-modification.component'; +import { SignatureBookComponent } from './signature-book.component'; +import { SaveNumericPackageComponent } from './save-numeric-package.component'; @NgModule({ imports: [ RouterModule.forRoot([ { path: 'profile', component: ProfileComponent }, + { path: 'password-modification', component: PasswordModificationComponent }, { path: 'saveNumericPackage', component: SaveNumericPackageComponent }, { path: 'groups/:groupId/baskets/:basketId/signatureBook/:resId', component: SignatureBookComponent }, { path: '**', redirectTo: '', pathMatch: 'full' }, diff --git a/apps/maarch_entreprise/js/angular/app/app.module.ts b/apps/maarch_entreprise/js/angular/app/app.module.ts index 71ac7c732c4..b8f41b0675d 100755 --- a/apps/maarch_entreprise/js/angular/app/app.module.ts +++ b/apps/maarch_entreprise/js/angular/app/app.module.ts @@ -10,6 +10,7 @@ import { AppRoutingModule } from './app-routing.module'; import { AdministrationModule } from './administration/administration.module'; import { ProfileComponent } from './profile.component'; +import { PasswordModificationComponent } from './password-modification.component'; import { SignatureBookComponent, SafeUrlPipe } from './signature-book.component'; import { SaveNumericPackageComponent } from './save-numeric-package.component'; @@ -22,9 +23,10 @@ import { SaveNumericPackageComponent } from './save-numeric-package.com declarations: [ AppComponent, ProfileComponent, - SaveNumericPackageComponent, + PasswordModificationComponent, SignatureBookComponent, SafeUrlPipe, + SaveNumericPackageComponent, CustomSnackbarComponent, ConfirmModalComponent ], diff --git a/apps/maarch_entreprise/js/angular/app/password-modification.component.ts b/apps/maarch_entreprise/js/angular/app/password-modification.component.ts new file mode 100644 index 00000000000..34e2091a72d --- /dev/null +++ b/apps/maarch_entreprise/js/angular/app/password-modification.component.ts @@ -0,0 +1,60 @@ +import { ChangeDetectorRef, Component, OnInit } from '@angular/core'; +import { MediaMatcher } from '@angular/cdk/layout'; +import { HttpClient } from '@angular/common/http'; +import { LANG } from './translate.component'; +import { NotificationService } from './notification.service'; +import { MatDialog } from '@angular/material'; + +declare function $j(selector: any): any; + +declare var tinymce: any; +declare var angularGlobals: any; + + +@Component({ + templateUrl: "../../../Views/password-modification.component.html", + providers: [NotificationService] +}) +export class PasswordModificationComponent implements OnInit { + + private _mobileQueryListener: () => void; + mobileQuery : MediaQueryList; + + coreUrl : string; + lang : any = LANG; + loading : boolean = false; + + passwordModel : any = { + currentPassword : "", + newPassword : "", + reNewPassword : "", + }; + + constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, public http: HttpClient, private notify: NotificationService, public dialog: MatDialog) { + $j("link[href='merged_css.php']").remove(); + this.mobileQuery = media.matchMedia('(max-width: 768px)'); + this._mobileQueryListener = () => changeDetectorRef.detectChanges(); + this.mobileQuery.addListener(this._mobileQueryListener); + } + + prepare() { + $j('#inner_content').remove(); + $j('#inner_content_contact').parent('div').remove(); + $j('#inner_content_contact').remove(); + $j('#menunav').hide(); + $j('#divList').remove(); + $j('#magicContactsTable').remove(); + $j('#manageBasketsOrderTable').remove(); + $j('#controlParamTechnicTable').remove(); + $j('#container').width("99%"); + if ($j('#content h1')[0] && $j('#content h1')[0] != $j('my-app h1')[0]) { + $j('#content h1')[0].remove(); + } + } + + ngOnInit(): void { + this.prepare(); + this.coreUrl = angularGlobals.coreUrl; + + } +} diff --git a/core/class/class_security.php b/core/class/class_security.php index 75a6d012e56..444d7464b21 100755 --- a/core/class/class_security.php +++ b/core/class/class_security.php @@ -229,12 +229,28 @@ class security extends Database ); } + $passwordRules = \SrcCore\models\PasswordModel::getEnabledRules(); + + if (!empty($passwordRules['renewal'])) { + $currentDate = new \DateTime(); + $lastModificationDate = new \DateTime($user->__get('password_modification_date')); + $lastModificationDate->add(new DateInterval("P{$passwordRules['renewal']}D")); + + if ($currentDate > $lastModificationDate) { + return [ + 'user' => $array, + 'error' => $error, + 'url' => 'index.php?trigger=changePass', + ]; + } + } + $loggingMethod = \SrcCore\models\CoreConfigModel::getLoggingMethod(); if ($array['change_pass'] == 'Y' && !in_array($loggingMethod['id'], ['sso', 'cas', 'ldap', 'ozwillo'])) { return array( 'user' => $array, 'error' => $error, - 'url' => 'index.php?display=true&page=change_pass', + 'url' => 'index.php?trigger=changePass', ); } elseif (isset($_SESSION['requestUri']) && trim($_SESSION['requestUri']) != '' diff --git a/sql/data_fr.sql b/sql/data_fr.sql index edf9fb3b576..0ceabae4dcb 100755 --- a/sql/data_fr.sql +++ b/sql/data_fr.sql @@ -1756,7 +1756,7 @@ INSERT INTO password_rules (label, "value") VALUES ('complexityNumber', 0); INSERT INTO password_rules (label, "value") VALUES ('complexitySpecial', 0); INSERT INTO password_rules (label, "value") VALUES ('lockAttempts', 3); INSERT INTO password_rules (label, "value") VALUES ('lockTime', 5); -INSERT INTO password_rules (label, "value") VALUES ('useNumber', 2); +INSERT INTO password_rules (label, "value") VALUES ('historyLastUse', 2); INSERT INTO password_rules (label, "value") VALUES ('renewal', 90); diff --git a/sql/develop.sql b/sql/develop.sql index 995e320185f..41ce64997fe 100644 --- a/sql/develop.sql +++ b/sql/develop.sql @@ -98,10 +98,10 @@ INSERT INTO password_rules (label, "value") VALUES ('complexityNumber', 0); INSERT INTO password_rules (label, "value") VALUES ('complexitySpecial', 0); INSERT INTO password_rules (label, "value") VALUES ('lockAttempts', 3); INSERT INTO password_rules (label, "value") VALUES ('lockTime', 5); -INSERT INTO password_rules (label, "value") VALUES ('useNumber', 2); +INSERT INTO password_rules (label, "value") VALUES ('historyLastUse', 2); INSERT INTO password_rules (label, "value") VALUES ('renewal', 90); ALTER TABLE users DROP COLUMN IF EXISTS password_modification_date; -ALTER TABLE users ADD COLUMN password_modification_date timestamp without time zone; +ALTER TABLE users ADD COLUMN password_modification_date timestamp without time zone DEFAULT CURRENT_TIMESTAMP; ALTER TABLE users DROP COLUMN IF EXISTS failed_authentication; ALTER TABLE users ADD COLUMN failed_authentication INTEGER DEFAULT 0; ALTER TABLE users DROP COLUMN IF EXISTS locked_until; diff --git a/sql/structure.sql b/sql/structure.sql index c147c0a3330..644231b085b 100755 --- a/sql/structure.sql +++ b/sql/structure.sql @@ -227,7 +227,7 @@ CREATE TABLE users status character varying(10) NOT NULL DEFAULT 'OK'::character varying, enabled character(1) NOT NULL DEFAULT 'Y'::bpchar, change_password character(1) NOT NULL DEFAULT 'Y'::bpchar, - password_modification_date timestamp without time zone, + password_modification_date timestamp without time zone DEFAULT CURRENT_TIMESTAMP, loginmode character varying(50) DEFAULT NULL::character varying, cookie_key character varying(255) DEFAULT NULL::character varying, cookie_date timestamp without time zone, diff --git a/src/core/models/PasswordModel.php b/src/core/models/PasswordModel.php index 21090c9bf27..8317b716538 100644 --- a/src/core/models/PasswordModel.php +++ b/src/core/models/PasswordModel.php @@ -94,14 +94,14 @@ class PasswordModel $passwordRules = PasswordModel::getEnabledRules(); - if (!empty($passwordRules['useNumber'])) { + if (!empty($passwordRules['historyLastUse'])) { $passwordHistory = DatabaseModel::select([ 'select' => ['password'], 'table' => ['password_history'], 'where' => ['user_serial_id = ?'], 'data' => [$aArgs['userSerialId']], 'order_by' => ['id DESC'], - 'limit' => $passwordRules['useNumber'] + 'limit' => $passwordRules['historyLastUse'] ]); foreach ($passwordHistory as $value) { -- GitLab