Base solution for your next web application
Open Closed

How to hide Dynamic Web Api from Swagger UI documentation #4380


User avatar
0
banksearch created

Hi There,

I would like to hide all dynamic APIS from /swagger documentation. (Still generates dynamic apis but hide them from documentation)

I have seen a note about this in your documentation stating that this could be achieved like below

"API Explorer All dynamic web api controllers are visible to API explorer by default (They are available in Swagger for example). You can control this behaviour with fluent DynamicApiControllerBuilder API or using RemoteService attribute defined below. i RemoteService Attribute You can also use RemoteService attribute for any interface or method definition to enable/disable (IsEnabled) dynamic API or API explorer setting (IsMetadataEnabled)."

However, When I use the attribute [RemoteService(IsMetadataEnabled=true)] in the services, This is perfectly hides the documentation in swagger. But also breaks the page that service does not get created

My understanding is that if [RemoteService(IsEnabled=true)] then the dynamic api should still be generated. And IsMetadataEnabled=false should disable the swagger ui.

I have put the attribute for the class HostDashboardAppService class and this breaks the home page as I guess home page uses the api.

Is there any better way to hide all dynamic apis from the documentation?

I have also tried swagger way to hide the apis but as the apis are generated dynamically

[ApiExplorerSettings(IgnoreApi=true)] did not work to hide documentations.

Any better idea to hide all dynamic apis documentation?

Regards,


3 Answer(s)
  • User Avatar
    0
    bbakermmc created

    We created our own attribute/filter for swagger. It will show the endpoint the user has permissions too. You should be able to adapt it to show none :D

    public class SwaggerAbpAuthorizeAttributeAuthorizationFilter : IDocumentFilter
        {
            private readonly IPermissionChecker _permissionChecker;
    
            public SwaggerAbpAuthorizeAttributeAuthorizationFilter(IPermissionChecker permissionChecker)
            {
                _permissionChecker = permissionChecker;
            }
    
            public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
            {
                var descriptions = context.ApiDescriptionsGroups.Items.SelectMany(group => group.Items);
    
                foreach (var description in descriptions)
                {
                    var route = "/" + description.RelativePath.TrimEnd('/');
                    var path = swaggerDoc.Paths[route];
    
                    var controllerAbpAuthorizeAttributes = description.ControllerAttributes()
                        .OfType<AbpAuthorizeAttribute>().ToList();
    
                    var actionAbpAuthorizeAttributes = description.ActionAttributes()
                        .OfType<AbpAuthorizeAttribute>().ToList();
    
                    var hideSwaggerList = description.ActionAttributes()
                        .OfType<SwaggerHide>().ToList();
    
                    var isHideSwagger = hideSwaggerList.Any();
                    
                    if (isHideSwagger)
                    {
                        swaggerDoc.Paths.Remove(route);
                    }
    
                    var authAttributes = new List<AbpAuthorizeAttribute>();
    
                    if (actionAbpAuthorizeAttributes.Count > 0)
                        authAttributes = actionAbpAuthorizeAttributes;
                    else if (controllerAbpAuthorizeAttributes.Count > 0)
                        authAttributes = controllerAbpAuthorizeAttributes;
    
                    // check if this action should be visible
                    var forbiddenDuePermissions = IsForbiddenDuePermissions(authAttributes);
    
                    if (!forbiddenDuePermissions)
                        continue; // user passed all permissions checks
    
                    // remove method or entire path (if there are no more methods in this path)
                    switch (description.HttpMethod)
                    {
                        case "DELETE":
                            path.Delete = null;
                            break;
                        case "GET":
                            path.Get = null;
                            break;
                        case "HEAD":
                            path.Head = null;
                            break;
                        case "OPTIONS":
                            path.Options = null;
                            break;
                        case "PATCH":
                            path.Patch = null;
                            break;
                        case "POST":
                            path.Post = null;
                            break;
                        case "PUT":
                            path.Put = null;
                            break;
                        default: throw new ArgumentOutOfRangeException("Method name not mapped to operation");
                    }
    
                    if (path.Delete == null && path.Get == null &&
                        path.Head == null && path.Options == null &&
                        path.Patch == null && path.Post == null && path.Put == null)
                        swaggerDoc.Paths.Remove(route);
    
                    
                }
            }
    
            private bool IsForbiddenDuePermissions(IEnumerable<AbpAuthorizeAttribute> attributes)
            {
                var authorizeAttributes = attributes
                    .Where(p => p.Permissions != null).ToList();
    
                var permissions = new List<string>();
                if (authorizeAttributes.Count != 0)
                    foreach (var authorizeAttribute in authorizeAttributes)
                        permissions.AddRange(authorizeAttribute.Permissions.ToList());
                else
                    return true;
    
                foreach (var permission in permissions)
                {
                    var allow = _permissionChecker.IsGranted(permission);
                    if (allow)
                        return false;
                }
    
                return true;
            }
        }
    
  • User Avatar
    0
    banksearch created

    Thanks for the code. It helped me to find a way to hide all. I have created a custom attribute as ShowSwagger and onyl shows the services that has the ShowSwagger.

  • User Avatar
    0
    alper created
    Support Team

    thanks for your share @BBakerMMC