From ad374677ee471e64563ee0d1134a70a73c356165 Mon Sep 17 00:00:00 2001 From: anhefti Date: Fri, 15 Feb 2019 12:30:26 +0100 Subject: [PATCH] doku --- .../gbl/authorization/Privilege.java | 21 ++- .../authorization/AuthorizationService.java | 139 ++++++++++++++++-- .../AuthorizationServiceImpl.java | 24 +-- .../weblayer/api/EntityController.java | 4 +- .../AuthorizationServiceTest.java | 30 ++-- 5 files changed, 163 insertions(+), 55 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/authorization/Privilege.java b/src/main/java/ch/ethz/seb/sebserver/gbl/authorization/Privilege.java index a39a5a63..d4fa2561 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/authorization/Privilege.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/authorization/Privilege.java @@ -15,7 +15,10 @@ import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; /** Defines a Privilege by combining a PrivilegeType for base (overall) rights, - * institutional rights and ownershipRights. */ + * institutional rights and ownership rights. + * + * A base-, institutional- and ownership- grant is checked in this exact order and the + * first match fund makes a grant or a denied if none of the three privilege levels has a match */ public final class Privilege { /** The RoleTypeKey defining the UserRole and EntityType for this Privilege */ @@ -75,6 +78,22 @@ public final class Privilege { return this.ownershipPrivilege.hasImplicit(privilegeType); } + /** Checks if this Privilege has a grant for a given context. + * + * The privilege grant check function always checks first the base privilege with no institutional or owner grant. + * If user has a grant on base privileges this returns true without checking further institutional or owner grant + * If user has no base privilege grant the function checks further grants, first the institutional grant, where + * the institution id and the users institution id must match and further more the owner grant, where ownerId + * and the users id must match. + * + * @param userId The user identifier of the user to check the grant on + * @param userInstitutionId the users institution identifier. The institution where the user belong to + * @param privilegeType the type of privilege to check (READ_ONLY, MODIFY, WRITE...) + * @param institutionId the institution identifier of an Entity for the institutional grant check, + * may be null in case the institutional grant check should be skipped + * @param ownerId the owner identifier of an Entity for ownership grant check, may be null in case + * the ownership grant check should be skipped + * @return true if there is any grant within the given context or false on deny */ public final boolean hasGrant( final String userId, final Long userInstitutionId, diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java index 2f0abb4a..2f1fdb79 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationService.java @@ -35,62 +35,144 @@ public interface AuthorizationService { * @return all registered Privileges */ Collection getAllPrivileges(); - boolean hasPrivilege( + /** Check grant on privilege type for specified EntityType and for the given user and institution. + * + * This makes a privilege grant check for every UserRole given. The first found successful grant + * will immediately return true + * + * The privilege grant check function always checks first the base privilege with no institutional or owner grant. + * If user has a grant on base privileges this returns true without checking further institutional or owner grant + * If user has no base privilege grant the function checks further grants, first the institutional grant, where + * the institution id and the users institution id must match and further more the owner grant, where ownerId + * and the users id must match. + * + * see Privilege.hasGrant for more information how the overall grant function works + * + * @param privilegeType The privilege type to check + * @param entityType The type of entity to check privilege on + * @param institutionId the institution id (may be null in case the institutional grant check should be skipped) + * @param ownerId the owner identifier (may be null in case the owner grant check should be skipped) + * @param userId the user identifier (UUID) + * @param userInstitutionId the user institution identifier + * @param userRoles the user roles + * @return true if there is any grant within the given context or false on deny */ + boolean hasGrant( PrivilegeType privilegeType, EntityType entityType, Long institutionId, + String ownerId, String userId, Long userInstitutionId, Set userRoles); - boolean hasPrivilege(PrivilegeType privilegeType, GrantEntity grantEntity); - - default boolean hasPrivilege(final PrivilegeType privilegeType, final EntityType entityType) { + /** Check grant for a given privilege type and entity type for the current user. + * + * NOTE: This only checks the base privilege grant because there is no Entity specific information + * + * @param privilegeType the privilege type to check + * @param entityType the type of the entity to check the given privilege type on + * @return true if there is any grant within the given context or false on deny */ + default boolean hasGrant(final PrivilegeType privilegeType, final EntityType entityType) { final SEBServerUser currentUser = getUserService().getCurrentUser(); final UserInfo userInfo = currentUser.getUserInfo(); - return hasPrivilege( + return hasGrant( privilegeType, entityType, - null, + null, null, userInfo.uuid, userInfo.institutionId, currentUser.getUserRoles()); } - default boolean hasPrivilege( + /** Check grant for a given privilege type and Entity for the current user. + * + * @param privilegeType the privilege type to check + * @param grantEntity the Entity to check the privilege grant on + * @return true if there is any grant within the given context or false on deny */ + default boolean hasGrant(final PrivilegeType privilegeType, final GrantEntity grantEntity) { + final SEBServerUser currentUser = getUserService().getCurrentUser(); + final UserInfo userInfo = currentUser.getUserInfo(); + return hasGrant( + privilegeType, + grantEntity.entityType(), + grantEntity.getInstitutionId(), + grantEntity.getOwnerId(), + userInfo.uuid, + userInfo.institutionId, + currentUser.getUserRoles()); + } + + /** Check base privilege grant and institutional privilege grant for a given privilege type + * on a given entity type. + * + * If the question is similar like this: + * "Has the current user that belongs to institution A the right to create an entity of + * type X on institution B", then this is the answer, use: + * + * hasPrivilege(PrivilegeType.WRITE, EntityType.X, B) + * + * @param privilegeType the privilege type to check + * @param entityType the type of the entity to check the given privilege type on + * @param institutionId the institution identifier for institutional privilege grant check + * @return true if there is any grant within the given context or false on deny */ + default boolean hasGrant( final PrivilegeType privilegeType, final EntityType entityType, final Long institutionId) { final SEBServerUser currentUser = getUserService().getCurrentUser(); final UserInfo userInfo = currentUser.getUserInfo(); - return hasPrivilege( + return hasGrant( privilegeType, entityType, institutionId, + null, userInfo.uuid, userInfo.institutionId, currentUser.getUserRoles()); } - default boolean hasReadonlyPrivilege(final GrantEntity grantEntity) { - return hasPrivilege(PrivilegeType.READ_ONLY, grantEntity); + /** Check read-only grant for a given Entity instance and current user. + * + * @param grantEntity Entity instance + * @return true if the current user has read-only grant on given Entity instance or false on deny */ + default boolean hasReadonlyGrant(final GrantEntity grantEntity) { + return hasGrant(PrivilegeType.READ_ONLY, grantEntity); } - default boolean hasModifyPrivilege(final GrantEntity grantEntity) { - return hasPrivilege(PrivilegeType.MODIFY, grantEntity); + /** Check modify grant for a given Entity instance and current user. + * + * @param grantEntity Entity instance + * @return true if the current user has modify grant on given Entity instance or false on deny */ + default boolean hasModifyGrant(final GrantEntity grantEntity) { + return hasGrant(PrivilegeType.MODIFY, grantEntity); } - default boolean hasWritePrivilege(final GrantEntity grantEntity) { - return hasPrivilege(PrivilegeType.WRITE, grantEntity); + /** Check write grant for a given Entity instance and current user. + * + * @param grantEntity Entity instance + * @return true if the current user has write grant on given Entity instance or false on deny */ + default boolean hasWriteGrant(final GrantEntity grantEntity) { + return hasGrant(PrivilegeType.WRITE, grantEntity); } + /** Check grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException + * on deny. + * + * @param privilegeType the privilege type to check + * @param entityType the type of the entity to check the given privilege type on */ default void check(final PrivilegeType privilegeType, final EntityType entityType) { check(privilegeType, entityType, null); } + /** Check grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException + * on deny. + * + * @param privilegeType the privilege type to check + * @param entityType the type of the entity to check the given privilege type on + * @param institutionId the institution identifier for institutional privilege grant check */ default void check(final PrivilegeType privilegeType, final EntityType entityType, final Long institutionId) { - if (!hasPrivilege(privilegeType, entityType, institutionId)) { + if (!hasGrant(privilegeType, entityType, institutionId)) { throw new PermissionDeniedException( entityType, privilegeType, @@ -98,8 +180,15 @@ public interface AuthorizationService { } } + /** Check grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException + * on deny or return the given grantEntity within a Result on successful grant. + * This is useful to use with a Result based functional chain. + * + * @param privilegeType the privilege type to check + * @param entityType the type of the entity to check the given privilege type on + * @param institutionId the institution identifier for institutional privilege grant check */ default Result check(final PrivilegeType privilegeType, final E grantEntity) { - if (!hasPrivilege(privilegeType, grantEntity)) { + if (!hasGrant(privilegeType, grantEntity)) { throw new PermissionDeniedException( grantEntity, privilegeType, @@ -109,14 +198,32 @@ public interface AuthorizationService { return Result.of(grantEntity); } + /** Check read-only grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException + * on deny or returns the given grantEntity within a Result on successful grant. + * This is useful to use with a Result based functional chain. + * + * @param entityType the type of the entity to check the given privilege type on + * @param institutionId the institution identifier for institutional privilege grant check */ default Result checkReadonly(final E grantEntity) { return check(PrivilegeType.READ_ONLY, grantEntity); } + /** Check modify grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException + * on deny or returns the given grantEntity within a Result on successful grant. + * This is useful to use with a Result based functional chain. + * + * @param entityType the type of the entity to check the given privilege type on + * @param institutionId the institution identifier for institutional privilege grant check */ default Result checkModify(final E grantEntity) { return check(PrivilegeType.MODIFY, grantEntity); } + /** Check write grant by using corresponding hasGrant(XY) method and throws PermissionDeniedException + * on deny or returns the given grantEntity within a Result on successful grant. + * This is useful to use with a Result based functional chain. + * + * @param entityType the type of the entity to check the given privilege type on + * @param institutionId the institution identifier for institutional privilege grant check */ default Result checkWrite(final E grantEntity) { return check(PrivilegeType.WRITE, grantEntity); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java index ebd9e01b..2d6ee586 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceImpl.java @@ -23,7 +23,6 @@ import ch.ethz.seb.sebserver.gbl.authorization.Privilege; import ch.ethz.seb.sebserver.gbl.authorization.Privilege.RoleTypeKey; import ch.ethz.seb.sebserver.gbl.authorization.PrivilegeType; import ch.ethz.seb.sebserver.gbl.model.EntityType; -import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; @@ -115,10 +114,11 @@ public class AuthorizationServiceImpl implements AuthorizationService { } @Override - public boolean hasPrivilege( + public boolean hasGrant( final PrivilegeType privilegeType, final EntityType entityType, final Long institutionId, + final String ownerId, final String userId, final Long userInstitutionId, final Set userRoles) { @@ -132,25 +132,7 @@ public class AuthorizationServiceImpl implements AuthorizationService { userInstitutionId, privilegeType, institutionId, - null)) - .findFirst() - .isPresent(); - } - - @Override - public boolean hasPrivilege(final PrivilegeType privilegeType, final GrantEntity grantEntity) { - final UserInfo userInfo = this.userService.getCurrentUser().getUserInfo(); - return userInfo.getRoles() - .stream() - .map(roleName -> UserRole.valueOf(roleName)) - .map(role -> new RoleTypeKey(grantEntity.entityType(), role)) - .map(key -> this.privileges.get(key)) - .filter(priv -> (priv != null) && priv.hasGrant( - userInfo.uuid, - userInfo.institutionId, - privilegeType, - grantEntity.getInstitutionId(), - grantEntity.getOwnerId())) + ownerId)) .findFirst() .isPresent(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java index 0cc89823..d3add2bc 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/EntityController.java @@ -178,7 +178,7 @@ public abstract class EntityController> getAll(final FilterMap filterMap) { return this.entityDAO.allMatching( filterMap, - this.authorization::hasReadonlyPrivilege); + this.authorization::hasReadonlyGrant); } protected Result notifySaved(final M modifyData, final T entity) { diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java index a63f88f3..de2cf105 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/authorization/AuthorizationServiceTest.java @@ -32,36 +32,36 @@ public class AuthorizationServiceTest { public void testInstitutionGrantForSEB_SERVER_ADMIN() { final AuthorizationServiceImpl service = getTestServiceWithUserWithRoles(UserRole.SEB_SERVER_ADMIN); - assertTrue(service.hasPrivilege(PrivilegeType.READ_ONLY, EntityType.INSTITUTION)); - assertTrue(service.hasPrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION)); - assertTrue(service.hasPrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION)); + assertTrue(service.hasGrant(PrivilegeType.READ_ONLY, EntityType.INSTITUTION)); + assertTrue(service.hasGrant(PrivilegeType.MODIFY, EntityType.INSTITUTION)); + assertTrue(service.hasGrant(PrivilegeType.WRITE, EntityType.INSTITUTION)); final GrantEntity institution = entityOf(EntityType.INSTITUTION, 2L, ""); - assertTrue(service.hasReadonlyPrivilege(institution)); - assertTrue(service.hasModifyPrivilege(institution)); - assertTrue(service.hasWritePrivilege(institution)); + assertTrue(service.hasReadonlyGrant(institution)); + assertTrue(service.hasModifyGrant(institution)); + assertTrue(service.hasWriteGrant(institution)); } @Test public void testInstitutionGrantsForINSTITUTIONAL_ADMIN() { final AuthorizationServiceImpl service = getTestServiceWithUserWithRoles(UserRole.INSTITUTIONAL_ADMIN); - assertFalse(service.hasPrivilege(PrivilegeType.READ_ONLY, EntityType.INSTITUTION)); - assertFalse(service.hasPrivilege(PrivilegeType.MODIFY, EntityType.INSTITUTION)); - assertFalse(service.hasPrivilege(PrivilegeType.WRITE, EntityType.INSTITUTION)); + assertFalse(service.hasGrant(PrivilegeType.READ_ONLY, EntityType.INSTITUTION)); + assertFalse(service.hasGrant(PrivilegeType.MODIFY, EntityType.INSTITUTION)); + assertFalse(service.hasGrant(PrivilegeType.WRITE, EntityType.INSTITUTION)); final GrantEntity ownInstitution = entityOf(EntityType.INSTITUTION, 1L, ""); - assertTrue(service.hasReadonlyPrivilege(ownInstitution)); - assertTrue(service.hasModifyPrivilege(ownInstitution)); - assertFalse(service.hasWritePrivilege(ownInstitution)); + assertTrue(service.hasReadonlyGrant(ownInstitution)); + assertTrue(service.hasModifyGrant(ownInstitution)); + assertFalse(service.hasWriteGrant(ownInstitution)); final GrantEntity otherInstitution = entityOf(EntityType.INSTITUTION, 2L, ""); - assertFalse(service.hasReadonlyPrivilege(otherInstitution)); - assertFalse(service.hasModifyPrivilege(otherInstitution)); - assertFalse(service.hasWritePrivilege(otherInstitution)); + assertFalse(service.hasReadonlyGrant(otherInstitution)); + assertFalse(service.hasModifyGrant(otherInstitution)); + assertFalse(service.hasWriteGrant(otherInstitution)); } private SEBServerUser getUser(final UserRole... roles) {