From b3a73a50aa4282a8ce6582417a7a78cd99aa9d33 Mon Sep 17 00:00:00 2001 From: sgiannopoulos Date: Tue, 17 Oct 2023 17:13:34 +0300 Subject: [PATCH] task #9088 Authorization model should be changed to be Permission based --- dmp-backend/core/pom.xml | 1 + .../authorization/AuthorizationFlags.java | 2 -- .../DescriptionTemplateTypeBuilder.java | 20 ++++------- .../DescriptionTemplateTypeCensor.java | 4 ++- .../query/DescriptionTemplateTypeQuery.java | 22 ++++++------ .../DescriptionTemplateTypeServiceImpl.java | 16 +++++---- .../main/java/eu/eudat/EuDatApplication.java | 2 ++ .../DescriptionTemplateTypeV2Controller.java | 17 ++++----- .../src/main/resources/config/permissions.yml | 2 +- dmp-frontend/src/app/app-routing.module.ts | 8 +++-- .../src/app/core/auth-guard.service.ts | 23 +++++++----- .../description-template-type.ts | 2 +- .../description-types.routing.ts | 36 ++++++++++++++++--- 13 files changed, 96 insertions(+), 59 deletions(-) diff --git a/dmp-backend/core/pom.xml b/dmp-backend/core/pom.xml index e51f64977..09e82047c 100644 --- a/dmp-backend/core/pom.xml +++ b/dmp-backend/core/pom.xml @@ -28,6 +28,7 @@ gr.cite validation + 2.1.0 gr.cite diff --git a/dmp-backend/core/src/main/java/eu/eudat/authorization/AuthorizationFlags.java b/dmp-backend/core/src/main/java/eu/eudat/authorization/AuthorizationFlags.java index b1868d641..e87d23b26 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/authorization/AuthorizationFlags.java +++ b/dmp-backend/core/src/main/java/eu/eudat/authorization/AuthorizationFlags.java @@ -5,6 +5,4 @@ import java.util.EnumSet; public enum AuthorizationFlags { None, Permission, Owner; public static final EnumSet OwnerOrPermission = EnumSet.of(Owner, Permission); - public static final EnumSet OwnerOrPermissionOrIndicator = EnumSet.of(Owner, Permission); - public static final EnumSet OwnerOrPermissionOrIndicatorOrIndicatorAccess = EnumSet.of(Owner, Permission); } diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/builder/DescriptionTemplateTypeBuilder.java b/dmp-backend/core/src/main/java/eu/eudat/model/builder/DescriptionTemplateTypeBuilder.java index d60023632..7581b6325 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/builder/DescriptionTemplateTypeBuilder.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/builder/DescriptionTemplateTypeBuilder.java @@ -1,5 +1,6 @@ package eu.eudat.model.builder; +import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.commons.JsonHandlingService; import eu.eudat.convention.ConventionService; import eu.eudat.data.DescriptionTemplateTypeEntity; @@ -24,25 +25,18 @@ import java.util.stream.Collectors; @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class DescriptionTemplateTypeBuilder extends BaseBuilder { - private final QueryFactory queryFactory; - private final BuilderFactory builderFactory; - private final JsonHandlingService jsonHandlingService; - //private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); @Autowired public DescriptionTemplateTypeBuilder( - ConventionService conventionService, - QueryFactory queryFactory, BuilderFactory builderFactory, JsonHandlingService jsonHandlingService) { + ConventionService conventionService) { super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeBuilder.class))); - this.queryFactory = queryFactory; - this.builderFactory = builderFactory; - this.jsonHandlingService = jsonHandlingService; } -// public DescriptionTemplateTypeBuilder authorize(EnumSet values) { -// this.authorize = values; -// return this; -// } + public DescriptionTemplateTypeBuilder authorize(EnumSet values) { + this.authorize = values; + return this; + } @Override public List build(FieldSet fields, List datas) throws MyApplicationException { diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java index e4deef226..b941be7e2 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java +++ b/dmp-backend/core/src/main/java/eu/eudat/model/censorship/DescriptionTemplateTypeCensor.java @@ -11,6 +11,8 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; +import java.util.UUID; + @Component @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class DescriptionTemplateTypeCensor extends BaseCensor{ @@ -22,7 +24,7 @@ public class DescriptionTemplateTypeCensor extends BaseCensor{ this.authService = authService; } - public void censor(FieldSet fields) { + public void censor(FieldSet fields, UUID userId) { logger.debug(new DataLogEntry("censoring fields", fields)); if (fields.isEmpty()) return; diff --git a/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTemplateTypeQuery.java b/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTemplateTypeQuery.java index faeb2fcd6..c7928779d 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTemplateTypeQuery.java +++ b/dmp-backend/core/src/main/java/eu/eudat/query/DescriptionTemplateTypeQuery.java @@ -1,9 +1,11 @@ package eu.eudat.query; +import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.commons.enums.Status; -import eu.eudat.commons.scope.UserScope; +import eu.eudat.commons.scope.user.UserScope; import eu.eudat.data.DescriptionTemplateTypeEntity; import eu.eudat.model.DescriptionTemplateType; +import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.tools.data.query.FieldResolver; import gr.cite.tools.data.query.QueryBase; import gr.cite.tools.data.query.QueryContext; @@ -25,7 +27,7 @@ public class DescriptionTemplateTypeQuery extends QueryBase ids; private Collection isActives; private Collection excludedIds; - //private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); + private EnumSet authorize = EnumSet.of(AuthorizationFlags.None); public DescriptionTemplateTypeQuery like(String value) { this.like = value; @@ -77,20 +79,20 @@ public class DescriptionTemplateTypeQuery extends QueryBase values) { -// this.authorize = values; -// return this; -// } + public DescriptionTemplateTypeQuery authorize(EnumSet values) { + this.authorize = values; + return this; + } private final UserScope userScope; -// private final AuthorizationService authService; + private final AuthorizationService authService; public DescriptionTemplateTypeQuery( - UserScope userScope - //AuthorizationService authService + UserScope userScope, + AuthorizationService authService ) { this.userScope = userScope; - //this.authService = authService; + this.authService = authService; } @Override diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/DescriptionTemplateTypeServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/DescriptionTemplateTypeServiceImpl.java index dd9580143..e7c9c2970 100644 --- a/dmp-backend/core/src/main/java/eu/eudat/service/DescriptionTemplateTypeServiceImpl.java +++ b/dmp-backend/core/src/main/java/eu/eudat/service/DescriptionTemplateTypeServiceImpl.java @@ -1,5 +1,7 @@ package eu.eudat.service; +import eu.eudat.authorization.AuthorizationFlags; +import eu.eudat.authorization.Permission; import eu.eudat.commons.JsonHandlingService; import eu.eudat.commons.enums.Status; import eu.eudat.convention.ConventionService; @@ -12,6 +14,7 @@ import eu.eudat.model.builder.DescriptionTemplateTypeBuilder; import eu.eudat.model.deleter.DescriptionTemplateTypeDeleter; import eu.eudat.model.persist.DescriptionTemplateTypePersist; import eu.eudat.query.DescriptionTemplateTypeQuery; +import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.tools.data.builder.BuilderFactory; import gr.cite.tools.data.deleter.DeleterFactory; import gr.cite.tools.data.query.QueryFactory; @@ -42,7 +45,7 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DescriptionTemplateTypeServiceImpl.class)); private final EntityManager entityManager; - //private final AuthorizationService authorizationService; + private final AuthorizationService authorizationService; private final DeleterFactory deleterFactory; private final BuilderFactory builderFactory; private final ConventionService conventionService; @@ -55,7 +58,7 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy @Autowired public DescriptionTemplateTypeServiceImpl( EntityManager entityManager, - //AuthorizationService authorizationService, + AuthorizationService authorizationService, DeleterFactory deleterFactory, BuilderFactory builderFactory, ConventionService conventionService, @@ -65,7 +68,7 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy QueryFactory queryFactory, JsonHandlingService jsonHandlingService) { this.entityManager = entityManager; - //this.authorizationService = authorizationService; + this.authorizationService = authorizationService; this.deleterFactory = deleterFactory; this.builderFactory = builderFactory; this.conventionService = conventionService; @@ -79,7 +82,7 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy public DescriptionTemplateType persist(DescriptionTemplateTypePersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException { logger.debug(new MapLogEntry("persisting data descriptionTemplateType").And("model", model).And("fields", fields)); - //this.authorizationService.authorizeForce(Permission.EditDescriptionTemplateType); + this.authorizationService.authorizeForce(Permission.EditDescriptionTemplateType); Boolean isUpdate = this.conventionService.isValidGuid(model.getId()); @@ -102,14 +105,13 @@ public class DescriptionTemplateTypeServiceImpl implements DescriptionTemplateTy this.entityManager.flush(); this.eventBroker.emit(new DescriptionTemplateTypeTouchedEvent(data.getId())); - //return this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).authorize(AuthorizationFlags.OwnerOrPermissionOrDescriptionTemplateType).build(BaseFieldSet.build(fields, DescriptionTemplateType._id), data); - return this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).build(BaseFieldSet.build(fields, DescriptionTemplateType._id), data); + return this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(BaseFieldSet.build(fields, DescriptionTemplateType._id), data); } public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException { logger.debug("deleting dataset: {}", id); - //this.authorizationService.authorizeForce(Permission.DeleteDescriptionTemplateType); + this.authorizationService.authorizeForce(Permission.DeleteDescriptionTemplateType); this.deleterFactory.deleter(DescriptionTemplateTypeDeleter.class).deleteAndSaveByIds(List.of(id)); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java index 3b8efaa2c..1ca2a7223 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java +++ b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java @@ -1,5 +1,6 @@ package eu.eudat; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; @@ -28,6 +29,7 @@ public class EuDatApplication extends SpringBootServletInitializer { @Primary public ObjectMapper primaryObjectMapper() { return JsonMapper.builder().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .serializationInclusion(JsonInclude.Include.NON_NULL) .addModule(new JavaTimeModule()).build(); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeV2Controller.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeV2Controller.java index 628bd2696..e8df7549d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeV2Controller.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/DescriptionTemplateTypeV2Controller.java @@ -1,6 +1,7 @@ package eu.eudat.controllers.v2; import eu.eudat.audit.AuditableAction; +import eu.eudat.authorization.AuthorizationFlags; import eu.eudat.data.DescriptionTemplateTypeEntity; import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.model.DescriptionTemplateType; @@ -72,14 +73,12 @@ public class DescriptionTemplateTypeV2Controller { public QueryResult Query(@RequestBody DescriptionTemplateTypeLookup lookup) throws MyApplicationException, MyForbiddenException { logger.debug("querying {}", DescriptionTemplateType.class.getSimpleName()); - //this.censorFactory.censor(DescriptionTemplateTypeCensor.class).censor(lookup.getProject(), null); + this.censorFactory.censor(DescriptionTemplateTypeCensor.class).censor(lookup.getProject(), null); - DescriptionTemplateTypeQuery query = lookup.enrich(this.queryFactory); - //DescriptionTemplateTypeQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermissionOrDescriptionTemplateType); + DescriptionTemplateTypeQuery query = lookup.enrich(this.queryFactory).authorize(AuthorizationFlags.OwnerOrPermission); List data = query.collectAs(lookup.getProject()); - //List models = this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).authorize(AuthorizationFlags.OwnerOrPermissionOrDescriptionTemplateType).build(lookup.getProject(), data); - List models = this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).build(lookup.getProject(), data); + List models = this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(lookup.getProject(), data); long count = (lookup.getMetadata() != null && lookup.getMetadata().getCountAll()) ? query.count() : models.size(); this.auditService.track(AuditableAction.DescriptionTemplateType_Query, "lookup", lookup); @@ -92,12 +91,10 @@ public class DescriptionTemplateTypeV2Controller { public DescriptionTemplateType Get(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException { logger.debug(new MapLogEntry("retrieving" + DescriptionTemplateType.class.getSimpleName()).And("id", id).And("fields", fieldSet)); - //this.censorFactory.censor(DescriptionTemplateTypeCensor.class).censor(fieldSet, null); + this.censorFactory.censor(DescriptionTemplateTypeCensor.class).censor(fieldSet, null); - DescriptionTemplateTypeQuery query = this.queryFactory.query(DescriptionTemplateTypeQuery.class).ids(id); - DescriptionTemplateType model = this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).build(fieldSet, query.firstAs(fieldSet)); - //DescriptionTemplateTypeQuery query = this.queryFactory.query(DescriptionTemplateTypeQuery.class).authorize(AuthorizationFlags.OwnerOrPermissionOrDescriptionTemplateType).ids(id); - //DescriptionTemplateType model = this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).authorize(AuthorizationFlags.OwnerOrPermissionOrDescriptionTemplateType).build(fieldSet, query.firstAs(fieldSet)); + DescriptionTemplateTypeQuery query = this.queryFactory.query(DescriptionTemplateTypeQuery.class).authorize(AuthorizationFlags.OwnerOrPermission).ids(id); + DescriptionTemplateType model = this.builderFactory.builder(DescriptionTemplateTypeBuilder.class).authorize(AuthorizationFlags.OwnerOrPermission).build(fieldSet, query.firstAs(fieldSet)); if (model == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, DescriptionTemplateType.class.getSimpleName()}, LocaleContextHolder.getLocale())); this.auditService.track(AuditableAction.DescriptionTemplateType_Lookup, Map.ofEntries( diff --git a/dmp-backend/web/src/main/resources/config/permissions.yml b/dmp-backend/web/src/main/resources/config/permissions.yml index 68f99ab75..1d61b4aa4 100644 --- a/dmp-backend/web/src/main/resources/config/permissions.yml +++ b/dmp-backend/web/src/main/resources/config/permissions.yml @@ -23,7 +23,7 @@ permissions: allowAuthenticated: false # ViewPage Permissions - ViewDatasetPage: + ViewDescriptionTemplateTypePage: roles: - Admin clients: [ ] diff --git a/dmp-frontend/src/app/app-routing.module.ts b/dmp-frontend/src/app/app-routing.module.ts index c5918c5ab..d418c98f7 100644 --- a/dmp-frontend/src/app/app-routing.module.ts +++ b/dmp-frontend/src/app/app-routing.module.ts @@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router'; import { ReloadHelperComponent } from '@app/ui/misc/reload-helper/reload-helper.component'; import { Oauth2DialogComponent } from './ui/misc/oauth2-dialog/oauth2-dialog.component'; import { AppComponent } from './app.component'; +import { AppPermission } from './core/common/enum/permission.enum'; const appRoutes: Routes = [ { @@ -102,8 +103,11 @@ const appRoutes: Routes = [ loadChildren: () => import('./ui/admin/description-types/description-types.module').then(m => m.DescriptionTypesModule), data: { breadcrumb: true, - title: 'GENERAL.TITLES.DESCRIPTION-TYPES' - } + title: 'GENERAL.TITLES.DESCRIPTION-TYPES', + authContext: { + permissions: [AppPermission.ViewDescriptionTemplateTypePage] + } + }, }, { path: 'contact-support', diff --git a/dmp-frontend/src/app/core/auth-guard.service.ts b/dmp-frontend/src/app/core/auth-guard.service.ts index cc1d878a4..e6df4cc28 100644 --- a/dmp-frontend/src/app/core/auth-guard.service.ts +++ b/dmp-frontend/src/app/core/auth-guard.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router'; -import { AuthService } from './services/auth/auth.service'; +import { AuthService, ResolutionContext } from './services/auth/auth.service'; import { from, Observable, of as observableOf } from 'rxjs'; import { catchError, map, tap } from 'rxjs/operators'; @@ -11,25 +11,32 @@ export class AuthGuard implements CanActivate, CanLoad { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { const url: string = state.url; - return this.applyGuard(url); + const authContext = route.data ? route.data['authContext'] as ResolutionContext : null; + return this.applyGuard(url, authContext); } canLoad(route: Route): Observable { const url = `/${route.path}`; - return this.applyGuard(url); + const authContext = route.data ? route.data['authContext'] as ResolutionContext : null; + return this.applyGuard(url, authContext); } - private applyGuard(url: string) { - return this.checkLogin(url).pipe(tap(loggedIn => { + private applyGuard(url: string, authContext: ResolutionContext) { + return this.checkLogin(url, authContext).pipe(tap(loggedIn => { if (!loggedIn) { this.router.navigate(['/unauthorized'], { queryParams: { returnUrl: url } }); - } else{ - return true; + } else { + const authorized = this.authService.hasAccessToken() && this.authService.authorize(authContext); + if(!authorized){ + this.router.navigate(['/unauthorized']); + }else{ + return authorized; + } } })); } - private checkLogin(url: string): Observable { + private checkLogin(url: string, authContext: ResolutionContext): Observable { if (!this.authService.isLoggedIn()) { return observableOf(false); } return this.authService.hasAccessToken() diff --git a/dmp-frontend/src/app/core/model/description-template-type/description-template-type.ts b/dmp-frontend/src/app/core/model/description-template-type/description-template-type.ts index 1b2812e09..67af2f190 100644 --- a/dmp-frontend/src/app/core/model/description-template-type/description-template-type.ts +++ b/dmp-frontend/src/app/core/model/description-template-type/description-template-type.ts @@ -2,4 +2,4 @@ export interface DescriptionTemplateType { id: string; name: string; status: number; -} \ No newline at end of file +} diff --git a/dmp-frontend/src/app/ui/admin/description-types/description-types.routing.ts b/dmp-frontend/src/app/ui/admin/description-types/description-types.routing.ts index fea0e116d..70af68dcf 100644 --- a/dmp-frontend/src/app/ui/admin/description-types/description-types.routing.ts +++ b/dmp-frontend/src/app/ui/admin/description-types/description-types.routing.ts @@ -3,15 +3,43 @@ import { RouterModule, Routes } from "@angular/router"; import { AdminAuthGuard } from "@app/core/admin-auth-guard.service"; import { DescriptionTypeEditorComponent } from './editor/description-type-editor.component'; import { DescriptionTypesComponent } from "./listing/description-types.component"; +import { AuthGuard } from "@app/core/auth-guard.service"; +import { AppPermission } from "@app/core/common/enum/permission.enum"; const routes: Routes = [ - { path: '', component: DescriptionTypesComponent, canActivate: [AdminAuthGuard] }, - { path: 'new', component: DescriptionTypeEditorComponent, canActivate: [AdminAuthGuard], data: { title: 'GENERAL.TITLES.DESCRIPTION-TYPE-NEW' } }, - { path: ':id', component: DescriptionTypeEditorComponent, canActivate: [AdminAuthGuard], data: { title: 'GENERAL.TITLES.DESCRIPTION-TYPE-EDIT' } } + { + path: '', + component: DescriptionTypesComponent, + canActivate: [AuthGuard], + data: { + authContext: { + permissions: [AppPermission.ViewDescriptionTemplateTypePage] + } + }, + }, + { + path: 'new', + component: DescriptionTypeEditorComponent, + canActivate: [AuthGuard], + data: { + title: 'GENERAL.TITLES.DESCRIPTION-TYPE-NEW', + authContext: { + permissions: [AppPermission.EditDescriptionTemplateType] + } + } + }, + { + path: ':id', + component: DescriptionTypeEditorComponent, + canActivate: [AuthGuard], + data: { + title: 'GENERAL.TITLES.DESCRIPTION-TYPE-EDIT' + } + } ] @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) -export class DescriptionTypesRoutingModule { } \ No newline at end of file +export class DescriptionTypesRoutingModule { }