Commit b5162318 authored by Florent POITTEVIN's avatar Florent POITTEVIN
Browse files

feat: 1496 refacto security service for role in org unit

parent 76cecb36
......@@ -206,7 +206,6 @@ export class DepositState extends ResourceLogoState<DepositStateModel, Deposit>
private readonly _FOLDER_QUERY_PARAM: string = "folder";
private readonly _DEPOSIT_REJECT_MESSAGE: string = "message";
constructor(protected apiService: ApiService,
protected store: Store,
protected notificationService: NotificationService,
......@@ -299,10 +298,8 @@ export class DepositState extends ResourceLogoState<DepositStateModel, Deposit>
if (isNullOrUndefined(listAuthorizedOrgUnit) || isEmptyArray(listAuthorizedOrgUnit)) {
return;
}
this._securityService.canCreateDepositOnOrgUnit(action.organizationalUnitId).pipe(
take(1),
tap(canCreate => ctx.dispatch(new DepositAction.CanCreate(canCreate))),
).subscribe();
const canCreate = this._securityService.canCreateDepositOnOrgUnit(action.organizationalUnitId);
ctx.dispatch(new DepositAction.CanCreate(canCreate));
const orgUnit = listAuthorizedOrgUnit.find(o => o.resId === action.organizationalUnitId);
ctx.patchState({
counterTabInProgress: undefined,
......@@ -487,12 +484,12 @@ export class DepositState extends ResourceLogoState<DepositStateModel, Deposit>
reject(ctx: StateContext<DepositStateModel>, action: DepositAction.Reject): Observable<Result> {
return this.apiService.post<Result>(`${this._urlResource + urlSeparator + action.deposit.resId + urlSeparator + ApiActionEnum.REJECT}?${this._DEPOSIT_REJECT_MESSAGE}=${action.message}`)
.pipe(
tap(deposit => ctx.dispatch(new DepositAction.RejectSuccess(deposit))),
catchError(error => {
ctx.dispatch(new DepositAction.RejectFail());
throw new SolidifyStateError(this, error);
}),
);
tap(deposit => ctx.dispatch(new DepositAction.RejectSuccess(deposit))),
catchError(error => {
ctx.dispatch(new DepositAction.RejectFail());
throw new SolidifyStateError(this, error);
}),
);
}
@Action(DepositAction.RejectSuccess)
......
......@@ -190,12 +190,10 @@ export class PreservationSpaceOrganizationalUnitState extends ResourceLogoState<
}
@Action(PreservationSpaceOrganizationalUnitAction.ComputeCurrentUserIsManager)
computeCurrentUserIsManager(ctx: StateContext<PreservationSpaceOrganizationalUnitStateModel>, action: PreservationSpaceOrganizationalUnitAction.ComputeCurrentUserIsManager): void | Observable<any> {
return this._securityService.isManagerOfOrgUnit(ctx.getState().current.resId).pipe(
tap(isManager => {
ctx.dispatch(new PreservationSpaceOrganizationalUnitAction.SaveCurrentUserIsManagerAndRetrievePersonRoleIfManager(isManager));
}),
);
computeCurrentUserIsManager(ctx: StateContext<PreservationSpaceOrganizationalUnitStateModel>, action: PreservationSpaceOrganizationalUnitAction.ComputeCurrentUserIsManager): void | boolean {
const isManager = this._securityService.isManagerOfOrgUnit(ctx.getState().current.resId);
ctx.dispatch(new PreservationSpaceOrganizationalUnitAction.SaveCurrentUserIsManagerAndRetrievePersonRoleIfManager(isManager));
return isManager;
}
@Action(PreservationSpaceOrganizationalUnitAction.SaveCurrentUserIsManager)
......
......@@ -216,6 +216,7 @@ export interface OrganizationalUnit extends OrganizationalUnitPartial, BaseResou
researchDomains?: ResearchDomain[];
keywords?: string[];
defaultLicense?: License;
role?: Role | null;
logo?: Logo;
}
......
......@@ -11,8 +11,6 @@ import {
} from "@ngxs/store";
import {AppRoutesEnum} from "@shared/enums/routes.enum";
import {SecurityService} from "@shared/services/security.service";
import {Observable} from "rxjs";
import {map} from "rxjs/operators";
import {
ApiService,
NotificationService,
......@@ -30,11 +28,9 @@ export class OrganizationalUnitComputeIsManagerGuardService implements CanActiva
private readonly _actions$: Actions) {
}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
return this._securityService.isManagerOfOrgUnit(route.params[AppRoutesEnum.paramIdWithoutPrefixParam]).pipe(
map(authorized => {
this.store.dispatch(new PreservationSpaceOrganizationalUnitAction.SaveCurrentUserIsManager(authorized));
return true;
}));
canActivate(route: ActivatedRouteSnapshot): boolean {
const authorized = this._securityService.isManagerOfOrgUnit(route.params[AppRoutesEnum.paramIdWithoutPrefixParam]);
this.store.dispatch(new PreservationSpaceOrganizationalUnitAction.SaveCurrentUserIsManager(authorized));
return true;
}
}
......@@ -7,12 +7,10 @@ import {
import {Store} from "@ngxs/store";
import {AppRoutesEnum} from "@shared/enums/routes.enum";
import {SecurityService} from "@shared/services/security.service";
import {Observable} from "rxjs";
import {tap} from "rxjs/operators";
import {
ApiService,
NotificationService,
MARK_AS_TRANSLATABLE,
NotificationService,
} from "solidify-frontend";
@Injectable({
......@@ -26,12 +24,11 @@ export class OrganizationalUnitRoleGuardService implements CanActivate {
private readonly _notificationService: NotificationService) {
}
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
return this._securityService.isManagerOfOrgUnit(route.parent.params[AppRoutesEnum.paramIdWithoutPrefixParam]).pipe(
tap(authorized => {
if (authorized === false) {
this._notificationService.showWarning(MARK_AS_TRANSLATABLE("organizationalUnit.security.notification.noRightForThisAction"));
}
}));
canActivate(route: ActivatedRouteSnapshot): boolean {
const authorized = this._securityService.isManagerOfOrgUnit(route.parent.params[AppRoutesEnum.paramIdWithoutPrefixParam]);
if (authorized === false) {
this._notificationService.showWarning(MARK_AS_TRANSLATABLE("organizationalUnit.security.notification.noRightForThisAction"));
}
return authorized;
}
}
import {Injectable} from "@angular/core";
import {AppState} from "@app/stores/app.state";
import {AppOrgUnitPersonRoleAction} from "@app/stores/organizational-unit-person-role/app-organizational-unit-person-role.action";
import {DepositAction} from "@deposit/stores/deposit.action";
import {DepositState} from "@deposit/stores/deposit.state";
import {Enums} from "@enums";
import {Deposit} from "@models";
import {
Deposit,
Role,
} from "@models";
import {
Actions,
Store,
......@@ -13,12 +15,10 @@ import {
Observable,
of,
} from "rxjs";
import {
flatMap,
map,
} from "rxjs/operators";
import {map} from "rxjs/operators";
import {
isFalse,
isNotNullNorUndefined,
isNullOrUndefined,
MemoizedUtil,
} from "solidify-frontend";
......@@ -40,44 +40,44 @@ export class SecurityService {
private readonly _actions$: Actions) {
}
public canCreateDepositOnOrgUnit(orgUnitId: string): Observable<boolean> {
canCreateDepositOnOrgUnit(orgUnitId: string): boolean {
if (this.isRootOrAdmin()) {
return of(true);
return true;
}
if (!this.isMemberOfOrgUnit(orgUnitId)) {
return of(false);
return false;
}
return this.currentUserHaveRoleInListForOrgUnit(orgUnitId, this.DEPOSIT_ROLE_NEED_TO_CREATE);
}
public isManagerOfOrgUnit(orgUnitId: string): Observable<boolean> {
isManagerOfOrgUnit(orgUnitId: string): boolean {
if (this.isRootOrAdmin()) {
return of(true);
return true;
}
if (!this.isMemberOfOrgUnit(orgUnitId)) {
return of(false);
return false;
}
return this.currentUserHaveRoleInListForOrgUnit(orgUnitId, this.ORGUNIT_ROLE_NEED_TO_EDIT);
}
public isStewardOfOrgUnit(orgUnitId: string): Observable<boolean> {
isStewardOfOrgUnit(orgUnitId: string): boolean {
if (this.isRootOrAdmin()) {
return of(true);
return true;
}
if (!this.isMemberOfOrgUnit(orgUnitId)) {
return of(false);
return false;
}
return this.currentUserHaveRoleInListForOrgUnit(orgUnitId, this.ORGUNIT_ROLE_NEED_ACCESS_TO_CLOSED_DATASET);
}
public canSeeDetailDeposit(deposit: Deposit): boolean {
canSeeDetailDeposit(deposit: Deposit): boolean {
if (this.isRootOrAdmin()) {
return true;
}
return this.isMemberOfOrgUnit(deposit.organizationalUnitId);
}
public canSeeDetailDepositById(depositId: string): Observable<boolean> {
canSeeDetailDepositById(depositId: string): Observable<boolean> {
if (this.isRootOrAdmin()) {
return of(true);
}
......@@ -95,7 +95,7 @@ export class SecurityService {
}
}
public canEditDeposit(deposit: Deposit, currentRoleOnOrgUnit: string[]): boolean {
canEditDeposit(deposit: Deposit, currentRoleOnOrgUnit: string[]): boolean {
if (isFalse(this.depositInEditionStep(deposit))) {
return false;
}
......@@ -103,10 +103,10 @@ export class SecurityService {
if (isFalse(canSeeDetail)) {
return false;
}
return this.isCurrentRoleOnOrgUnitAuthorized(currentRoleOnOrgUnit, this.DEPOSIT_ROLE_NEED_TO_EDIT);
return this.isCurrentRoleIdOnOrgUnitAuthorized(currentRoleOnOrgUnit, this.DEPOSIT_ROLE_NEED_TO_EDIT);
}
public canApproveOrRejectDeposit(deposit: Deposit, currentRoleOnOrgUnit: string[]): boolean {
canApproveOrRejectDeposit(deposit: Deposit, currentRoleOnOrgUnit: string[]): boolean {
if (isFalse(this.depositInValidationStep(deposit))) {
return false;
}
......@@ -114,14 +114,14 @@ export class SecurityService {
if (isFalse(canSeeDetail)) {
return false;
}
return this.isCurrentRoleOnOrgUnitAuthorized(currentRoleOnOrgUnit, this.DEPOSIT_ROLE_NEED_TO_VALIDATE);
return this.isCurrentRoleIdOnOrgUnitAuthorized(currentRoleOnOrgUnit, this.DEPOSIT_ROLE_NEED_TO_VALIDATE);
}
public depositInValidationStep(deposit: Deposit): boolean {
depositInValidationStep(deposit: Deposit): boolean {
return this.depositInState(deposit, this.DEPOSIT_STATUS_ALLOW_VALIDATION);
}
public depositInEditionStep(deposit: Deposit): boolean {
depositInEditionStep(deposit: Deposit): boolean {
return this.depositInState(deposit, this.DEPOSIT_STATUS_ALLOW_ALTERATION);
}
......@@ -129,50 +129,42 @@ export class SecurityService {
return inState.includes(deposit.status);
}
private isCurrentRoleOnOrgUnitAuthorized(currentRoleOnOrgUnit: string[], listRolesAuthorized: Enums.Role.RoleEnum[]): boolean {
private isCurrentRoleOnOrgUnitAuthorized(currentRoleOnOrgUnit: Role, listRolesAuthorized: Enums.Role.RoleEnum[]): boolean {
return listRolesAuthorized.includes(currentRoleOnOrgUnit.resId as Enums.Role.RoleEnum);
}
private isCurrentRoleIdOnOrgUnitAuthorized(currentRoleOnOrgUnit: string[], listRolesAuthorized: Enums.Role.RoleEnum[]): boolean {
return currentRoleOnOrgUnit.some(currentRole => listRolesAuthorized.includes(currentRole as Enums.Role.RoleEnum));
}
public canEditDepositById(depositId: string): Observable<boolean> {
canEditDepositById(depositId: string): Observable<boolean> {
if (this.isRootOrAdmin()) {
return of(true);
}
return this.canSeeDetailDepositById(depositId).pipe(
flatMap((isAuthorized: boolean) => {
map((isAuthorized: boolean) => {
if (isFalse(isAuthorized)) {
return of(false);
return false;
}
const currentDeposit = MemoizedUtil.currentSnapshot(this._store, DepositState);
if (!this.depositInEditionStep(currentDeposit)) {
return of(false);
return false;
}
return this.currentUserHaveRoleInListForOrgUnit(currentDeposit.organizationalUnitId, this.DEPOSIT_ROLE_NEED_TO_EDIT);
}),
);
}
private currentUserHaveRoleInListForOrgUnit(orgUnitId: string, listRolesAuthorized: Enums.Role.RoleEnum[]): Observable<boolean> {
const currentPersonId = this._store.selectSnapshot(AppState.currentPerson).resId;
const currentPersonRoleInOrgUnit = this._store.selectSnapshot(AppState.currentOrgUnitPerson);
if (!isNullOrUndefined(currentPersonRoleInOrgUnit) && currentPersonRoleInOrgUnit.orgUnitId === orgUnitId && currentPersonRoleInOrgUnit.resId === currentPersonId) {
let roles = [];
if (!isNullOrUndefined(currentPersonRoleInOrgUnit.roles)) {
roles = currentPersonRoleInOrgUnit.roles.map(r => r.resId);
}
return of(this.isCurrentRoleOnOrgUnitAuthorized(roles, listRolesAuthorized));
private currentUserHaveRoleInListForOrgUnit(orgUnitId: string, listRolesAuthorized: Enums.Role.RoleEnum[]): boolean {
const currentRoleInOrgUnit = this.getRoleInOrgUnit(orgUnitId);
if (isNullOrUndefined(currentRoleInOrgUnit)) {
return false;
}
return this._store.dispatch(new AppOrgUnitPersonRoleAction.GetById(orgUnitId, currentPersonId)).pipe(
map(state => {
const currentRoleOnOrgUnit = this._store.selectSnapshot(AppState.currentOrgUnitPersonRoleResId);
return this.isCurrentRoleOnOrgUnitAuthorized(currentRoleOnOrgUnit, listRolesAuthorized);
}),
);
return this.isCurrentRoleOnOrgUnitAuthorized(currentRoleInOrgUnit, listRolesAuthorized);
}
public isRootOrAdmin(): boolean {
isRootOrAdmin(): boolean {
const applicationRoles = this._store.selectSnapshot(AppState.currentUserApplicationRoleResId);
if (isNullOrUndefined(applicationRoles)) {
return false;
......@@ -180,9 +172,13 @@ export class SecurityService {
return applicationRoles.includes(Enums.UserApplicationRole.UserApplicationRoleEnum.admin) || applicationRoles.includes(Enums.UserApplicationRole.UserApplicationRoleEnum.root);
}
public isMemberOfOrgUnit(orgUnitId: string): boolean {
const listAuthorizedOrgUnitId = this._store.selectSnapshot(AppState.listAuthorizedOrganizationalUnitId);
return listAuthorizedOrgUnitId.includes(orgUnitId);
getRoleInOrgUnit(orgUnitId: string): Role | undefined {
const listAuthorizedOrgUnit = this._store.selectSnapshot(AppState.listAuthorizedOrganizationalUnit);
return listAuthorizedOrgUnit.find(o => isNotNullNorUndefined(o.role) && o.resId === orgUnitId)?.role;
}
isMemberOfOrgUnit(orgUnitId: string): boolean {
return isNotNullNorUndefined(this.getRoleInOrgUnit(orgUnitId));
}
isLoggedIn(): boolean {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment