Search code examples
javaswaggeropenapiopenapi-generator

Using @PreAuthorize with openapi-tools


I am using openapi-generator-maven-plugin for code generation

            <groupId>org.openapitools</groupId>
            <artifactId>openapi-generator-maven-plugin</artifactId>
            <version>6.0.1</version>

And I need to have @PreAuthorize annotation on precise API method.

@RestController
@Validated
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/api/v1")
public class SomeController implements SomeApi {

    @Override
    @PreAuthorize("hasRole('ROLE_USER_ADMIN') || hasRole('ROLE_DIGITAL_REP') || hasRole('ROLE_FIELD_REP')")
    public ResponseEntity<SomeDto> getSomeInfo() {
        return ResponseEntity
            .status(HttpStatus.OK)
            .body("some info");
    }

It does not work because you can't use Spring annotations inside class (SomeApi calls overriden version of getSomeInfo inside). So my question is - is that possible to add @PreAuthorize for API endpoint during code generation step ? I've found discussion here https://github.com/OpenAPITools/openapi-generator/issues/1975, but it is not clear was tis solved or not.


Solution

  • I've managed to do it by custom templates. Here is the nice video about it https://www.youtube.com/watch?v=Jp2y15Xgk9g&t=1175s&ab_channel=Cloud-NativeDevelopment and my custom template looks like this:

            @RequestMapping(
            method = RequestMethod.{{httpMethod}},
            value = "{{{path}}}"{{#singleContentTypes}}{{#hasProduces}},
            produces = "{{{vendorExtensions.x-accepts}}}"{{/hasProduces}}{{#hasConsumes}},
            consumes = "{{{vendorExtensions.x-content-type}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}},
            produces = { {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} }{{/hasProduces}}{{#hasConsumes}},
            consumes = { {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} }{{/hasConsumes}}{{/singleContentTypes}}
            )
        {{#vendorExtensions.x-custom-role}}
            @PreAuthorize("{{{.}}}")
        {{/vendorExtensions.x-custom-role}}
    

    and yml looks like this:

      /foo/bar/{tab}:
        get:
          operationId: someOperation
          x-custom-role: "hasRole('ROLE_USER_ADMIN')