API for roles
parent
632805d9ac
commit
7d787f98bd
|
|
@ -5,6 +5,8 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.api.admin.security;
|
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.CcmObjectRepository;
|
||||||
import org.libreccm.core.CoreConstants;
|
import org.libreccm.core.CoreConstants;
|
||||||
import org.libreccm.api.admin.security.dto.RoleData;
|
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.PartyRepository;
|
||||||
import org.libreccm.security.Permission;
|
import org.libreccm.security.Permission;
|
||||||
import org.libreccm.security.PermissionManager;
|
import org.libreccm.security.PermissionManager;
|
||||||
|
import org.libreccm.security.PermissionRepository;
|
||||||
import org.libreccm.security.RequiresPrivilege;
|
import org.libreccm.security.RequiresPrivilege;
|
||||||
import org.libreccm.security.Role;
|
import org.libreccm.security.Role;
|
||||||
import org.libreccm.security.RoleManager;
|
import org.libreccm.security.RoleManager;
|
||||||
import org.libreccm.security.RoleRepository;
|
import org.libreccm.security.RoleRepository;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
|
@ -57,12 +61,18 @@ public class RolesApi {
|
||||||
@Inject
|
@Inject
|
||||||
private CcmObjectRepository ccmObjectRepository;
|
private CcmObjectRepository ccmObjectRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private IdentifierExtractor identifierExtractor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PartyRepository partyRepository;
|
private PartyRepository partyRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private PermissionManager permissionManager;
|
private PermissionManager permissionManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PermissionRepository permissionRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SecurityApiRepository repository;
|
private SecurityApiRepository repository;
|
||||||
|
|
||||||
|
|
@ -270,14 +280,56 @@ public class RolesApi {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
permission = permissionManager.grantPrivilege(
|
if (permissionRepository.existsPermission(
|
||||||
privilege, role, object
|
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 {
|
} 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
|
@DELETE
|
||||||
|
|
@ -286,10 +338,56 @@ public class RolesApi {
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public Response removePermission(
|
public Response removePermission(
|
||||||
@PathParam("roleIdentifier") final String roleIdentifier,
|
@PathParam("roleIdentifier")
|
||||||
@PathParam("permissionIdentifier") final String permissionIdentifier
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,10 @@ public class PermissionManager implements Serializable {
|
||||||
|
|
||||||
@SuppressWarnings("PMD.LongVariable")
|
@SuppressWarnings("PMD.LongVariable")
|
||||||
private static final String QUERY_PARAM_OBJECT = "object";
|
private static final String QUERY_PARAM_OBJECT = "object";
|
||||||
|
|
||||||
@SuppressWarnings("PMD.LongVariable")
|
@SuppressWarnings("PMD.LongVariable")
|
||||||
private static final String QUERY_PARAM_GRANTEE = "grantee";
|
private static final String QUERY_PARAM_GRANTEE = "grantee";
|
||||||
|
|
||||||
@SuppressWarnings("PMD.LongVariable")
|
@SuppressWarnings("PMD.LongVariable")
|
||||||
private static final String QUERY_PARAM_PRIVILEGE = "privilege";
|
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.");
|
"Can't grant a permission on object NULL.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existsInheritedPermission(privilege, grantee, object)) {
|
if (permissionRepository.existsInheritedPermission(
|
||||||
|
privilege, grantee, object
|
||||||
|
)) {
|
||||||
revokePrivilege(privilege, grantee, object);
|
revokePrivilege(privilege, grantee, object);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existsPermission(privilege, grantee, object)) {
|
if (permissionRepository.existsPermission(
|
||||||
|
privilege, grantee, object
|
||||||
|
)) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
final Permission permission = new Permission();
|
final Permission permission = new Permission();
|
||||||
|
|
@ -360,7 +366,9 @@ public class PermissionManager implements Serializable {
|
||||||
final CcmObject object,
|
final CcmObject object,
|
||||||
final CcmObject inheritedFrom) {
|
final CcmObject inheritedFrom) {
|
||||||
|
|
||||||
if (!existsPermission(privilege, grantee, object)) {
|
if (!permissionRepository.existsPermission(
|
||||||
|
privilege, grantee, object
|
||||||
|
)) {
|
||||||
final Permission permission = new Permission();
|
final Permission permission = new Permission();
|
||||||
permission.setGrantee(grantee);
|
permission.setGrantee(grantee);
|
||||||
permission.setGrantedPrivilege(privilege);
|
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.
|
* method does nothing.
|
||||||
*
|
*
|
||||||
* @param privilege The privilege to grant.
|
* @param privilege The privilege to grant.
|
||||||
* @param grantee The role to which the privilege is granted.
|
* @param grantee The role to which the privilege is granted.
|
||||||
|
*
|
||||||
|
* @return The newly granted permission.
|
||||||
*/
|
*/
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public void grantPrivilege(final String privilege,
|
public Permission grantPrivilege(final String privilege,
|
||||||
final Role grantee) {
|
final Role grantee) {
|
||||||
if (privilege == null || privilege.isEmpty()) {
|
if (privilege == null || privilege.isEmpty()) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't grant a permission without a privilege.");
|
"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.");
|
"Can't grant a permission to grantee null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!existsPermission(privilege, grantee)) {
|
if (!permissionRepository.existsPermission(privilege, grantee)) {
|
||||||
final Permission permission = new Permission();
|
final Permission permission = new Permission();
|
||||||
permission.setGrantee(grantee);
|
permission.setGrantee(grantee);
|
||||||
permission.setGrantedPrivilege(privilege);
|
permission.setGrantedPrivilege(privilege);
|
||||||
|
|
@ -411,7 +421,7 @@ public class PermissionManager implements Serializable {
|
||||||
entityManager.persist(permission);
|
entityManager.persist(permission);
|
||||||
|
|
||||||
return permission;
|
return permission;
|
||||||
} else{
|
} else {
|
||||||
// ToDo
|
// ToDo
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
@ -453,9 +463,10 @@ public class PermissionManager implements Serializable {
|
||||||
grantee.getName(),
|
grantee.getName(),
|
||||||
object.getUuid());
|
object.getUuid());
|
||||||
|
|
||||||
if (existsPermission(privilege, grantee, object)
|
if (permissionRepository.existsPermission(privilege, grantee, object)
|
||||||
|| existsInheritedPermission(privilege, grantee, object)) {
|
|| permissionRepository.existsInheritedPermission(
|
||||||
|
privilege, grantee, object
|
||||||
|
)) {
|
||||||
LOGGER.debug("There is a permission for the provided parameters, "
|
LOGGER.debug("There is a permission for the provided parameters, "
|
||||||
+ "revoking it...");
|
+ "revoking it...");
|
||||||
|
|
||||||
|
|
@ -512,7 +523,7 @@ public class PermissionManager implements Serializable {
|
||||||
"Can't revoke a permission from grantee null.");
|
"Can't revoke a permission from grantee null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existsPermission(privilege, grantee)) {
|
if (permissionRepository.existsPermission(privilege, grantee)) {
|
||||||
final Query query = entityManager.createQuery(
|
final Query query = entityManager.createQuery(
|
||||||
"DELETE FROM Permission p "
|
"DELETE FROM Permission p "
|
||||||
+ "WHERE p.grantedPrivilege = :privilege "
|
+ "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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
package org.libreccm.security;
|
package org.libreccm.security;
|
||||||
|
|
||||||
import org.libreccm.core.AbstractEntityRepository;
|
import org.libreccm.core.AbstractEntityRepository;
|
||||||
|
import org.libreccm.core.CcmObject;
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.persistence.NoResultException;
|
import javax.persistence.NoResultException;
|
||||||
|
|
@ -39,6 +40,15 @@ public class PermissionRepository
|
||||||
|
|
||||||
private static final long serialVersionUID = -4240674229117593486L;
|
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
|
@Override
|
||||||
public Class<Permission> getEntityClass() {
|
public Class<Permission> getEntityClass() {
|
||||||
return Permission.class;
|
return Permission.class;
|
||||||
|
|
@ -63,14 +73,14 @@ public class PermissionRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initNewEntity(final Permission permission) {
|
public void initNewEntity(final Permission permission) {
|
||||||
|
|
||||||
permission.setUuid(UUID.randomUUID().toString());
|
permission.setUuid(UUID.randomUUID().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Permission> findByUuid(final String uuid) {
|
public Optional<Permission> findByUuid(final String uuid) {
|
||||||
final TypedQuery<Permission> query = getEntityManager()
|
final TypedQuery<Permission> query = getEntityManager()
|
||||||
.createNamedQuery("Permission.findByUuid", Permission.class);
|
.createNamedQuery("Permission.findByUuid", Permission.class);
|
||||||
query.setParameter("uuid", uuid);
|
query.setParameter("uuid", uuid);
|
||||||
|
|
||||||
return getSingleResult(query);
|
return getSingleResult(query);
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue