Create one code client / flatten controllers with NSwag and AutoREST - swagger

I'm trying to create a code wrapper for an api with NSwag and Autorest.
Previously I was using Swashbuckle to generate the swagger file. It generated the swagger file with operationIds in the format actionMethod. This resulted in Autorest generating a code client that was 1-deep. All of the actions were on the top-level class.
For various reasons, I needed to change swagger generation to NSwag. This generates operationIds in the format controller_actionMethod. This results in AutoRest creating a composite class that exposes separate classes with actions for each controller.
How can either
Change how NSwag generates the operationIds
Change how Autorest maps operationIds
Note: I know I can manually change the swagger.json, but I'd like to keep a consistent automated process for generating the code client.

There doesn't appear to be any readily available settings, but you can hook into the generation process of NSwag
https://github.com/RicoSuter/NSwag/wiki/Document-Processors-and-Operation-Processors#operation-processors
The operation processor
class FlattenOperationsProcessor: IOperationProcessor
{
public async Task<bool> ProcessAsync(OperationProcessorContext context)
{
context.OperationDescription.Operation.OperationId = $"{context.MethodInfo.Name}";
return true;
}
}
Then add it in Startup.cs
document.OperationProcessors.Add(new FlattenOperationsProcessor());

Not sure if this was available when the question was asked, but here is a pretty easy way to do it:
services.AddSwaggerGen(c =>
{
...
c.CustomOperationIds(d => d.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor ? controllerActionDescriptor.MethodInfo.Name : d.ActionDescriptor.AttributeRouteInfo?.Name);
});
The same can also be set via c.SwaggerGeneratorOptions.OperationIdSelector
Note that ActionDescriptor.AttributeRouteInfo?.Name is the default I used from the source code here

Related

How to extend standard spring cloud data flow components and add our custom logic

I'm looking to develop a custom processor that leverages the functionality of s3-sink and then add some custom logic to it.
I could do it without using standard components. i.e. using S3 APIs to write files along with custom logic. I would like to know if there is any way I can leverage the functionality of standard component and extend it to add our custom logic.
If you want to invoke some logic before or after the S3Sink normal logic then you can use function composition and create a custom Sink application that imports the S3SinkConfiguration and defines a java.util.Function that is applied after the normal S3Sink logic.
You will need to set the spring.cloud.function.definition property to s3Consumer|myCustomLogicFunctionName.
However, if you want to tweak what the S3Sink logic actually is (not before or after it executes), you will have to look into what it offers for extensibility/configurability. The S3Sink app looks like this:
#SpringBootApplication
#Import({ org.springframework.cloud.fn.consumer.s3.AwsS3ConsumerConfiguration.class })
public class S3SinkKafkaApplication {
public static void main(String[] args) {
SpringApplication.run(S3SinkKafkaApplication.class, args);
}
}
As you can see its just a SpringBoot app that imports a single configuration class. All the logic/magic is in that configuration. It in turn leverages Spring Integration AWS S3MessageHandler.
What does the custom logic need to do? Maybe the underlying S3MessageHandler supports that via configuration/extension.

How to sort the Schemas on Swagger-ui SpringDoc open ui

I want to sort my Schemas generated for my Entity classes, DTO classes in Springdoc UI.
I am able to sort the tags and operations using the below configuration in yml file but my schemas are not in the sorted order.
springdoc:
swagger-ui:
disable-swagger-default-url: true
tags-sorter: alpha
operations-sorter: alpha
doc-expansion: none
How could I sort my schemas.
Thanks.
You can have full control of the schemas order using OpenApiCustomiser.
This is a sample code that you can customize using Comparators, depending on the sorting logic you want:
#Bean
public OpenApiCustomiser sortSchemasAlphabetically() {
return openApi -> {
Map<String, Schema> schemas = openApi.getComponents().getSchemas();
openApi.getComponents().setSchemas(new TreeMap<>(schemas));
};
}
If you are interested on the sorting on the swagger-ui, not on the server side, then you can log a feature request on the swagger-ui project.

How can I find my dotnet mvc Controller's ApiVersion programmatically

I'm using dotnet core 1.1. I have a web api with several controllers, which look like this:
[ApiVersion("1.0")]
[Route("v{version:apiVersion}/mycontroller")]
public class MyController : Controller
{
[HttpGet("action1")]
public string Get()
{ /* actual logic */ }
// More actions ...
}
I'd like to have a special controller which iterates through my controllers and print out the version and the route to them, like this:
MyController -- 1.0 -- /v1.0/mycontroller
MyOtherController -- 1.1 -- /v1.1/myothercontroller
But I can't figure out how to access the data at runtime. Thoughts?
Apologies for being late to the party, but the way to achieve this is to use the complimentary API Explorer package for API Versioning. This package is most commonly used for Swagger generation, but there is no direct coupling or usage of Swagger. You can use the API Explorer to enumerate all your controllers as well as their corresponding versions and routes.
In your scenario, you would integrate the required services with:
services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
}
The controller you want to output the information should declare the IApiDescriptionGroupCollectionProvider and IApiVersionDescriptionProvider services in its constructor. The APIs will be grouped according to the GroupName property in the format specified by the API Explorer.
That should get you started. Let me know if you have more questions.

AutoFac Injection into attribute

So I have a need for injecting a number of different services into an authorization attribute I'm using. For simplicity I will leave this to show the configuration manager.
public class FeatureAuthorizeAttribute : AuthorizeAttribute
{
public IConfigurationManager ConfigurationManager;
private readonly string _feature;
public FeatureAuthorizeAttribute(string feature)
{
_feature = feature;
var test = ConfigurationManager.GetCdnPath();
}
}
Which would be used as follows
[FeatureAuthorize("Admin")]
I have tried to use constructor injection
public FeatureAuthorizeAttribute(string feature, IConfigurationManager configurationManager)
{
ConfigurationManager = configurationManager;
_feature = feature
}
However this just causes an error when I attempt
[FeatureAuthorize("Admin", IConfigurationManager)]
Which seems like the wrong way to go about it in the first place. I'm assuming that I need to register my custom authorization attribute with the container to get it to start picking up
Instead of trying to use Dependency Injection with attributes (which you can't do in any sane, useful way), create Passive Attributes.
Specifically, in this case, assuming that this is an ASP.NET MVC scenario, you can't derive from AuthorizeAttribute. Instead, you should make your Authorization service look for your custom attribute, and implement IAuthorizationFilter. Then add the filter to your application's configuration.
More details can be found in this answer: https://stackoverflow.com/a/7194467/126014.

Any way to get MVC Authorization statistics of an application?

I'm now building an application in MVC5. Data of different corporations are stored in the same database and people access them under the control of "[Authorize(...)]" and some other costumed filters. With the growing of controllers and actions, I'm more and more worried about the security, for example: is there any actions without authorization or with wrong authorization?
So the question is: Is there any
1. Report views in Visual Studio (might not designed to do the work)
2. Third part tools
3. Something else
that give a clear map of authorization of all controllers/actions? This is a critical work and I think there should be some solutions rather than check through all those code files.
Thanks.
I like to use FluentSecurity because of this. From their docs:
Ignoring missing configurations
By default FluentSecurity will throw an exception if a missing
configuration is encountered for a controller action. If you don't
want FluentSecurity to handle security for all controllers you can
tell it to ignore missing configurations. You can do this by adding
configuration.IgnoreMissingConfiguration(); to your configuration
expression.
It puts security configurations in a single file, makes them unit testable, and is generally useful. There is a small learning curve to figuring out how to bootstrap it and get it set up. You can install it and get going quickly using nuget.
Besides this, there arent really any tools that I know of that can do the reporting that you are asking about... unless you want to write a battery of unit tests against each actionmethod:
[TestFixture]
public class AccountControllerTests {
[Test]
public void Verify_ChangePassword_Method_Is_Decorated_With_Authorize_Attribute() {
var controller = new AccountController();
var type = controller.GetType();
var methodInfo = type.GetMethod("ChangePassword", new Type[] { typeof(ChangePasswordModel) });
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
Assert.IsTrue(attributes.Any(), "No AuthorizeAttribute found on ChangePassword(ChangePasswordModel model) method");
}
}

Resources