Skip to content

Commit

Permalink
feat: impl internal user api for roles and permissions (#41)
Browse files Browse the repository at this point in the history
* feat: impl internal user api for roles and permissions

* feat: token from header

* feat: getHeaderString

* feat: updated docker
  • Loading branch information
JordenReuter authored Jun 4, 2024
1 parent ec54a5c commit eafb70c
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/main/docker/Dockerfile.jvm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/onecx/docker-quarkus-jvm:0.5.0
FROM ghcr.io/onecx/docker-quarkus-jvm:0.6.0

COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
COPY --chown=185 target/quarkus-app/*.jar /deployments/
Expand Down
2 changes: 1 addition & 1 deletion src/main/docker/Dockerfile.native
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
FROM ghcr.io/onecx/docker-quarkus-native:0.3.0
FROM ghcr.io/onecx/docker-quarkus-native:0.4.0

COPY --chown=1001:root target/*-runner /work/application
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.tkit.onecx.permission.bff.rs.controllers;

import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION;

import jakarta.inject.Inject;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.resteasy.reactive.ClientWebApplicationException;
import org.jboss.resteasy.reactive.server.ServerExceptionMapper;
import org.tkit.onecx.permission.bff.rs.mappers.ExceptionMapper;
import org.tkit.onecx.permission.bff.rs.mappers.UserMapper;

import gen.org.tkit.onecx.permission.bff.rs.internal.UserApiService;
import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsCriteriaDTO;
import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsPageResultDTO;
import gen.org.tkit.onecx.permission.client.api.PermissionInternalApi;
import gen.org.tkit.onecx.permission.client.api.RoleInternalApi;
import gen.org.tkit.onecx.permission.client.model.PermissionPageResult;
import gen.org.tkit.onecx.permission.client.model.RolePageResult;

public class UserRestController implements UserApiService {

@Inject
UserMapper userMapper;
@Inject
ExceptionMapper exceptionMapper;

@Inject
@RestClient
RoleInternalApi roleClient;

@Inject
@RestClient
PermissionInternalApi permissionClient;

@Inject
HttpHeaders headers;

@Override
public Response getUserRolesAndPermissions(UserRolesAndPermissionsCriteriaDTO userRolesAndPermissionsCriteriaDTO) {
UserRolesAndPermissionsPageResultDTO resultDTO;
var token = headers.getHeaderString(AUTHORIZATION);
try (Response roleResponse = roleClient
.getUserRoles(userMapper.mapRoleRequest(userRolesAndPermissionsCriteriaDTO, token))) {
try (Response permissionResponse = permissionClient
.getUsersPermissions(userMapper.mapPermissionRequest(userRolesAndPermissionsCriteriaDTO, token))) {
resultDTO = userMapper.map(roleResponse.readEntity(RolePageResult.class),
permissionResponse.readEntity(PermissionPageResult.class));
}
}
return Response.status(Response.Status.OK).entity(resultDTO).build();
}

@ServerExceptionMapper
public Response clientRestException(ClientWebApplicationException ex) {
return exceptionMapper.clientException(ex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ public interface RoleMapper {

@Mapping(target = "removeStreamItem", ignore = true)
IAMRolePageResultDTO map(RolePageResultIamV1 pageResultIamV1);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.tkit.onecx.permission.bff.rs.mappers;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.tkit.quarkus.rs.mappers.OffsetDateTimeMapper;

import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsCriteriaDTO;
import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsPageResultDTO;
import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsPageResultPermissionsDTO;
import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsPageResultRolesDTO;
import gen.org.tkit.onecx.permission.client.model.PermissionPageResult;
import gen.org.tkit.onecx.permission.client.model.PermissionRequest;
import gen.org.tkit.onecx.permission.client.model.RolePageResult;
import gen.org.tkit.onecx.permission.client.model.RoleRequest;

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

@Mapping(target = "pageSize", source = "userRolesAndPermissionsCriteriaDTO.rolesPageSize")
@Mapping(target = "pageNumber", source = "userRolesAndPermissionsCriteriaDTO.rolesPageNumber")
RoleRequest mapRoleRequest(UserRolesAndPermissionsCriteriaDTO userRolesAndPermissionsCriteriaDTO, String token);

@Mapping(target = "pageSize", source = "userRolesAndPermissionsCriteriaDTO.permissionsPageSize")
@Mapping(target = "pageNumber", source = "userRolesAndPermissionsCriteriaDTO.permissionsPageNumber")
PermissionRequest mapPermissionRequest(UserRolesAndPermissionsCriteriaDTO userRolesAndPermissionsCriteriaDTO, String token);

@Mapping(target = "roles", source = "rolePageResult")
@Mapping(target = "permissions", source = "permissionPageResult")
UserRolesAndPermissionsPageResultDTO map(RolePageResult rolePageResult, PermissionPageResult permissionPageResult);

@Mapping(target = "removeStreamItem", ignore = true)
UserRolesAndPermissionsPageResultRolesDTO map(RolePageResult rolePageResult);

@Mapping(target = "removeStreamItem", ignore = true)
UserRolesAndPermissionsPageResultPermissionsDTO map(PermissionPageResult permissionPageResult);
}
90 changes: 89 additions & 1 deletion src/main/openapi/openapi-bff.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetailResponse'
#
/assignments/revoke/{roleId}:
post:
tags:
Expand Down Expand Up @@ -658,8 +657,97 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/WorkspaceDetails'
/user/me:
post:
x-onecx:
permissions:
permission:
- read
tags:
- user
description: get user roles and permissions
operationId: getUserRolesAndPermissions
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserRolesAndPermissionsCriteria'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/UserRolesAndPermissionsPageResult'
components:
schemas:
UserRolesAndPermissionsCriteria:
type: object
properties:
rolesPageNumber:
format: int32
description: The number of page.
default: 0
type: integer
rolesPageSize:
format: int32
description: The size of page
default: 100
type: integer
permissionsPageNumber:
format: int32
description: The number of page.
default: 0
type: integer
permissionsPageSize:
format: int32
description: The size of page
default: 100
type: integer
UserRolesAndPermissionsPageResult:
type: object
properties:
roles:
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/Role'
permissions:
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/Permission'
CreateRolesRequest:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.tkit.onecx.permission.rs;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class UserRestControllerIT extends UserRestControllerTest {
}
130 changes: 130 additions & 0 deletions src/test/java/org/tkit/onecx/permission/rs/UserRestControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.tkit.onecx.permission.rs;

import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;

import java.util.List;

import jakarta.ws.rs.HttpMethod;
import jakarta.ws.rs.core.Response;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockserver.client.MockServerClient;
import org.mockserver.model.JsonBody;
import org.mockserver.model.MediaType;
import org.tkit.onecx.permission.bff.rs.controllers.UserRestController;

import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsCriteriaDTO;
import gen.org.tkit.onecx.permission.bff.rs.internal.model.UserRolesAndPermissionsPageResultDTO;
import gen.org.tkit.onecx.permission.client.model.*;
import io.quarkiverse.mockserver.test.InjectMockServerClient;
import io.quarkus.test.common.http.TestHTTPEndpoint;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
@TestHTTPEndpoint(UserRestController.class)
class UserRestControllerTest extends AbstractTest {

@InjectMockServerClient
MockServerClient mockServerClient;

final String TOKEN = keycloakClient.getAccessToken(ADMIN);

@Test
void getUserRolesAndPermissions() {
var testToken = "Bearer " + TOKEN;
RoleRequest roleRequest = new RoleRequest();
roleRequest.pageNumber(0).pageSize(5).token(testToken);

RolePageResult roleResponse = new RolePageResult();
roleResponse.stream(List.of(new Role().name("role1")));
mockServerClient.when(request().withPath("/internal/roles/me").withMethod(HttpMethod.POST)
.withBody(JsonBody.json(roleRequest)))
.withId("mock1")
.respond(httpRequest -> response().withStatusCode(Response.Status.OK.getStatusCode())
.withContentType(MediaType.APPLICATION_JSON)
.withBody(JsonBody.json(roleResponse)));

PermissionRequest permissionRequest = new PermissionRequest();
permissionRequest.pageNumber(0).pageSize(5).token(testToken);

PermissionPageResult permissionResponse = new PermissionPageResult();
permissionResponse.stream(List.of(new Permission().resource("resource1").action("action1")));
mockServerClient.when(request().withPath("/internal/permissions/me").withMethod(HttpMethod.POST)
.withBody(JsonBody.json(permissionRequest)))
.withId("mock2")
.respond(httpRequest -> response().withStatusCode(Response.Status.OK.getStatusCode())
.withContentType(MediaType.APPLICATION_JSON)
.withBody(JsonBody.json(permissionResponse)));

UserRolesAndPermissionsCriteriaDTO criteriaDTO = new UserRolesAndPermissionsCriteriaDTO();
criteriaDTO.setPermissionsPageNumber(0);
criteriaDTO.setPermissionsPageSize(5);
criteriaDTO.setRolesPageNumber(0);
criteriaDTO.setRolesPageSize(5);

var output = given()
.when()
.auth().oauth2(TOKEN)
.header(APM_HEADER_PARAM, ADMIN)
.contentType(APPLICATION_JSON)
.body(criteriaDTO)
.post()
.then()
.statusCode(Response.Status.OK.getStatusCode())
.contentType(APPLICATION_JSON)
.extract().as(UserRolesAndPermissionsPageResultDTO.class);

Assertions.assertNotNull(output);
Assertions.assertEquals(1, output.getRoles().getStream().size());
Assertions.assertEquals(1, output.getPermissions().getStream().size());

mockServerClient.clear("mock1");
mockServerClient.clear("mock2");
}

@Test
void getUserRolesAndPermissions_BAD_REQUEST() {
var testToken = "Bearer " + TOKEN;
RoleRequest roleRequest = new RoleRequest();
roleRequest.pageNumber(0).pageSize(5).token(testToken);

mockServerClient.when(request().withPath("/internal/roles/me").withMethod(HttpMethod.POST)
.withBody(JsonBody.json(roleRequest)))
.withId("mock1")
.respond(httpRequest -> response().withStatusCode(Response.Status.BAD_REQUEST.getStatusCode())
.withContentType(MediaType.APPLICATION_JSON));

PermissionRequest permissionRequest = new PermissionRequest();
permissionRequest.pageNumber(0).pageSize(5).token(testToken);

mockServerClient.when(request().withPath("/internal/permissions/me").withMethod(HttpMethod.POST)
.withBody(JsonBody.json(permissionRequest)))
.withId("mock2")
.respond(httpRequest -> response().withStatusCode(Response.Status.BAD_REQUEST.getStatusCode())
.withContentType(MediaType.APPLICATION_JSON));

UserRolesAndPermissionsCriteriaDTO criteriaDTO = new UserRolesAndPermissionsCriteriaDTO();
criteriaDTO.setPermissionsPageNumber(0);
criteriaDTO.setPermissionsPageSize(5);
criteriaDTO.setRolesPageNumber(0);
criteriaDTO.setRolesPageSize(5);

var output = given()
.when()
.auth().oauth2(TOKEN)
.header(APM_HEADER_PARAM, ADMIN)
.contentType(APPLICATION_JSON)
.body(criteriaDTO)
.post()
.then()
.statusCode(Response.Status.BAD_REQUEST.getStatusCode());

Assertions.assertNotNull(output);
mockServerClient.clear("mock1");
mockServerClient.clear("mock2");
}
}

0 comments on commit eafb70c

Please sign in to comment.