1
0

add RbacUser* tests and improved http status codes

This commit is contained in:
Michael Hoennig
2022-08-05 14:31:54 +02:00
parent f2bc42bd85
commit bef358eda6
16 changed files with 540 additions and 73 deletions

View File

@ -13,6 +13,7 @@ import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.time.LocalDateTime;
import java.util.Optional;
@ControllerAdvice
public class RestResponseEntityExceptionHandler
@ -22,16 +23,39 @@ public class RestResponseEntityExceptionHandler
protected ResponseEntity<CustomErrorResponse> handleConflict(
final RuntimeException exc, final WebRequest request) {
return new ResponseEntity<>(
new CustomErrorResponse(request.getContextPath(), exc, HttpStatus.CONFLICT), HttpStatus.CONFLICT);
final var message = firstLine(NestedExceptionUtils.getMostSpecificCause(exc).getMessage());
return errorResponse(request, HttpStatus.CONFLICT, message);
}
@ExceptionHandler(JpaSystemException.class)
protected ResponseEntity<CustomErrorResponse> handleJpaExceptions(
final RuntimeException exc, final WebRequest request) {
final var message = firstLine(NestedExceptionUtils.getMostSpecificCause(exc).getMessage());
return errorResponse(request, httpStatus(message).orElse(HttpStatus.FORBIDDEN), message);
}
private Optional<HttpStatus> httpStatus(final String message) {
if (message.startsWith("ERROR: [")) {
for (HttpStatus status : HttpStatus.values()) {
if (message.startsWith("ERROR: [" + status.value() + "]")) {
return Optional.of(status);
}
}
return Optional.of(HttpStatus.INTERNAL_SERVER_ERROR);
}
return Optional.empty();
}
private static ResponseEntity<CustomErrorResponse> errorResponse(
final WebRequest request,
final HttpStatus conflict,
final String message) {
return new ResponseEntity<>(
new CustomErrorResponse(request.getContextPath(), exc, HttpStatus.FORBIDDEN), HttpStatus.FORBIDDEN);
new CustomErrorResponse(request.getContextPath(), conflict, message), conflict);
}
private String firstLine(final String message) {
return message.split("\\r|\\n|\\r\\n", 0)[0];
}
}
@ -49,15 +73,11 @@ class CustomErrorResponse {
private final String message;
public CustomErrorResponse(final String path, final RuntimeException exc, final HttpStatus status) {
public CustomErrorResponse(final String path, final HttpStatus status, final String message) {
this.timestamp = LocalDateTime.now();
this.path = path;
this.status = status.value();
this.error = status.getReasonPhrase();
this.message = firstLine(NestedExceptionUtils.getMostSpecificCause(exc).getMessage());
}
private String firstLine(final String message) {
return message.split("\\r|\\n|\\r\\n", 0)[0];
this.message = message;
}
}

View File

@ -1,11 +1,16 @@
package net.hostsharing.hsadminng.rbac.rbacuser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import net.hostsharing.hsadminng.context.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
@RestController
public class RbacUserController {
@ -16,9 +21,18 @@ public class RbacUserController {
@Autowired
private RbacUserRepository rbacUserRepository;
@GetMapping(value = "/api/rbacuser")
@GetMapping(value = "/api/rbacusers")
@Operation(description = "List accessible RBAC users with optional filter by name.",
responses = {
@ApiResponse(responseCode = "200",
content = @Content(array = @ArraySchema(
schema = @Schema(implementation = RbacUserEntity.class)))),
@ApiResponse(responseCode = "401",
description = "if the 'current-user' cannot be identified"),
@ApiResponse(responseCode = "403",
description = "if the 'current-user' is not allowed to assume any of the roles from 'assumed-roles'") })
@Transactional
public Iterable<RbacUserEntity> listUsers(
public List<RbacUserEntity> listUsers(
@RequestHeader(name = "current-user") String currentUserName,
@RequestHeader(name = "assumed-roles", required = false) String assumedRoles,
@RequestParam(name="name", required = false) String userName
@ -31,8 +45,15 @@ public class RbacUserController {
}
@GetMapping(value = "/api/rbacuser/{userName}/permissions")
@Operation(description = "List all visible permissions granted to the given user; reduced ", responses = {
@ApiResponse(responseCode = "200",
content = @Content(array = @ArraySchema( schema = @Schema(implementation = RbacUserPermission.class)))),
@ApiResponse(responseCode = "401",
description = "if the 'current-user' cannot be identified"),
@ApiResponse(responseCode = "403",
description = "if the 'current-user' is not allowed to view permissions of the given user") })
@Transactional
public Iterable<RbacUserPermission> listUserPermissions(
public List<RbacUserPermission> listUserPermissions(
@RequestHeader(name = "current-user") String currentUserName,
@RequestHeader(name = "assumed-roles", required = false) String assumedRoles,
@PathVariable(name= "userName") String userName

View File

@ -14,30 +14,6 @@ import java.util.UUID;
@Immutable
@NoArgsConstructor
@AllArgsConstructor
//@SqlResultSetMapping(
// name = "rbacUserPermissionMapping",
// classes = {
// @ConstructorResult(
// targetClass = RbacUserPermission.class,
// columns = {
// @ColumnResult(name = "roleUuid", type = UUID.class),
// @ColumnResult(name = "oleName", type = String.class),
// @ColumnResult(name = "permissionUuid", type = UUID.class),
// @ColumnResult(name = "op", type=String.class),
// @ColumnResult(name = "objectTable", type=String.class),
// @ColumnResult(name = "objectIdName", type =String.class),
// @ColumnResult(name = "objectUuid", type = UUID.class),
// @ColumnResult(name = "campId", type = Integer.class),
// @ColumnResult(name = "userCount", type = Byte.class)
// }
// )
// }
//)
//@NamedNativeQuery(
// name = "grantedPermissions",
// query = "SELECT * FROM grantedPermissions(:userName)",
// resultSetMapping = "rbacUserPermissionMapping"
//)
public class RbacUserEntity {
@Id

View File

@ -13,5 +13,5 @@ public interface RbacUserRepository extends Repository<RbacUserEntity, UUID> {
List<RbacUserEntity> findByOptionalNameLike(final String userName);
@Query(value = "SELECT * FROM grantedPermissions(:userName)", nativeQuery = true)
Iterable<RbacUserPermission> findPermissionsOfUser(@Param("userName") String userName);
List<RbacUserPermission> findPermissionsOfUser(@Param("userName") String userName);
}