Skip to content
Snippets Groups Projects
Commit 5c141eee authored by Florent Poittevin's avatar Florent Poittevin
Browse files

feat: 830 Update token when user edit is own token information and display warning before

parent 5bb99ff9
No related branches found
No related tags found
No related merge requests found
Showing
with 273 additions and 10 deletions
......@@ -8,9 +8,7 @@ import {AdminOrganizationalUnitFundingAgencyState} from "@admin/orgunit/stores/f
import {AdminOrganizationalUnitInstitutionState} from "@admin/orgunit/stores/institution/admin-organizational-unit-institution.state";
import {AdminOrganizationalUnitPersonRoleState} from "@admin/orgunit/stores/person-role/admin-organizational-unit-person-role.state";
import {AdminPersonState} from "@admin/person/stores/admin-person.state";
import {
AdminPersonInstitutionsState,
} from "@admin/person/stores/institutions/admin-people-institutions.state";
import {AdminPersonInstitutionsState} from "@admin/person/stores/institutions/admin-people-institutions.state";
import {AdminPersonOrgUnitRoleState} from "@admin/person/stores/person-role/admin-person-orgunit-role.state";
import {AdminPreservationPolicyState} from "@admin/preservation-policy/stores/admin-preservation-policy.state";
import {AdminRoleState} from "@admin/role/stores/admin-role.state";
......@@ -63,7 +61,7 @@ const presentationals = [];
AdminRoleState,
AdminFundingAgenciesState,
AdminFundingAgenciesOrganizationalUnitState,
AdminPersonInstitutionsState
AdminPersonInstitutionsState,
]),
],
entryComponents: [
......
<h1 mat-dialog-title>{{"admin.user.dialog.editOwnRoles.title" | translate}}</h1>
<div mat-dialog-content>
<p class="warning">{{"admin.user.dialog.editOwnRoles.warning" | translate}}</p>
<p *ngIf="data.newRolesAfterUpdate.length === 0"
class="message-alert"
>{{"admin.user.dialog.editOwnRoles.noMoreRight" | translate}}</p>
<p *ngIf="data.newRolesAfterUpdate.length > 0
&& !data.newRolesAfterUpdate.includes(applicationRoleEnum.admin)
&& !data.newRolesAfterUpdate.includes(applicationRoleEnum.root)"
class="message-alert"
>{{"admin.user.dialog.editOwnRoles.looseAdminRole" | translate}}</p>
<div *ngIf="data.removedRoles.length > 0"
class="summary"
>
<label>{{"admin.user.dialog.editOwnRoles.summary.removedRoles" | translate}}</label>
<ul>
<li *ngFor="let role of data.removedRoles">{{role}}</li>
</ul>
</div>
<div *ngIf="data.addedRoles.length > 0"
class="summary"
>
<label>{{"admin.user.dialog.editOwnRoles.summary.addedRoles" | translate}}</label>
<ul>
<li *ngFor="let role of data.addedRoles">{{role}}</li>
</ul>
</div>
</div>
<div mat-dialog-actions>
<button mat-flat-button
color="warn"
(click)="confirm()"
>{{"admin.user.dialog.editOwnRoles.confirm" | translate}}</button>
<button mat-button
[mat-dialog-close]=""
cdkFocusInitial
>{{"admin.user.dialog.editOwnRoles.cancel" | translate}}</button>
</div>
@import "../sass/abstracts/mixins";
@import "../sass/abstracts/variables";
:host {
.warning {
white-space: pre;
}
.message-alert {
color: $error;
}
.summary {
ul {
padding-top: 10px;
li {
list-style-type: initial;
margin-left: 15px;
}
}
padding: 10px 0;
}
}
import {
ChangeDetectionStrategy,
Component,
Inject,
OnInit,
} from "@angular/core";
import {
MAT_DIALOG_DATA,
MatDialogRef,
} from "@angular/material";
import {Store} from "@ngxs/store";
import {SharedAbstractContainer} from "@shared/components/containers/shared-abstract/shared-abstract.container";
import {ApplicationRoleEnum} from "@shared/enums/application-role.enum";
@Component({
selector: "dlcm-admin-user-edit-role-current-user-dialog",
templateUrl: "./admin-user-edit-role-current-user.dialog.html",
styleUrls: ["./admin-user-edit-role-current-user.dialog.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AdminUserEditRoleCurrentUserDialog extends SharedAbstractContainer implements OnInit {
get applicationRoleEnum(): typeof ApplicationRoleEnum {
return ApplicationRoleEnum;
}
constructor(protected store: Store,
protected dialogRef: MatDialogRef<AdminUserEditRoleCurrentUserDialog>,
@Inject(MAT_DIALOG_DATA) public data: AdminUserEditRoleCurrentUserDialogData) {
super();
}
ngOnInit(): void {
super.ngOnInit();
}
confirm(): void {
this.dialogRef.close(true);
}
}
export interface AdminUserEditRoleCurrentUserDialogData {
removedRoles: string[];
addedRoles: string[];
newRolesAfterUpdate: string[];
oldRolesBeforeUpdate: string[];
}
......@@ -111,6 +111,10 @@
</div>
</div>
<!-- TODO DEBUG CHECKBOX NOT CONNECTED TO FORM WHEN EDIT NOT IS IN EDIT MODE-->
<!-- TODO REMOVE USELESS MAT ERROR-->
<!-- {{form.get(formDefinition.applicationRoles).value | json}}-->
<div class="submit-button">
<button *ngIf="!readonly"
mat-flat-button
......
......@@ -13,6 +13,7 @@ import {
AccessOrganizationalUnit,
ApplicationRole,
Person,
User,
} from "@app/generated-api";
import {SharedAbstractFormPresentational} from "@shared/components/presentationals/shared-abstract-form/shared-abstract-form.presentational";
import {UserApplicationRoleEnum} from "@shared/enums/user-application-role.enum";
......@@ -41,6 +42,9 @@ export class AdminUserFormPresentational extends SharedAbstractFormPresentationa
@Input()
listOrganizationalUnit: AccessOrganizationalUnit[];
@Input()
currentUser: User;
constructor(protected readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _fb: FormBuilder) {
super(_changeDetectorRef);
......
......@@ -11,8 +11,12 @@
<div class="wrapper"
[dlcmSpinner]="isLoadingWithDependencyObs | async"
>
<label *ngIf="isCurrentUser(currentUser | async)"
class="current-user-admin"
>{{"admin.user.editCurrentUser" | translate}}</label>
<dlcm-admin-user-form #formPresentational
*ngIf="isReadyToBeDisplayedObs | async"
[currentUser]="currentUser | async"
[model]="currentObs | async"
[listPersons]="listPersonObs | async"
[listOrganizationalUnit]="listOrgUnitObs | async"
......
@import "../../../../../../shared/components/routables/shared-abstract-edit/shared-abstract-edit.routable.scss";
@import "../sass/abstracts/variables";
.current-user-admin {
text-align: center;
padding: 0 10px 20px;
color: $warning;
display: block;
}
import {adminUserActionNameSpace} from "@admin/user/stores/admin-user.action";
import {
AdminUserEditRoleCurrentUserDialog,
AdminUserEditRoleCurrentUserDialogData,
} from "@admin/user/components/dialogs/admin-user-edit-role-current-user/admin-user-edit-role-current-user.dialog";
import {
AdminUserAction,
adminUserActionNameSpace,
} from "@admin/user/stores/admin-user.action";
import {
AdminUserState,
AdminUserStateModel,
......@@ -7,12 +14,17 @@ import {
ChangeDetectionStrategy,
Component,
} from "@angular/core";
import {MatDialog} from "@angular/material/dialog";
import {ActivatedRoute} from "@angular/router";
import {
AccessOrganizationalUnit,
Person,
} from "@app/generated-api";
import {AppAction} from "@app/stores/app.action";
import {AppState} from "@app/stores/app.state";
import {
Actions,
ofActionCompleted,
Select,
Store,
} from "@ngxs/store";
......@@ -20,25 +32,104 @@ import {SharedAbstractEditRoutable} from "@shared/components/routables/shared-ab
import {LocalStateEnum} from "@shared/enums/local-state.enum";
import {UserExtended} from "@shared/models/business/user-extended.model";
import {LocalStateModel} from "@shared/models/local-state.model";
import {Observable} from "rxjs";
import {
Observable,
of,
} from "rxjs";
import {
take,
tap,
} from "rxjs/operators";
import {
isNullOrUndefined,
isTrue,
ModelFormControlEvent,
} from "solidify-frontend";
@Component({
selector: "dlcm-admin-user-edit-routable",
templateUrl: "./admin-user-edit.routable.html",
styleUrls: ["../../../../../../shared/components/routables/shared-abstract-edit/shared-abstract-edit.routable.scss"],
styleUrls: ["./admin-user-edit.routable.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AdminUserEditRoutable extends SharedAbstractEditRoutable<UserExtended, AdminUserStateModel> {
@Select(AdminUserState.isLoadingWithDependency) isLoadingWithDependencyObs: Observable<boolean>;
@Select(AdminUserState.isReadyToBeDisplayed) isReadyToBeDisplayedObs: Observable<boolean>;
@Select(AppState.currentUser) currentUser: Observable<UserExtended>;
@Select((state: LocalStateModel) => state.shared.shared_person.list) listPersonObs: Observable<Person[]>;
@Select((state: LocalStateModel) => state.shared.shared_organizationalUnit.list) listOrgUnitObs: Observable<AccessOrganizationalUnit[]>;
constructor(protected store: Store,
protected route: ActivatedRoute) {
protected route: ActivatedRoute,
private readonly _dialog: MatDialog,
private readonly _actions$: Actions) {
super(store, route, LocalStateEnum.admin_user, adminUserActionNameSpace, LocalStateEnum.admin);
}
getSubResourceWithParentId(id: string): void {
}
update(model: ModelFormControlEvent<UserExtended>): Observable<any> {
this.subscribe(this.currentUser.pipe(
take(1),
tap(currentUser => {
if (!this.isCurrentUser(currentUser)) {
super.update(model);
return;
}
const newApplicationRoles = model.model.applicationRoles.map(a => a.resId);
const oldApplicationRoles = currentUser.applicationRoles.map(a => a.resId);
const removedRoles = oldApplicationRoles.filter(item => newApplicationRoles.indexOf(item) < 0);
const addedRoles = newApplicationRoles.filter(item => oldApplicationRoles.indexOf(item) < 0);
if (removedRoles.length === 0 && addedRoles.length === 0) {
super.update(model);
return;
}
this.openModalConfirmEditRole({
newRolesAfterUpdate: newApplicationRoles,
oldRolesBeforeUpdate: oldApplicationRoles,
addedRoles: addedRoles,
removedRoles: removedRoles,
} as AdminUserEditRoleCurrentUserDialogData, model);
}),
));
return of();
}
private openModalConfirmEditRole(data: AdminUserEditRoleCurrentUserDialogData, model: ModelFormControlEvent<UserExtended>): void {
this.subscribe(this._dialog.open(AdminUserEditRoleCurrentUserDialog, {
data: data,
}).afterClosed().pipe(
tap((isConfirmed: boolean | undefined) => {
if (isNullOrUndefined(isConfirmed)) {
return;
}
if (isTrue(isConfirmed)) {
this.updateAndLogout(model);
}
}),
));
}
private updateAndLogout(model: ModelFormControlEvent<UserExtended>): void {
super.update(model);
this.subscribe(this._actions$.pipe(
ofActionCompleted(AdminUserAction.UpdateSuccess),
tap((result) => {
if (isTrue(result.result.successful)) {
this.store.dispatch(new AppAction.Logout());
}
}),
));
}
isCurrentUser(userExtended: UserExtended): boolean {
if (isNullOrUndefined(userExtended)) {
return false;
}
return userExtended.resId === this._resId;
}
}
import {AdminUserDeleteDialog} from "@admin/user/components/dialogs/admin-user-delete/admin-user-delete.dialog";
import {AdminUserEditRoleCurrentUserDialog} from "@admin/user/components/dialogs/admin-user-edit-role-current-user/admin-user-edit-role-current-user.dialog";
import {AdminUserFormPresentational} from "@admin/user/components/presentationals/admin-user-form/admin-user-form.presentational";
import {AdminUserCreateRoutable} from "@admin/user/components/routables/admin-user-create/admin-user-create.routable";
import {AdminUserDetailRoutable} from "@admin/user/components/routables/admin-user-detail/admin-user-detail.routable";
......@@ -20,6 +21,7 @@ const routables = [
const containers = [];
const dialogs = [
AdminUserDeleteDialog,
AdminUserEditRoleCurrentUserDialog,
];
const presentationals = [
AdminUserFormPresentational,
......
......@@ -75,9 +75,9 @@ export abstract class SharedAbstractEditRoutable<TResourceModel, UResourceStateM
return this._resId;
}
update(model: ModelFormControlEvent<TResourceModel>): void {
update(model: ModelFormControlEvent<TResourceModel>): Observable<any> {
super.saveInProgress();
this.store.dispatch(ResourceActionHelper.update<TResourceModel>(this.resourceNameSpace, model));
return this.store.dispatch(ResourceActionHelper.update<TResourceModel>(this.resourceNameSpace, model));
}
backToDetail(): void {
......
......@@ -431,8 +431,21 @@
"confirm": "Yes",
"message": "Are you sure you want to delete the User '{{name}}'?",
"title": "Confirm deletion"
},
"editOwnRoles": {
"cancel": "Cancel",
"confirm": "Yes, I'm sure!",
"looseAdminRole": "You will lose access to the administration features.",
"noMoreRight": "You have removed all your rights which will prevent you from accessing the application!",
"summary": {
"addedRoles": "Added roles :",
"removedRoles": "Removed roles :"
},
"title": "Be careful, you will modify your roles!",
"warning": "This will result in a change of rights within the application.\nYou're going to be dislodged."
}
},
"editCurrentUser": "Warning, you will edit your own informations !",
"form": {
"accessToken": "Access Token",
"email": "Email",
......
......@@ -431,8 +431,21 @@
"confirm": "Yes",
"message": "Are you sure you want to delete the User '{{name}}'?",
"title": "Confirm deletion"
},
"editOwnRoles": {
"cancel": "Cancel",
"confirm": "Yes, I'm sure!",
"looseAdminRole": "You will lose access to the administration features.",
"noMoreRight": "You have removed all your rights which will prevent you from accessing the application!",
"summary": {
"addedRoles": "Added roles :",
"removedRoles": "Removed roles :"
},
"title": "Be careful, you will modify your roles!",
"warning": "This will result in a change of rights within the application.\nYou're going to be dislodged."
}
},
"editCurrentUser": "Warning, you will edit your own informations !",
"form": {
"accessToken": "Access Token",
"email": "Email",
......
......@@ -431,8 +431,21 @@
"confirm": "Oui",
"message": "Êtes-vous sûr de vouloir supprimer l'utilisateur '{{name}}'?",
"title": "Confirmer suppresion"
},
"editOwnRoles": {
"cancel": "Annuler",
"confirm": "Oui, je suis sûr !",
"looseAdminRole": "Vous allez perdre l'accès aux fonctionnalités d'administration.",
"noMoreRight": "Vous avez retiré l'intégralité de vos droits ce qui vous empéchera d'accéder à l'application !",
"summary": {
"addedRoles": "Rôles ajoutés :",
"removedRoles": "Rôles supprimés :"
},
"title": "Attention, vous allez modifier vos rôles !",
"warning": "Cela va engendrer un changement de droits au sein de l'application.\nVous allez être déloggué."
}
},
"editCurrentUser": "Attention, vous allez éditer vos propres informations !",
"form": {
"accessToken": "Jeton d'accès OAuth",
"email": "Email",
......
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