API for roles

Jens Pelzetter 2020-06-03 17:56:10 +02:00
parent 632805d9ac
commit 7d787f98bd
3 changed files with 204 additions and 83 deletions

View File

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

View File

@ -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<Long> 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<Long> 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<Long> query = entityManager.createNamedQuery(
"Permission.existsForPrivilegeAndRole", Long.class);
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
return query.getSingleResult() > 0;
}
}

View File

@ -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<Permission> 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<Permission> findByUuid(final String uuid) {
final TypedQuery<Permission> 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<Long> 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<Long> 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<Long> query = getEntityManager().createNamedQuery(
"Permission.existsForPrivilegeAndRole", Long.class);
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);
query.setParameter(QUERY_PARAM_GRANTEE, grantee);
return query.getSingleResult() > 0;
}
}