Improvements for RESTful API

Jens Pelzetter 2020-06-05 20:32:27 +02:00
parent 8b3f843531
commit fe6e680733
15 changed files with 489 additions and 212 deletions

View File

@ -29,7 +29,7 @@ import javax.enterprise.context.Dependent;
@Dependent
public class IdentifierParser {
public Identifier extractIdentifier(final String identifierParam) {
public Identifier parseIdentifier(final String identifierParam) {
Objects.requireNonNull(identifierParam, "identifier param is null.");
if (identifierParam.startsWith(ApiConstants.IDENTIFIER_PREFIX_ID)) {

View File

@ -18,6 +18,7 @@
*/
package org.libreccm.api.admin.categorization;
import org.libreccm.api.admin.categorization.dto.CategorizationData;
import org.libreccm.api.admin.categorization.dto.CategoryData;
import org.libreccm.api.dto.ListView;
import org.libreccm.core.CoreConstants;
@ -28,12 +29,14 @@ import javax.enterprise.context.RequestScoped;
import javax.transaction.Transactional;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
@ -190,13 +193,56 @@ public class CategoriesApi {
throw new UnsupportedOperationException();
}
@GET
@Path("/{domainIdentifier}/{path:^[\\w\\-/]+$}/subcategories")
@Produces(MediaType.APPLICATION_JSON)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public ListView<CategoryData> getSubCategories(
@PathParam("domainIdentifier") final String domainIdentifierParam,
@PathParam("path") final String categoryPathTokens,
@QueryParam("limit") @DefaultValue("20") final int limit,
@QueryParam("offset") @DefaultValue("20") final int offset
) {
throw new UnsupportedOperationException();
}
@GET
@Path("/ID-{categoryId}/subcategories")
@Produces(MediaType.APPLICATION_JSON)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public ListView<CategoryData> getSubCategories(
@PathParam("categoryId") final long categoryId,
@QueryParam("limit") @DefaultValue("20") final int limit,
@QueryParam("offset") @DefaultValue("20") final int offset
) {
throw new UnsupportedOperationException();
}
@GET
@Path("/UUID-{categoryId}/subcategories")
@Produces(MediaType.APPLICATION_JSON)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public ListView<CategoryData> getSubCategories(
@PathParam("categoryUuid") final String uuid,
@QueryParam("limit") @DefaultValue("20") final int limit,
@QueryParam("offset") @DefaultValue("20") final int offset
) {
throw new UnsupportedOperationException();
}
@GET
@Path("/{domainIdentifier}/{path:^[\\w\\-/]+$}/objects")
@Produces(MediaType.APPLICATION_JSON)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public CategoryData getObjectsInCategory(
public ListView<CategorizationData> getObjectsInCategory(
@PathParam("domainIdentifier") final String domainIdentifierParam,
@PathParam("path") final String categoryPathTokens
) {
@ -209,7 +255,7 @@ public class CategoriesApi {
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public CategoryData getCategoryObjectsInCategory(
public ListView<CategorizationData> getCategoryObjectsInCategory(
@PathParam("categoryId") final long categoryId
) {
throw new UnsupportedOperationException();
@ -221,7 +267,7 @@ public class CategoriesApi {
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public CategoryData getObjectsInCategory(
public ListView<CategorizationData> getObjectsInCategory(
@PathParam("categoryId") final String categoryUuid
) {
throw new UnsupportedOperationException();

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2020 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.api.admin.categorization;
import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser;
import org.libreccm.categorization.Domain;
import org.libreccm.categorization.DomainRepository;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
/**
* Shared repository for the classes of the categorization RESTful api.
*
* All methods in this class will throw a {@link WebApplicationException} with a
* 404 status code if the requested entity is not found.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Dependent
public class CategorizationApiRepository {
@Inject
private DomainRepository domainRepository;
@Inject
private IdentifierParser identifierParser;
public Domain findDomain(final String domainIdentifier) {
final Identifier identifier = identifierParser.parseIdentifier(
domainIdentifier
);
switch (identifier.getType()) {
case ID:
return domainRepository
.findById(Long.parseLong(identifier.getIdentifier()))
.orElseThrow(
() -> new WebApplicationException(
String.format(
"No Domain with ID %s found.",
identifier.getIdentifier()
),
Response.Status.NOT_FOUND
)
);
case UUID:
return domainRepository
.findByUuid(identifier.getIdentifier())
.orElseThrow(
() -> new WebApplicationException(
String.format(
"No Domain with UUID %s found.",
identifier.getIdentifier()
),
Response.Status.NOT_FOUND
)
);
default:
return domainRepository
.findByDomainKey(identifier.getIdentifier())
.orElseThrow(
() -> new WebApplicationException(
String.format(
"No Domain with domain key %s found.",
identifier.getIdentifier()
),
Response.Status.NOT_FOUND
)
);
}
}
}

View File

@ -21,10 +21,7 @@ package org.libreccm.api.admin.categorization.dto;
import org.libreccm.categorization.Category;
import org.libreccm.l10n.LocalizedString;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
*
@ -50,17 +47,12 @@ public class CategoryData {
private boolean abstractCategory;
private List<CategorizationData> objects;
private List<AssociatedCategoryData> subCategories;
private AssociatedCategoryData parentCategory;
private long categoryOrder;
public CategoryData() {
objects = new ArrayList<>();
subCategories = new ArrayList<>();
// Nothing
}
public CategoryData(final Category fromCategory) {
@ -77,16 +69,6 @@ public class CategoryData {
enabled = fromCategory.isEnabled();
visible = fromCategory.isVisible();
abstractCategory = fromCategory.isAbstractCategory();
objects = fromCategory
.getObjects()
.stream()
.map(CategorizationData::new)
.collect(Collectors.toList());
subCategories = fromCategory
.getSubCategories()
.stream()
.map(AssociatedCategoryData::new)
.collect(Collectors.toList());
parentCategory = new AssociatedCategoryData(
fromCategory.getParentCategory()
);
@ -164,23 +146,6 @@ public class CategoryData {
this.abstractCategory = abstractCategory;
}
public List<CategorizationData> getObjects() {
return new ArrayList<>(objects);
}
public void setObjects(final List<CategorizationData> objects) {
this.objects = new ArrayList<>(objects);
}
public List<AssociatedCategoryData> getSubCategories() {
return new ArrayList<>(subCategories);
}
public void setSubCategories(
final List<AssociatedCategoryData> subCategories) {
this.subCategories = new ArrayList<>(subCategories);
}
public AssociatedCategoryData getParentCategory() {
return parentCategory;
}

View File

@ -203,14 +203,23 @@ public class GroupsApi {
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public List<GroupUserMembership> getMembers(
@PathParam("groupIdentifier") final String groupIdentifier
public ListView<GroupUserMembership> getMembers(
@PathParam("groupIdentifier") final String groupIdentifier,
@QueryParam("limit") @DefaultValue("20") final int limit,
@QueryParam("offset") @DefaultValue("0") final int offset
) {
return repository.findGroup(groupIdentifier)
.getMemberships()
final Group group = repository.findGroup(groupIdentifier);
return new ListView<>(
groupRepository
.findGroupMemberships(group, limit, offset)
.stream()
.map(GroupUserMembership::new)
.collect(Collectors.toList());
.collect(Collectors.toList()),
groupRepository.countGroupMemberships(group),
limit,
offset
);
}
@PUT

View File

@ -48,6 +48,8 @@ import java.net.URI;
import java.util.stream.Collectors;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
/**
*
@ -57,6 +59,9 @@ import javax.ws.rs.WebApplicationException;
@Path("/roles")
public class RolesApi {
@Context
private UriInfo uriInfo;
@Inject
private CcmObjectRepository ccmObjectRepository;
@ -179,14 +184,23 @@ public class RolesApi {
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public List<RolePartyMembership> getMembers(
@PathParam("roleIdentifier") final String roleIdentifier
public ListView<RolePartyMembership> getMembers(
@PathParam("roleIdentifier") final String roleIdentifier,
@QueryParam("limit") @DefaultValue("20") final int limit,
@QueryParam("offset") @DefaultValue("0") final int offset
) {
return repository.findRole(roleIdentifier)
.getMemberships()
.stream()
.map(RolePartyMembership::new)
.collect(Collectors.toList());
final Role role = repository.findRole(roleIdentifier);
final long count = roleRepository.countMembershipsByRole(role);
return new ListView<>(
roleRepository
.findMembershipsByRole(role, limit, offset)
.stream()
.map(RolePartyMembership::new)
.collect(Collectors.toList()),
count,
limit,
offset
);
}
@PUT
@ -244,14 +258,22 @@ public class RolesApi {
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public List<RolePermission> getPermissions(
@PathParam("roleIdentifier") final String roleIdentifier
public ListView<RolePermission> getPermissions(
@PathParam("roleIdentifier") final String roleIdentifier,
@QueryParam("limit") @DefaultValue("20") final int limit,
@QueryParam("offset") @DefaultValue("0") final int offset
) {
return repository.findRole(roleIdentifier)
.getPermissions()
.stream()
.map(RolePermission::new)
.collect(Collectors.toList());
final Role role = repository.findRole(roleIdentifier);
return new ListView<>(
permissionRepository
.findPermissionsForRole(role, limit, offset)
.stream()
.map(RolePermission::new)
.collect(Collectors.toList()),
permissionRepository.countPermissionsForRole(role),
limit,
offset
);
}
@POST
@ -345,7 +367,7 @@ public class RolesApi {
final Role role = repository.findRole(roleIdentifier);
final Identifier permissionIdentifier = identifierExtractor
.extractIdentifier(roleIdentifier);
.parseIdentifier(roleIdentifier);
final Permission permission;
switch (permissionIdentifier.getType()) {
@ -375,7 +397,7 @@ public class RolesApi {
Response.Status.NOT_FOUND
)
);
break;
break;
default:
return Response

View File

@ -63,7 +63,7 @@ class SecurityApiRepository {
protected Group findGroup(final String groupIdentifier) {
final Identifier identifier = identifierExtractor
.extractIdentifier(groupIdentifier);
.parseIdentifier(groupIdentifier);
switch (identifier.getType()) {
case ID:
@ -107,7 +107,7 @@ class SecurityApiRepository {
protected Party findParty(final String partyIdentifier) {
final Identifier identifier = identifierExtractor
.extractIdentifier(partyIdentifier);
.parseIdentifier(partyIdentifier);
switch (identifier.getType()) {
case ID:
@ -152,7 +152,7 @@ class SecurityApiRepository {
protected Role findRole(final String roleIdentifier) {
final Identifier identifier = identifierExtractor
.extractIdentifier(roleIdentifier);
.parseIdentifier(roleIdentifier);
switch (identifier.getType()) {
case ID:
@ -196,7 +196,7 @@ class SecurityApiRepository {
protected User findUser(final String identifierParam) {
final Identifier identifier = identifierExtractor
.extractIdentifier(identifierParam);
.parseIdentifier(identifierParam);
switch (identifier.getType()) {
case ID:

View File

@ -41,19 +41,19 @@ public class RoleData {
private LocalizedString description;
private List<RolePartyMembership> memberships;
// private List<RolePartyMembership> memberships;
private List<RolePermission> permissions;
private List<RoleAssignedTask> assignedTasks;
// private List<RoleAssignedTask> assignedTasks;
/**
* Parameterless constructor for creating empty instances.
*/
public RoleData() {
memberships = new ArrayList<>();
// membership = new ArrayList<>();
permissions = new ArrayList<>();
assignedTasks = new ArrayList<>();
// assignedTasks = new ArrayList<>();
}
public RoleData(final Role role) {
@ -64,23 +64,23 @@ public class RoleData {
name = role.getName();
description = role.getDescription();
memberships = role
.getMemberships()
.stream()
.map(RolePartyMembership::new)
.collect(Collectors.toList());
permissions = role
.getPermissions()
.stream()
.map(RolePermission::new)
.collect(Collectors.toList());
assignedTasks = role
.getAssignedTasks()
.stream()
.map(RoleAssignedTask::new)
.collect(Collectors.toList());
// memberships = role
// .getMemberships()
// .stream()
// .map(RolePartyMembership::new)
// .collect(Collectors.toList());
//
// permissions = role
// .getPermissions()
// .stream()
// .map(RolePermission::new)
// .collect(Collectors.toList());
//
// assignedTasks = role
// .getAssignedTasks()
// .stream()
// .map(RoleAssignedTask::new)
// .collect(Collectors.toList());
}
public long getRoleId() {
@ -107,21 +107,21 @@ public class RoleData {
this.name = name;
}
public List<RolePartyMembership> getMemberships() {
return new ArrayList<>(memberships);
}
public void setMemberships(final List<RolePartyMembership> memberships) {
this.memberships = new ArrayList<>(memberships);
}
public List<RoleAssignedTask> getAssignedTasks() {
return new ArrayList<>(assignedTasks);
}
public void setAssignedTasks(final List<RoleAssignedTask> assignedTasks) {
this.assignedTasks = new ArrayList<>(assignedTasks);
}
// public List<RolePartyMembership> getMemberships() {
// return new ArrayList<>(memberships);
// }
//
// public void setMemberships(final List<RolePartyMembership> memberships) {
// this.memberships = new ArrayList<>(memberships);
// }
//
// public List<RoleAssignedTask> getAssignedTasks() {
// return new ArrayList<>(assignedTasks);
// }
//
// public void setAssignedTasks(final List<RoleAssignedTask> assignedTasks) {
// this.assignedTasks = new ArrayList<>(assignedTasks);
// }
public LocalizedString getDescription() {
return description;

View File

@ -66,31 +66,38 @@ import javax.persistence.Table;
@NamedQuery(
name = "Group.findByName",
query = "SELECT g FROM Group g WHERE g.name = :name "
+ "ORDER BY g.name")
,
+ "ORDER BY g.name"),
@NamedQuery(
name = "Group.searchByName",
query = "SELECT g FROM Group g "
+ "WHERE LOWER(g.name) LIKE CONCAT(LOWER(:name), '%') "
+ "ORDER BY g.name")
,
+ "ORDER BY g.name"),
@NamedQuery(
name = "Group.findAllOrderedByGroupName",
query = "SELECT g FROM Group g ORDER BY g.name")
,
query = "SELECT g FROM Group g ORDER BY g.name"),
@NamedQuery(
name = "Group.findByMember",
query = "SELECT g FROM Group g "
+ "JOIN g.memberships m "
+ "WHERE m.member = :member"
),
@NamedQuery(
name = "Group.findMemberships",
query = "SELECT m FROM GroupMembership m "
+ "JOIN m.member u "
+ "WHERE m.group = :group "
+ "ORDER BY u.name"
),
@NamedQuery(
name = "Group.countMemberships",
query = "SELECT COUNT(m) FROM GroupMembership m WHERE m.group = :group"
)
})
@NamedEntityGraphs({
@NamedEntityGraph(
name = "Group.withMembersAndRoleMemberships",
attributeNodes = {
@NamedAttributeNode(value = "memberships")
,
@NamedAttributeNode(value = "memberships"),
@NamedAttributeNode(value = "roleMemberships",
subgraph = "role")},
subgraphs = {
@ -99,8 +106,7 @@ import javax.persistence.Table;
attributeNodes = {
@NamedAttributeNode(value = "role",
subgraph = "permissions")
})
,
}),
@NamedSubgraph(
name = "permissions",
attributeNodes = {

View File

@ -26,6 +26,7 @@ import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
@ -66,7 +67,7 @@ public class GroupRepository extends AbstractEntityRepository<Long, Group> {
public Optional<Group> findByUuid(final String uuid) {
final TypedQuery<Group> query = getEntityManager()
.createNamedQuery("Group.findByUuid", Group.class);
.createNamedQuery("Group.findByUuid", Group.class);
query.setParameter("uuid", uuid);
final List<Group> result = query.getResultList();
if (result.isEmpty()) {
@ -107,6 +108,38 @@ public class GroupRepository extends AbstractEntityRepository<Long, Group> {
return query.getResultList();
}
public List<GroupMembership> findGroupMemberships(
final Group group,
final int limit,
final int offset
) {
return getEntityManager()
.createNamedQuery("Group.findMemberships", GroupMembership.class)
.setParameter(
"group",
Objects.requireNonNull(
group,
"Can't retrieve menberships for group null."
)
)
.setMaxResults(limit)
.setFirstResult(offset)
.getResultList();
}
public long countGroupMemberships(final Group group) {
return getEntityManager()
.createNamedQuery("Group.countMemberships", Long.class)
.setParameter(
"group",
Objects.requireNonNull(
group,
"Can't count menberships for group null."
)
)
.getSingleResult();
}
/**
* Tries to find a group which name contains a provided token.
*

View File

@ -70,44 +70,65 @@ import javax.persistence.TemporalType;
@Entity
@Table(name = "PERMISSIONS", schema = DB_SCHEMA)
@NamedQueries({
@NamedQuery(name = "Permission.findByUuid",
query = "SELECT p FROM Permission p WHERE p.uuid = :uuid"),
@NamedQuery(name = "Permission.findByCustomPermId",
query = "SELECT p FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object"),
@NamedQuery(name = "Permission.existsForPrivilegeRoleObject",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object"),
@NamedQuery(name = "Permission.existsDirectForPrivilegeRoleObject",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object "
+ "AND p.inherited = false"),
@NamedQuery(name = "Permission.existsInheritedForPrivilegeRoleObject",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object "
+ "AND p.inherited = true"),
@NamedQuery(name = "Permission.existsForPrivilegeAndRole",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object IS NULL"),
@NamedQuery(name = "Permission.findPermissionsForRole",
query = "SELECT p FROM Permission p "
+ "WHERE p.grantee = :grantee"),
@NamedQuery(name = "Permission.findPermissionsForCcmObject",
query = "SELECT p FROM Permission p "
+ "WHERE p.object = :object"),
@NamedQuery(name = "Permission.findPermissionsForRoleAndObject",
query = "SELECT p FROM Permission p "
+ "WHERE p.object = :object and p.grantee = :grantee")
@NamedQuery(
name = "Permission.findByUuid",
query = "SELECT p FROM Permission p WHERE p.uuid = :uuid"
),
@NamedQuery(
name = "Permission.findByCustomPermId",
query = "SELECT p FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object"
),
@NamedQuery(
name = "Permission.existsForPrivilegeRoleObject",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object"
),
@NamedQuery(
name = "Permission.existsDirectForPrivilegeRoleObject",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object "
+ "AND p.inherited = false"
),
@NamedQuery(
name = "Permission.existsInheritedForPrivilegeRoleObject",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object = :object "
+ "AND p.inherited = true"
),
@NamedQuery(
name = "Permission.existsForPrivilegeAndRole",
query = "SELECT COUNT(p) FROM Permission p "
+ "WHERE p.grantedPrivilege = :privilege "
+ "AND p.grantee = :grantee "
+ "AND p.object IS NULL"
),
@NamedQuery(
name = "Permission.findPermissionsForRole",
query = "SELECT p FROM Permission p WHERE p.grantee = :grantee"
),
@NamedQuery(
name = "Permission.countPermissionsForRole",
query = "SELECT COUNT(p) FROM Permission p WHERE p.grantee = :grantee"
),
@NamedQuery(
name = "Permission.findPermissionsForCcmObject",
query = "SELECT p FROM Permission p "
+ "WHERE p.object = :object"
),
@NamedQuery(
name = "Permission.findPermissionsForRoleAndObject",
query = "SELECT p FROM Permission p "
+ "WHERE p.object = :object and p.grantee = :grantee"
)
})
@XmlRootElement(name = "permission", namespace = CORE_XML_NS)

View File

@ -21,6 +21,9 @@ package org.libreccm.security;
import org.libreccm.core.AbstractEntityRepository;
import org.libreccm.core.CcmObject;
import java.util.List;
import java.util.Objects;
import javax.enterprise.context.RequestScoped;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
@ -28,6 +31,8 @@ import javax.persistence.TypedQuery;
import java.util.Optional;
import java.util.UUID;
import javax.transaction.Transactional;
/**
* A repository class for {@link Permission}.
*
@ -55,11 +60,13 @@ public class PermissionRepository
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
public String getIdAttributeName() {
return "permissionId";
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
public Long getIdOfEntity(final Permission entity) {
return entity.getPermissionId();
}
@ -73,6 +80,7 @@ public class PermissionRepository
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
public void initNewEntity(final Permission permission) {
permission.setUuid(UUID.randomUUID().toString());
@ -97,6 +105,7 @@ public class PermissionRepository
*
* @return An optional either with the found item or empty
*/
@Transactional(Transactional.TxType.REQUIRED)
public Optional<Permission> findByCustomPermId(final String privilege,
final Role grantee,
final Object object) {
@ -116,6 +125,38 @@ public class PermissionRepository
}
}
@Transactional(Transactional.TxType.REQUIRED)
public List<Permission> findPermissionsForRole(
final Role role, final int limit, final int offset
) {
return getEntityManager()
.createNamedQuery(
"Permission.findPermissionsForRole", Permission.class)
.setParameter(
"grantee",
Objects.requireNonNull(
role,
"Can't retrieve permissions for role null"
)
)
.setMaxResults(limit)
.setFirstResult(offset)
.getResultList();
}
@Transactional(Transactional.TxType.REQUIRED)
public long countPermissionsForRole(final Role role) {
return getEntityManager()
.createNamedQuery("Permission.countPermissionsForRole", Long.class)
.setParameter(
"grantee",
Objects.requireNonNull(
role,
"Can't count permissions for role null."
)
)
.getSingleResult();
}
/**
* Checks if a not inherited permission granting the provided
* {@code privilege} on the provided {@code object} to the provided
@ -128,6 +169,8 @@ public class PermissionRepository
* @return {@code true} if there is a matching permission, {@code false} if
* not.
*/
@Transactional(Transactional.TxType.REQUIRED)
public boolean existsPermission(final String privilege,
final Role grantee,
final CcmObject object) {
@ -142,9 +185,10 @@ public class PermissionRepository
return query.getSingleResult() > 0;
}
public boolean existsInheritedPermission(final String privilege,
final Role grantee,
final CcmObject object) {
@Transactional(Transactional.TxType.REQUIRED)
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);
@ -164,8 +208,9 @@ public class PermissionRepository
* @return {@code true} if there is a matching permission, {@code false} if
* not.
*/
@Transactional(Transactional.TxType.REQUIRED)
public boolean existsPermission(final String privilege,
final Role grantee) {
final Role grantee) {
final TypedQuery<Long> query = getEntityManager().createNamedQuery(
"Permission.existsForPrivilegeAndRole", Long.class);
query.setParameter(QUERY_PARAM_PRIVILEGE, privilege);

View File

@ -57,11 +57,31 @@ import javax.persistence.Table;
@Entity
@Table(name = "ROLE_MEMBERSHIPS", schema = DB_SCHEMA)
@NamedQueries({
@NamedQuery(name = "RoleMembership.findByUuid",
query = "SELECT m FROM RoleMembership m WHERE m.uuid = :uuid"),
@NamedQuery(name = "RoleMembership.findByRoleAndMember",
query = "SELECT m FROM RoleMembership m "
+ "WHERE m.member = :member AND m.role = :role")
@NamedQuery(
name = "RoleMembership.findByUuid",
query = "SELECT m FROM RoleMembership m WHERE m.uuid = :uuid"
),
@NamedQuery(
name = "RoleMembership.findByRoleAndMember",
query = "SELECT m FROM RoleMembership m "
+ "WHERE m.member = :member AND m.role = :role"
),
@NamedQuery(
name = "RoleMembership.countByParty",
query = "SELECT COUNT(m) FROM RoleMembership m WHERE m.member = :party"
),
@NamedQuery(
name = "RoleMembership.countByRole",
query = "SELECT COUNT(m) FROM RoleMembership m WHERE m.role = :role"
),
@NamedQuery(
name = "RoleMembership.findByParty",
query = "SELECT m FROM RoleMembership m WHERE m.member = :party"
),
@NamedQuery(
name = "RoleMembership.findByRole",
query = "SELECT m FROM RoleMembership m WHERE m.role = :role"
)
})
@XmlRootElement(name = "role-membership", namespace = CORE_XML_NS)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,

View File

@ -80,7 +80,7 @@ public class RoleRepository extends AbstractEntityRepository<Long, Role> {
public Optional<Role> findByUuid(final String uuid) {
final TypedQuery<Role> query = getEntityManager()
.createNamedQuery("Role.findByUuid", Role.class);
.createNamedQuery("Role.findByUuid", Role.class);
query.setParameter("uuid", uuid);
return getSingleResult(query);
@ -150,6 +150,24 @@ public class RoleRepository extends AbstractEntityRepository<Long, Role> {
return query.getResultList();
}
public long countMembershipsByRole(final Role role) {
return getEntityManager()
.createNamedQuery("RoleMembership.countByRole", Long.class)
.setParameter("role", role)
.getSingleResult();
}
public List<RoleMembership> findMembershipsByRole(
final Role role, final int limit, final int offset
) {
return getEntityManager()
.createNamedQuery("RoleMembership.findByRole", RoleMembership.class)
.setParameter("role", role)
.setMaxResults(limit)
.setFirstResult(offset)
.getResultList();
}
public List<Role> searchByName(final String name) {
final TypedQuery<Role> query = getEntityManager().createNamedQuery(
"Role.searchByName", Role.class);

View File

@ -116,7 +116,7 @@ import javax.xml.bind.annotation.XmlTransient;
@NamedQuery(name = "User.findByGroup",
query = "SELECT u FROM User u "
+ "JOIN u.groupMemberships m "
+ "WHERE m.group = :group")
+ "WHERE m.group = :group"),
})
@NamedEntityGraphs({
@NamedEntityGraph(