diff --git a/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java b/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java index 1b196cf6b..adf0bd84e 100644 --- a/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java +++ b/ccm-core/src/main/java/org/libreccm/api/admin/security/RolesApi.java @@ -5,6 +5,8 @@ */ package org.libreccm.api.admin.security; +import org.libreccm.api.ExtractedIdentifier; +import org.libreccm.api.IdentifierExtractor; import org.libreccm.core.CcmObjectRepository; import org.libreccm.core.CoreConstants; import org.libreccm.api.admin.security.dto.RoleData; @@ -36,12 +38,14 @@ import org.libreccm.security.Party; import org.libreccm.security.PartyRepository; import org.libreccm.security.Permission; import org.libreccm.security.PermissionManager; +import org.libreccm.security.PermissionRepository; import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.Role; import org.libreccm.security.RoleManager; import org.libreccm.security.RoleRepository; import java.net.URI; +import java.util.Optional; import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; @@ -57,12 +61,18 @@ public class RolesApi { @Inject private CcmObjectRepository ccmObjectRepository; + @Inject + private IdentifierExtractor identifierExtractor; + @Inject private PartyRepository partyRepository; @Inject private PermissionManager permissionManager; + @Inject + private PermissionRepository permissionRepository; + @Inject private SecurityApiRepository repository; @@ -270,14 +280,56 @@ public class RolesApi { ) ) ); - permission = permissionManager.grantPrivilege( + if (permissionRepository.existsPermission( privilege, role, object - ); + )) { + return Response.ok( + String.format( + "A permission granting privilege %s on object %s to " + + "role %s already exists.", + privilege, + object.getDisplayName(), + role.getName() + ) + ).build(); + } else { + permission = permissionManager.grantPrivilege( + privilege, role, object + ); + return Response.created( + URI.create( + String.format( + "/api/admin/roles/%s/permissions/UUID-%s", + role.getName(), + permission.getUuid() + ) + ) + ).build(); + } } else { - permission = permissionManager.grantPrivilege(privilege, role); - } + if (permissionRepository.existsPermission(privilege, role)) { + return Response.ok( + String.format( + "A permission granting the privilege %s to " + + "role %s already exists.", + privilege, + role.getName() + ) + ).build(); + } else { + permission = permissionManager.grantPrivilege(privilege, role); - throw new UnsupportedOperationException(); + return Response.created( + URI.create( + String.format( + "/api/admin/roles/%s/permissions/UUID-%s", + role.getName(), + permission.getUuid() + ) + ) + ).build(); + } + } } @DELETE @@ -286,10 +338,56 @@ public class RolesApi { @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @Transactional(Transactional.TxType.REQUIRED) public Response removePermission( - @PathParam("roleIdentifier") final String roleIdentifier, - @PathParam("permissionIdentifier") final String permissionIdentifier + @PathParam("roleIdentifier") + final String roleIdentifier, + @PathParam("permissionIdentifier") + final String permissionIdentifierParam ) { - throw new UnsupportedOperationException(); + final Role role = repository.findRole(roleIdentifier); + + final ExtractedIdentifier permissionIdentifier = identifierExtractor + .extractIdentifier(roleIdentifier); + + final Permission permission; + switch (permissionIdentifier.getType()) { + case ID: + permission = permissionRepository + .findById( + Long.parseLong(permissionIdentifier.getIdentifier()) + ) + .orElseThrow( + () -> new WebApplicationException( + String.format( + "No permission with ID %s found.", + permissionIdentifier.getIdentifier()), + Response.Status.NOT_FOUND + ) + ); + break; + case UUID: + permission = permissionRepository + .findByUuid(permissionIdentifier.getIdentifier()) + .orElseThrow( + () -> new WebApplicationException( + String.format( + "No permission with UUID %s found.", + permissionIdentifier.getIdentifier() + ), + Response.Status.NOT_FOUND + ) + ); + break; + + default: + return Response + .status(Response.Status.BAD_REQUEST) + .entity("Permissions can only be identified by ID or UUID.") + .build(); + } + + permissionRepository.delete(permission); + + return Response.ok().build(); } } diff --git a/ccm-core/src/main/java/org/libreccm/security/PermissionManager.java b/ccm-core/src/main/java/org/libreccm/security/PermissionManager.java index 72c95f89a..cc81177b3 100644 --- a/ccm-core/src/main/java/org/libreccm/security/PermissionManager.java +++ b/ccm-core/src/main/java/org/libreccm/security/PermissionManager.java @@ -57,8 +57,10 @@ public class PermissionManager implements Serializable { @SuppressWarnings("PMD.LongVariable") private static final String QUERY_PARAM_OBJECT = "object"; + @SuppressWarnings("PMD.LongVariable") private static final String QUERY_PARAM_GRANTEE = "grantee"; + @SuppressWarnings("PMD.LongVariable") private static final String QUERY_PARAM_PRIVILEGE = "privilege"; @@ -166,11 +168,15 @@ public class PermissionManager implements Serializable { "Can't grant a permission on object NULL."); } - if (existsInheritedPermission(privilege, grantee, object)) { + if (permissionRepository.existsInheritedPermission( + privilege, grantee, object + )) { revokePrivilege(privilege, grantee, object); } - if (existsPermission(privilege, grantee, object)) { + if (permissionRepository.existsPermission( + privilege, grantee, object + )) { return null; } else { final Permission permission = new Permission(); @@ -360,7 +366,9 @@ public class PermissionManager implements Serializable { final CcmObject object, final CcmObject inheritedFrom) { - if (!existsPermission(privilege, grantee, object)) { + if (!permissionRepository.existsPermission( + privilege, grantee, object + )) { final Permission permission = new Permission(); permission.setGrantee(grantee); permission.setGrantedPrivilege(privilege); @@ -380,17 +388,19 @@ public class PermissionManager implements Serializable { } /** - * Grants a privilege to a role. If the privilege was already granted, the + * Grants a privilege to a role.If the privilege was already granted, the * method does nothing. * * @param privilege The privilege to grant. * @param grantee The role to which the privilege is granted. + * + * @return The newly granted permission. */ @AuthorizationRequired @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) @Transactional(Transactional.TxType.REQUIRED) - public void grantPrivilege(final String privilege, - final Role grantee) { + public Permission grantPrivilege(final String privilege, + final Role grantee) { if (privilege == null || privilege.isEmpty()) { throw new IllegalArgumentException( "Can't grant a permission without a privilege."); @@ -401,7 +411,7 @@ public class PermissionManager implements Serializable { "Can't grant a permission to grantee null."); } - if (!existsPermission(privilege, grantee)) { + if (!permissionRepository.existsPermission(privilege, grantee)) { final Permission permission = new Permission(); permission.setGrantee(grantee); permission.setGrantedPrivilege(privilege); @@ -409,9 +419,9 @@ public class PermissionManager implements Serializable { permission.setUuid(UUID.randomUUID().toString()); entityManager.persist(permission); - + return permission; - } else{ + } else { // ToDo throw new UnsupportedOperationException(); } @@ -453,9 +463,10 @@ public class PermissionManager implements Serializable { grantee.getName(), object.getUuid()); - if (existsPermission(privilege, grantee, object) - || existsInheritedPermission(privilege, grantee, object)) { - + if (permissionRepository.existsPermission(privilege, grantee, object) + || permissionRepository.existsInheritedPermission( + privilege, grantee, object + )) { LOGGER.debug("There is a permission for the provided parameters, " + "revoking it..."); @@ -512,7 +523,7 @@ public class PermissionManager implements Serializable { "Can't revoke a permission from grantee null."); } - if (existsPermission(privilege, grantee)) { + if (permissionRepository.existsPermission(privilege, grantee)) { final Query query = entityManager.createQuery( "DELETE FROM Permission p " + "WHERE p.grantedPrivilege = :privilege " @@ -622,60 +633,4 @@ public class PermissionManager implements Serializable { } } - /** - * Checks if a not inherited permission granting the provided - * {@code privilege} on the provided {@code object} to the provided - * {@code role} exists. - * - * @param privilege The privilege granted by the permission. - * @param grantee The role to which the privilege was granted. - * @param object The object on which the privilege is granted. - * - * @return {@code true} if there is a matching permission, {@code false} if - * not. - */ - private boolean existsPermission(final String privilege, - final Role grantee, - final CcmObject object) { - final TypedQuery query = entityManager.createNamedQuery( - "Permission.existsDirectForPrivilegeRoleObject", Long.class); - query.setParameter(QUERY_PARAM_PRIVILEGE, privilege); - query.setParameter(QUERY_PARAM_GRANTEE, grantee); - query.setParameter(QUERY_PARAM_OBJECT, object); - - return query.getSingleResult() > 0; - } - - private boolean existsInheritedPermission(final String privilege, - final Role grantee, - final CcmObject object) { - final TypedQuery query = entityManager.createNamedQuery( - "Permission.existsInheritedForPrivilegeRoleObject", Long.class); - query.setParameter(QUERY_PARAM_PRIVILEGE, privilege); - query.setParameter(QUERY_PARAM_GRANTEE, grantee); - query.setParameter(QUERY_PARAM_OBJECT, object); - - return query.getSingleResult() > 0; - } - - /** - * Checks if a permission granting the provided {@code privilege}to the - * provided {@code role} exists. - * - * @param privilege The privilege granted by the permission. - * @param grantee The role to which the privilege was granted. - * - * @return {@code true} if there is a matching permission, {@code false} if - * not. - */ - private boolean existsPermission(final String privilege, - final Role grantee) { - final TypedQuery query = entityManager.createNamedQuery( - "Permission.existsForPrivilegeAndRole", Long.class); - query.setParameter(QUERY_PARAM_PRIVILEGE, privilege); - query.setParameter(QUERY_PARAM_GRANTEE, grantee); - - return query.getSingleResult() > 0; - } - } diff --git a/ccm-core/src/main/java/org/libreccm/security/PermissionRepository.java b/ccm-core/src/main/java/org/libreccm/security/PermissionRepository.java index 0720a84f4..c0d106947 100644 --- a/ccm-core/src/main/java/org/libreccm/security/PermissionRepository.java +++ b/ccm-core/src/main/java/org/libreccm/security/PermissionRepository.java @@ -19,6 +19,7 @@ package org.libreccm.security; import org.libreccm.core.AbstractEntityRepository; +import org.libreccm.core.CcmObject; import javax.enterprise.context.RequestScoped; import javax.persistence.NoResultException; @@ -39,6 +40,15 @@ public class PermissionRepository private static final long serialVersionUID = -4240674229117593486L; + @SuppressWarnings("PMD.LongVariable") + private static final String QUERY_PARAM_OBJECT = "object"; + + @SuppressWarnings("PMD.LongVariable") + private static final String QUERY_PARAM_GRANTEE = "grantee"; + + @SuppressWarnings("PMD.LongVariable") + private static final String QUERY_PARAM_PRIVILEGE = "privilege"; + @Override public Class getEntityClass() { return Permission.class; @@ -63,19 +73,19 @@ public class PermissionRepository } @Override - public void initNewEntity(final Permission permission) { - + public void initNewEntity(final Permission permission) { + permission.setUuid(UUID.randomUUID().toString()); } - + public Optional findByUuid(final String uuid) { final TypedQuery query = getEntityManager() - .createNamedQuery("Permission.findByUuid", Permission.class); + .createNamedQuery("Permission.findByUuid", Permission.class); query.setParameter("uuid", uuid); - + return getSingleResult(query); } - + /** * Finds a {@link Permission} by the privilege, the grantee and the object. * Where the grantee has been granted the given privilege on the given @@ -106,4 +116,62 @@ public class PermissionRepository } } + /** + * Checks if a not inherited permission granting the provided + * {@code privilege} on the provided {@code object} to the provided + * {@code role} exists. + * + * @param privilege The privilege granted by the permission. + * @param grantee The role to which the privilege was granted. + * @param object The object on which the privilege is granted. + * + * @return {@code true} if there is a matching permission, {@code false} if + * not. + */ + public boolean existsPermission(final String privilege, + final Role grantee, + final CcmObject object) { + final TypedQuery query = getEntityManager() + .createNamedQuery( + "Permission.existsDirectForPrivilegeRoleObject", Long.class + ); + query.setParameter(QUERY_PARAM_PRIVILEGE, privilege); + query.setParameter(QUERY_PARAM_GRANTEE, grantee); + query.setParameter(QUERY_PARAM_OBJECT, object); + + return query.getSingleResult() > 0; + } + + public boolean existsInheritedPermission(final String privilege, + final Role grantee, + final CcmObject object) { + final TypedQuery query = getEntityManager().createNamedQuery( + "Permission.existsInheritedForPrivilegeRoleObject", Long.class); + query.setParameter(QUERY_PARAM_PRIVILEGE, privilege); + query.setParameter(QUERY_PARAM_GRANTEE, grantee); + query.setParameter(QUERY_PARAM_OBJECT, object); + + return query.getSingleResult() > 0; + } + + /** + * Checks if a permission granting the provided {@code privilege}to the + * provided {@code role} exists. + * + * @param privilege The privilege granted by the permission. + * @param grantee The role to which the privilege was granted. + * + * @return {@code true} if there is a matching permission, {@code false} if + * not. + */ + public boolean existsPermission(final String privilege, + final Role grantee) { + final TypedQuery query = getEntityManager().createNamedQuery( + "Permission.existsForPrivilegeAndRole", Long.class); + query.setParameter(QUERY_PARAM_PRIVILEGE, privilege); + query.setParameter(QUERY_PARAM_GRANTEE, grantee); + + return query.getSingleResult() > 0; + } + }