This commit is contained in:
anhefti 2019-02-15 12:30:26 +01:00
parent 285290d93d
commit ad374677ee
5 changed files with 163 additions and 55 deletions

View file

@ -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,

View file

@ -35,62 +35,144 @@ public interface AuthorizationService {
* @return all registered Privileges */
Collection<Privilege> 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<UserRole> 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 <E extends GrantEntity> Result<E> 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 <E extends GrantEntity> Result<E> 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 <E extends GrantEntity> Result<E> 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 <E extends GrantEntity> Result<E> checkWrite(final E grantEntity) {
return check(PrivilegeType.WRITE, grantEntity);
}

View file

@ -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<UserRole> 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();
}

View file

@ -178,7 +178,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
.flatMap(this.entityDAO::loadEntities)
.getOrThrow()
.stream()
.filter(this.authorization::hasReadonlyPrivilege)
.filter(this.authorization::hasReadonlyGrant)
.collect(Collectors.toList());
}
@ -296,7 +296,7 @@ public abstract class EntityController<T extends GrantEntity, M extends GrantEnt
protected Result<Collection<T>> getAll(final FilterMap filterMap) {
return this.entityDAO.allMatching(
filterMap,
this.authorization::hasReadonlyPrivilege);
this.authorization::hasReadonlyGrant);
}
protected Result<T> notifySaved(final M modifyData, final T entity) {

View file

@ -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) {