kokuwaio/micronaut-openapi-codegen

Feature: add flag to generate `Authentication` parameter into api interfaces

Closed this issue · 5 comments

If I want to use micronaut-security's Authentication parameter, which is supported inside controller-level methods, it isn't clear how to do so with this generator.

For example, given I want to check the value of this using something like:

public reactor.core.publisher.Mono<io.micronaut.http.HttpResponse<MyObject>> mySpecialMethod(Authentication auth,
                                                          @PathVariable("someVariable") UUID someVariable,
                                                          @Body @Valid MyRequestBody request) {
        JwtUtils.mustBeProperlyDefined(auth);
        String username = auth.getAttributes().get("user_name").toString();
        <...Business logic here...>
}

None of the settings in the generator allow for adding the Authentication auth parameter (io.micronaut.security.authentication.Authentication) upon generation.

I've checked the documentation provided but this isn't clear at all.

Right now there is no flag for this.

To access the authentication you can use:

@Inject
SecurityService security;

private Authentication getAuthentication() {
	return security.getAuthentication().orElseThrow(() -> new HttpStatusException(HttpStatus.UNAUTHORIZED, null));
}

Or use:

private Authentication getAuthentication() {
	return ServerRequestContext.currentRequest()
			.flatMap(r -> r.getUserPrincipal(Authentication.class))
			.orElseThrow(() -> new HttpStatusException(HttpStatus.UNAUTHORIZED, null));
}

If this is not sufficient for you, how should the generator handle this authentication objects? My suggestion: add a flag and if flag is enabled and response code 401 exists add Authentication for controller interfaces. What do you think?

That's the workaround I'm using at the moment, it does work - it's just a bit verbose to have to add it into every controller, which adds up if there are multiple. I think the flag is a good shout!

On another note - not sure if it's worth opening up a new issue - but how can I make sure from the API spec that a "number" input on an API Spec comes out as BigDecimal in the generated model? I can see here we're explicitly mapping it to Double, but I don't see the reason for that

typeMapping.put("BigDecimal", java.lang.Double.class.getName());

I found this: https://stackoverflow.com/questions/55654672/how-to-treat-a-double-field-as-bigdecimal-while-generating-java-code-from-a
But this doesn't work, as we seem to be clearing user-defined typeMappings at the top of that block of code for some reason, so even if we map Double to BigDecimal, the library clears it

I'll add this flag, but not immediately because if other stuff todo before.

Regarding BigDecimal vs Double, you can override the default mapping using:

<typeMappings>
  <typeMapping>BigDecimal=java.math.BigDecimal</typeMapping>
</typeMappings>

The default with Double was chosen because for most users double precision is enough and BigDecimal handling is sometimes a pain. I won't change this now because a lot of users rely on Double.

Please review the pr. Does this fit your requirements?

Released with 3.3.0