Skip to content

Commit

Permalink
feat: add permission operator rest api v1
Browse files Browse the repository at this point in the history
  • Loading branch information
andrejpetras committed Jan 4, 2024
1 parent 96e0400 commit c68251e
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 0 deletions.
12 changes: 12 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,18 @@
<modelNameSuffix>DTO</modelNameSuffix>
</configuration>
</execution>
<execution>
<id>operator-v1</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>src/main/openapi/onecx-permission-operator-v1.yaml</inputSpec>
<apiPackage>gen.io.github.onecx.permission.rs.operator.v1</apiPackage>
<modelPackage>gen.io.github.onecx.permission.rs.operator.v1.model</modelPackage>
<modelNameSuffix>DTOV1</modelNameSuffix>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.github.onecx.permission.rs.operator.v1.controllers;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.validation.ConstraintViolationException;
import jakarta.ws.rs.core.Response;

import org.jboss.resteasy.reactive.RestResponse;
import org.jboss.resteasy.reactive.server.ServerExceptionMapper;
import org.tkit.quarkus.log.cdi.LogService;

import gen.io.github.onecx.permission.rs.operator.v1.PermissionOperatorApi;
import gen.io.github.onecx.permission.rs.operator.v1.model.PermissionRequestDTOV1;
import gen.io.github.onecx.permission.rs.operator.v1.model.ProblemDetailResponseDTOV1;
import io.github.onecx.permission.rs.operator.v1.mappers.ExceptionMapper;

@LogService
@ApplicationScoped
public class PermissionOperator implements PermissionOperatorApi {

@Inject
ExceptionMapper exceptionMapper;

@Override
public Response createOrUpdatePermission(String appId, PermissionRequestDTOV1 permissionRequestDTOV1) {
return null;
}

@ServerExceptionMapper
public RestResponse<ProblemDetailResponseDTOV1> constraint(ConstraintViolationException ex) {
return exceptionMapper.constraint(ex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.github.onecx.permission.rs.operator.v1.mappers;

import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Path;
import jakarta.ws.rs.core.Response;

import org.jboss.resteasy.reactive.RestResponse;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import gen.io.github.onecx.permission.rs.operator.v1.model.ProblemDetailInvalidParamDTOV1;
import gen.io.github.onecx.permission.rs.operator.v1.model.ProblemDetailParamDTOV1;
import gen.io.github.onecx.permission.rs.operator.v1.model.ProblemDetailResponseDTOV1;

@Mapper
public abstract class ExceptionMapper {

public RestResponse<ProblemDetailResponseDTOV1> constraint(ConstraintViolationException ex) {
var dto = exception(ErrorKeys.CONSTRAINT_VIOLATIONS.name(), ex.getMessage());
dto.setInvalidParams(createErrorValidationResponse(ex.getConstraintViolations()));
return RestResponse.status(Response.Status.BAD_REQUEST, dto);
}

@Mapping(target = "removeParamsItem", ignore = true)
@Mapping(target = "params", ignore = true)
@Mapping(target = "invalidParams", ignore = true)
@Mapping(target = "removeInvalidParamsItem", ignore = true)
public abstract ProblemDetailResponseDTOV1 exception(String errorCode, String detail);

public List<ProblemDetailParamDTOV1> map(Map<String, Object> params) {
if (params == null) {
return List.of();
}
return params.entrySet().stream().map(e -> {
var item = new ProblemDetailParamDTOV1();
item.setKey(e.getKey());
if (e.getValue() != null) {
item.setValue(e.getValue().toString());
}
return item;
}).toList();
}

public abstract List<ProblemDetailInvalidParamDTOV1> createErrorValidationResponse(
Set<ConstraintViolation<?>> constraintViolation);

@Mapping(target = "name", source = "propertyPath")
@Mapping(target = "message", source = "message")
public abstract ProblemDetailInvalidParamDTOV1 createError(ConstraintViolation<?> constraintViolation);

public String mapPath(Path path) {
return path.toString();
}

public enum ErrorKeys {
CONSTRAINT_VIOLATIONS;
}
}
90 changes: 90 additions & 0 deletions src/main/openapi/onecx-permission-operator-v1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
openapi: 3.0.3
info:
title: onecx-permission operator service
version: 1.0.0
servers:
- url: "http://onecx-permission-svc:8080"
tags:
- name: permissionOperator
paths:
/operator/v1/update/{appId}:
put:
tags:
- permissionOperator
description: Creates or updates permission for application.
operationId: createOrUpdatePermission
parameters:
- name: appId
in: path
description: Application ID
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PermissionRequest'
responses:
201:
description: Create permission
204:
description: Update existing permission
400:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetailResponse'
components:
schemas:
PermissionRequest:
type: object
properties:
permissions:
type: array
minItems: 1
items:
$ref: '#/components/schemas/Permission'
Permission:
type: object
properties:
name:
type: string
object:
type: string
action:
type: string
description:
type: string
ProblemDetailResponse:
type: object
properties:
errorCode:
type: string
detail:
type: string
params:
type: array
items:
$ref: '#/components/schemas/ProblemDetailParam'
invalidParams:
type: array
items:
$ref: '#/components/schemas/ProblemDetailInvalidParam'
ProblemDetailParam:
type: object
properties:
key:
type: string
value:
type: string
ProblemDetailInvalidParam:
type: object
properties:
name:
type: string
message:
type: string
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.github.onecx.permission.rs.operator.v1.controllers;

import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.assertj.core.api.Assertions.assertThat;
import static org.jboss.resteasy.reactive.RestResponse.Status.BAD_REQUEST;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.tkit.quarkus.test.WithDBData;

import gen.io.github.onecx.permission.rs.operator.v1.model.PermissionRequestDTOV1;
import gen.io.github.onecx.permission.rs.operator.v1.model.ProblemDetailResponseDTOV1;
import io.github.onecx.permission.rs.operator.v1.mappers.ExceptionMapper;
import io.github.onecx.permission.test.AbstractTest;
import io.quarkus.test.common.http.TestHTTPEndpoint;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
@TestHTTPEndpoint(PermissionOperator.class)
@WithDBData(value = "data/test-operator-v1.xml", deleteBeforeInsert = true, deleteAfterTest = true, rinseAndRepeat = true)
public class PermissionOperatorTest extends AbstractTest {

@Test
void searchNoBodyTest() {
var exception = given()
.contentType(APPLICATION_JSON)
.pathParam("appId", "app1")
.put()
.then()
.statusCode(BAD_REQUEST.getStatusCode())
.contentType(APPLICATION_JSON)
.extract()
.as(ProblemDetailResponseDTOV1.class);

assertThat(exception).isNotNull();
assertThat(exception.getErrorCode()).isEqualTo(ExceptionMapper.ErrorKeys.CONSTRAINT_VIOLATIONS.name());
assertThat(exception.getDetail()).isEqualTo("createOrUpdatePermission.permissionRequestDTOV1: must not be null");
}

@Test
void searchEmptyListTest() {
var request = new PermissionRequestDTOV1();
request.setPermissions(List.of());

var exception = given()
.contentType(APPLICATION_JSON)
.body(request)
.pathParam("appId", "app1")
.put()
.then()
.statusCode(BAD_REQUEST.getStatusCode())
.contentType(APPLICATION_JSON)
.extract()
.as(ProblemDetailResponseDTOV1.class);

assertThat(exception).isNotNull();
assertThat(exception.getErrorCode()).isEqualTo(ExceptionMapper.ErrorKeys.CONSTRAINT_VIOLATIONS.name());
assertThat(exception.getDetail()).isEqualTo("createOrUpdatePermission.permissionRequestDTOV1.permissions: size must be between 1 and 2147483647");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.onecx.permission.rs.operator.v1.controllers;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
class PermissionOperatorTestIT extends PermissionOperatorTest {

}
14 changes: 14 additions & 0 deletions src/test/resources/data/test-operator-v1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<dataset>

<!-- PERMISSION -->
<PERMISSION guid="p11" optlock="0" name="n1" app_id="app1" object="o1" action="a1"/>
<PERMISSION guid="p12" optlock="0" name="n1" app_id="app1" object="o1" action="a2"/>
<PERMISSION guid="p13" optlock="0" name="n1" app_id="app1" object="o1" action="a3"/>

<PERMISSION guid="p14" optlock="0" name="n1" app_id="app1" object="o2" action="a2"/>
<PERMISSION guid="p15" optlock="0" name="n1" app_id="app1" object="o2" action="a3"/>

<PERMISSION guid="p21" optlock="0" name="n1" app_id="app2" object="o1" action="a1"/>
<PERMISSION guid="p22" optlock="0" name="n1" app_id="app2" object="o1" action="a2"/>
</dataset>

0 comments on commit c68251e

Please sign in to comment.