I have a REST handler with an endpoint for the GET verb. Where from an identifier (ObjectID of MongoDB) I get the information of that entity.
To validate that the ObjectID is valid and avoid errors when using Spring Data Mongo. I have developed a simple validator following the guidelines of the JPA bean validation standard.
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Constraint(validatedBy = ValidObjectIdValidator.class)
@NotNull
@Documented
public @interface ValidObjectId {
String message() default "{constraints.valid.objectid}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class ValidObjectIdValidator implements ConstraintValidator<ValidObjectId, String> {
@Override
public void initialize(ValidObjectId constraintAnnotation) {}
@Override
public boolean isValid(String id, ConstraintValidatorContext context) {
return ObjectId.isValid(id);
}
}
Then I apply the variable-level validation of the controller using the following configuration:
@Api
@RestController("RestUserController")
@Validated
@RequestMapping("/api/v1/children/")
public class ChildrenController implements ISonHAL, ICommentHAL, ISocialMediaHAL
Using @Validated annotation at controller level.
@GetMapping(path = "/{id}")
@ApiOperation(value = "GET_SON_BY_ID", nickname = "GET_SON_BY_ID", notes = "Get Son By Id",
response = SonDTO.class)
@PreAuthorize("@authorizationService.hasParentRole() && @authorizationService.isYourSon(#id)")
public ResponseEntity<APIResponse<SonDTO>> getSonById(
@Valid @ValidObjectId(message = "{son.id.notvalid}")
@ApiParam(value = "id", required = true) @PathVariable String id) throws Throwable {
logger.debug("Get User with id: " + id);
return Optional.ofNullable(sonService.getSonById(id))
.map(sonResource -> addLinksToSon(sonResource))
.map(sonResource -> ApiHelper.<SonDTO>createAndSendResponse(ChildrenResponseCode.SINGLE_USER, HttpStatus.OK, sonResource))
.orElseThrow(() -> { throw new SonNotFoundException(); });
}
Using the @Valid annotation on the @PathVariable.
The problem is that I must verify that the user is currently authenticated is the parent of the child for whom he wants to see his information. This is verified by the execution of:
@PreAuthorize("@authorizationService.hasParentRole() && @authorizationService.isYourSon(#id)")
And here the error occurs. Because I must convert the received id to an ObjectID mediate new ObjectId (id). And this may not be valid.
Is there any way to configure validation to occur before authorization?.
This is my configuration to enable security at the method level:
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
Thanks in advance.