Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: getUserAssignments #63

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ quarkus.hibernate-orm.multitenant=DISCRIMINATOR
quarkus.hibernate-orm.jdbc.timezone=UTC
quarkus.liquibase.migrate-at-start=true
quarkus.liquibase.validate-on-migrate=true
quarkus.hibernate-orm.log.sql=true
tkit.rs.context.tenant-id.enabled=true
onecx.permission.token.verified=true
onecx.permission.token.issuer.public-key-location.suffix=/protocol/openid-connect/certs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,33 @@ public List<PermissionAction> findPermissionActionForProducts(Set<String> produc
}
}

public PageResult<Assignment> findUserAssignments(List<String> roles, int pageNumber, int pageSize) {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Assignment.class);
var root = cq.from(Assignment.class);

cq.where(root.get(Assignment_.ROLE).get(Role_.NAME).in(roles));
return createPageQueryCustom(cq, Page.of(pageNumber, pageSize)).getPageResult();
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_USER_ASSIGNMENTS, ex);
}
}

public List<Assignment> loadAssignments(List<String> assignmentIds) {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Assignment.class);
var root = cq.from(Assignment.class);
cq.where(root.get(TraceableEntity_.ID).in(assignmentIds));

return this.getEntityManager().createQuery(cq).setHint(HINT_LOAD_GRAPH,
this.getEntityManager().getEntityGraph(Assignment.ASSIGNMENT_FULL)).getResultList();
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_LOAD_ASSIGNMENTS, ex);
}
}

public enum ErrorKeys {

ERROR_DELETE_BY_PRODUCT_NAME_APP_IDS,
Expand All @@ -184,7 +211,8 @@ public enum ErrorKeys {
ERROR_DELETE_BY_PERMISSION_ID,
ERROR_DELETE_BY_ROLE_ID,
ERROR_FIND_PERMISSION_ACTION_FOR_PRODUCTS,

ERROR_FIND_USER_ASSIGNMENTS,
ERROR_LOAD_ASSIGNMENTS,
FIND_ENTITY_BY_ID_FAILED,
ERROR_FIND_ASSIGNMENT_BY_CRITERIA,
ERROR_SELECT_MANDATORY_BY_ROLE_ID;
Expand Down
18 changes: 9 additions & 9 deletions src/main/java/org/tkit/onecx/permission/domain/daos/RoleDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,28 +63,28 @@ public PageResult<Role> findByCriteria(RoleSearchCriteria criteria) {
}
}

public PageResult<Role> findUsersRoles(List<String> tokenRoles, int pageNumber, int pageSize) {
public List<Role> findByNames(Set<String> names) {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Role.class);
var root = cq.from(Role.class);
cq.where(root.get(Role_.name).in(tokenRoles));

return createPageQuery(cq, Page.of(pageNumber, pageSize)).getPageResult();
cq.where(root.get(Role_.name).in(names));
return this.getEntityManager().createQuery(cq).getResultList();
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_USER_ROLES, ex);
throw new DAOException(ErrorKeys.ERROR_FIND_ROLE_BY_CRITERIA, ex);
}
}

public List<Role> findByNames(Set<String> names) {
public PageResult<Role> findUsersRoles(List<String> tokenRoles, int pageNumber, int pageSize) {
try {
var cb = this.getEntityManager().getCriteriaBuilder();
var cq = cb.createQuery(Role.class);
var root = cq.from(Role.class);
cq.where(root.get(Role_.name).in(names));
return this.getEntityManager().createQuery(cq).getResultList();
cq.where(root.get(Role_.name).in(tokenRoles));

return createPageQuery(cq, Page.of(pageNumber, pageSize)).getPageResult();
} catch (Exception ex) {
throw new DAOException(ErrorKeys.ERROR_FIND_ROLE_BY_CRITERIA, ex);
throw new DAOException(ErrorKeys.ERROR_FIND_USER_ROLES, ex);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
@Getter
@Setter
@Entity
@NamedEntityGraph(name = Assignment.ASSIGNMENT_FULL, includeAllAttributes = true)
@Table(name = "ASSIGNMENT", uniqueConstraints = {
@UniqueConstraint(name = "UC_ASSIGNMENT_KEY", columnNames = { "PERMISSION_ID", "ROLE_ID", "TENANT_ID" })
})
@SuppressWarnings("java:S2160")
public class Assignment extends TraceableEntity {

public static final String ASSIGNMENT_FULL = "assignment_full";

@TenantId
@Column(name = "TENANT_ID")
private String tenantId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@

import org.jboss.resteasy.reactive.RestResponse;
import org.jboss.resteasy.reactive.server.ServerExceptionMapper;
import org.tkit.onecx.permission.common.services.TokenService;
import org.tkit.onecx.permission.domain.daos.AssignmentDAO;
import org.tkit.onecx.permission.domain.daos.PermissionDAO;
import org.tkit.onecx.permission.domain.daos.RoleDAO;
import org.tkit.onecx.permission.domain.models.Assignment;
import org.tkit.onecx.permission.domain.services.AssignmentService;
import org.tkit.onecx.permission.rs.internal.mappers.AssignmentMapper;
import org.tkit.onecx.permission.rs.internal.mappers.ExceptionMapper;
import org.tkit.quarkus.jpa.daos.PageResult;
import org.tkit.quarkus.jpa.exceptions.ConstraintException;
import org.tkit.quarkus.jpa.models.TraceableEntity;
import org.tkit.quarkus.log.cdi.LogExclude;
import org.tkit.quarkus.log.cdi.LogService;

import gen.org.tkit.onecx.permission.rs.internal.AssignmentInternalApi;
Expand Down Expand Up @@ -46,6 +51,9 @@ public class AssignmentRestController implements AssignmentInternalApi {
@Inject
AssignmentService service;

@Inject
TokenService tokenService;

@Override
public Response getAssignment(String id) {
var data = dao.findById(id);
Expand All @@ -55,6 +63,17 @@ public Response getAssignment(String id) {
return Response.ok(mapper.map(data)).build();
}

@Override
public Response getUserAssignments(@LogExclude AssignmentRequestDTO assignmentRequestDTO) {
var roles = tokenService.getTokenRoles(assignmentRequestDTO.getToken());
var page = dao.findUserAssignments(roles, assignmentRequestDTO.getPageNumber(),
assignmentRequestDTO.getPageSize());
var assignments = dao.loadAssignments(page.getStream().map(TraceableEntity::getId).toList());
PageResult<Assignment> pageResult = new PageResult<>(page.getTotalElements(), assignments.stream(),
page.getNumber(), page.getSize());
return Response.ok().entity(mapper.mapUserAssignments(pageResult)).build();
}

@Override
public Response searchAssignments(AssignmentSearchCriteriaDTO assignmentSearchCriteriaDTO) {
var criteria = mapper.map(assignmentSearchCriteriaDTO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,29 @@
import org.tkit.onecx.permission.domain.criteria.AssignmentSearchCriteria;
import org.tkit.onecx.permission.domain.models.Assignment;
import org.tkit.onecx.permission.domain.models.Permission;
import org.tkit.onecx.permission.domain.models.PermissionAction;
import org.tkit.onecx.permission.domain.models.Role;
import org.tkit.quarkus.jpa.daos.PageResult;
import org.tkit.quarkus.rs.mappers.OffsetDateTimeMapper;

import gen.org.tkit.onecx.permission.rs.internal.model.AssignmentDTO;
import gen.org.tkit.onecx.permission.rs.internal.model.AssignmentPageResultDTO;
import gen.org.tkit.onecx.permission.rs.internal.model.AssignmentSearchCriteriaDTO;
import gen.org.tkit.onecx.permission.rs.internal.model.*;

@Mapper(uses = { OffsetDateTimeMapper.class })
public interface AssignmentMapper {

@Mapping(target = "removeStreamItem", ignore = true)
AssignmentPageResultDTO map(PageResult<Assignment> page);

@Mapping(target = "removeStreamItem", ignore = true)
UserAssignmentPageResultDTO mapUserAssignments(PageResult<Assignment> pageResult);

@Mapping(target = "roleName", source = "role.name")
@Mapping(target = "resource", source = "permission.resource")
@Mapping(target = "productName", source = "permission.productName")
@Mapping(target = "applicationId", source = "permission.appId")
@Mapping(target = "action", source = "permission.action")
UserAssignmentDTO mapAssignment(Assignment assignment);

AssignmentSearchCriteria map(AssignmentSearchCriteriaDTO dto);

@Mapping(target = "id", ignore = true)
Expand All @@ -44,4 +53,9 @@ public interface AssignmentMapper {
default List<Assignment> createList(Role role, List<Permission> permissions) {
return permissions.stream().map(permission -> create(role, permission)).toList();
}

@Mapping(target = "removeStreamItem", ignore = true)
UserAssignmentPageResultDTO mapPermissionActions(PageResult<PermissionAction> assignments);

UserAssignmentDTO map(PermissionAction permissionAction);
}
74 changes: 74 additions & 0 deletions src/main/openapi/onecx-permission-internal-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,30 @@ paths:
responses:
204:
description: Assignment deleted
/internal/assignments/me:
post:
tags:
- assignmentInternal
operationId: getUserAssignments
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AssignmentRequest'
responses:
200:
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserAssignmentPageResult'
400:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetailResponse'
/internal/roles:
post:
tags:
Expand Down Expand Up @@ -611,6 +635,23 @@ components:
description: The size of page
default: 100
type: integer
AssignmentRequest:
type: object
required:
- token
properties:
token:
type: string
pageNumber:
format: int32
description: The number of page.
default: 0
type: integer
pageSize:
format: int32
description: The size of page
default: 100
type: integer
AssignmentSearchCriteria:
type: object
properties:
Expand Down Expand Up @@ -771,6 +812,39 @@ components:
mandatory:
type: boolean
default: false
UserAssignmentPageResult:
type: object
properties:
totalElements:
format: int64
description: The total elements in the resource.
type: integer
number:
format: int32
type: integer
size:
format: int32
type: integer
totalPages:
format: int64
type: integer
stream:
type: array
items:
$ref: '#/components/schemas/UserAssignment'
UserAssignment:
type: object
properties:
roleName:
type: string
productName:
type: string
applicationId:
type: string
resource:
type: string
action:
type: string
RolePageResult:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ void methodExceptionTests() {
AssignmentDAO.ErrorKeys.ERROR_FIND_PERMISSION_ACTION_FOR_PRODUCTS);
methodExceptionTests(() -> dao.selectMandatoryByRoleId(null),
AssignmentDAO.ErrorKeys.ERROR_SELECT_MANDATORY_BY_ROLE_ID);
methodExceptionTests(() -> dao.findUserAssignments(null, 0, 0),
AssignmentDAO.ErrorKeys.ERROR_FIND_USER_ASSIGNMENTS);
methodExceptionTests(() -> dao.loadAssignments(null),
AssignmentDAO.ErrorKeys.ERROR_LOAD_ASSIGNMENTS);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ void methodExceptionTests() {
PermissionDAO.ErrorKeys.ERROR_FIND_NOT_BY_IDS);
methodExceptionTests(() -> dao.findUsersPermissions(null, 0, 0),
PermissionDAO.ErrorKeys.ERROR_FIND_PERMISSION_FOR_USER);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -576,4 +576,23 @@ void revokeAssignmentByRoleProducts() {
.statusCode(NO_CONTENT.getStatusCode());

}

@Test
void getUsersAssignmentsTest() {

// bearer prefix
var accessToken = createAccessTokenBearer(USER_ALICE);

var dto = given()
.contentType(APPLICATION_JSON)
.body(new AssignmentRequestDTO().token(accessToken).pageNumber(0).pageSize(10))
.post("/me")
.then()
.log().all()
.statusCode(OK.getStatusCode())
.extract()
.body().as(UserAssignmentPageResultDTO.class);

assertThat(dto).isNotNull();
}
}
Loading