Browse Source

Swagger improvements.

pull/336/head
Sebastian Stehle 7 years ago
parent
commit
bfe2e37686
  1. 29
      src/Squidex/Areas/Api/Config/Swagger/ScopesProcessor.cs
  2. 4
      src/Squidex/Areas/Api/Config/Swagger/SecurityProcessor.cs
  3. 6
      src/Squidex/Areas/Api/Config/Swagger/SwaggerExtensions.cs
  4. 3
      src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs
  5. 7
      src/Squidex/Areas/Api/Config/Swagger/XmlTagProcessor.cs
  6. 14
      src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs
  7. 1
      src/Squidex/Areas/Api/Controllers/Contents/ContentSwaggerController.cs
  8. 2
      src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
  9. 40
      src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaSwaggerGenerator.cs
  10. 4
      src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasSwaggerGenerator.cs
  11. 1
      src/Squidex/Areas/Api/Controllers/Docs/DocsController.cs
  12. 1
      src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs
  13. 52
      src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs
  14. 4
      src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs
  15. 1
      src/Squidex/Areas/Api/Controllers/Rules/TwitterController.cs
  16. 2
      src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs
  17. 1
      src/Squidex/Areas/Api/Controllers/Users/UserManagementController.cs
  18. 1
      src/Squidex/Areas/IdentityServer/Controllers/Account/AccountController.cs
  19. 1
      src/Squidex/Areas/IdentityServer/Controllers/IdentityServerController.cs
  20. 1
      src/Squidex/Areas/IdentityServer/Controllers/Profile/ProfileController.cs
  21. 6
      src/Squidex/Pipeline/ApiPermissionAttribute.cs
  22. 4
      src/Squidex/Pipeline/Swagger/NSwagHelper.cs

29
src/Squidex/Areas/Api/Config/Swagger/ScopesProcessor.cs

@ -15,6 +15,7 @@ using NSwag.SwaggerGeneration.Processors;
using NSwag.SwaggerGeneration.Processors.Contexts; using NSwag.SwaggerGeneration.Processors.Contexts;
using Squidex.Config; using Squidex.Config;
using Squidex.Infrastructure.Tasks; using Squidex.Infrastructure.Tasks;
using Squidex.Pipeline;
namespace Squidex.Areas.Api.Config.Swagger namespace Squidex.Areas.Api.Config.Swagger
{ {
@ -27,20 +28,32 @@ namespace Squidex.Areas.Api.Config.Swagger
context.OperationDescription.Operation.Security = new List<SwaggerSecurityRequirement>(); context.OperationDescription.Operation.Security = new List<SwaggerSecurityRequirement>();
} }
var authorizeAttributes = var permissionAttribute = context.MethodInfo.GetCustomAttribute<ApiPermissionAttribute>();
context.MethodInfo.GetCustomAttributes<AuthorizeAttribute>(true).Union(
context.MethodInfo.DeclaringType.GetCustomAttributes<AuthorizeAttribute>(true))
.ToArray();
if (authorizeAttributes.Any()) if (permissionAttribute != null)
{ {
var scopes = authorizeAttributes.Where(a => a.Roles != null).SelectMany(a => a.Roles.Split(',')).Distinct().ToList();
context.OperationDescription.Operation.Security.Add(new SwaggerSecurityRequirement context.OperationDescription.Operation.Security.Add(new SwaggerSecurityRequirement
{ {
{ Constants.SecurityDefinition, scopes } [Constants.SecurityDefinition] = permissionAttribute.PermissionIds
}); });
} }
else
{
var authorizeAttributes =
context.MethodInfo.GetCustomAttributes<AuthorizeAttribute>(true).Union(
context.MethodInfo.DeclaringType.GetCustomAttributes<AuthorizeAttribute>(true))
.ToArray();
if (authorizeAttributes.Any())
{
var scopes = authorizeAttributes.Where(a => a.Roles != null).SelectMany(a => a.Roles.Split(',')).Distinct().ToList();
context.OperationDescription.Operation.Security.Add(new SwaggerSecurityRequirement
{
[Constants.SecurityDefinition] = scopes
});
}
}
return TaskHelper.True; return TaskHelper.True;
} }

4
src/Squidex/Areas/Api/Config/Swagger/SecurityProcessor.cs

@ -29,7 +29,7 @@ namespace Squidex.Areas.Api.Config.Swagger
securityScheme.TokenUrl = tokenUrl; securityScheme.TokenUrl = tokenUrl;
var securityDocs = SwaggerHelper.LoadDocs("security"); var securityDocs = NSwagHelper.LoadDocs("security");
var securityText = securityDocs.Replace("<TOKEN_URL>", tokenUrl); var securityText = securityDocs.Replace("<TOKEN_URL>", tokenUrl);
securityScheme.Description = securityText; securityScheme.Description = securityText;
@ -39,7 +39,7 @@ namespace Squidex.Areas.Api.Config.Swagger
securityScheme.Scopes = new Dictionary<string, string> securityScheme.Scopes = new Dictionary<string, string>
{ {
{ Constants.ApiScope, "Read and write access to the API" } [Constants.ApiScope] = "Read and write access to the API"
}; };
return securityScheme; return securityScheme;

6
src/Squidex/Areas/Api/Config/Swagger/SwaggerExtensions.cs

@ -6,7 +6,6 @@
// ========================================================================== // ==========================================================================
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Squidex.Config;
namespace Squidex.Areas.Api.Config.Swagger namespace Squidex.Areas.Api.Config.Swagger
{ {
@ -14,10 +13,7 @@ namespace Squidex.Areas.Api.Config.Swagger
{ {
public static void UseMySwagger(this IApplicationBuilder app) public static void UseMySwagger(this IApplicationBuilder app)
{ {
app.UseSwagger(settings => app.UseSwagger();
{
settings.Path = $"{Constants.ApiPrefix}/swagger/{{documentName}}/swagger.json";
});
} }
} }
} }

3
src/Squidex/Areas/Api/Config/Swagger/SwaggerServices.cs

@ -32,6 +32,9 @@ namespace Squidex.Areas.Api.Config.Swagger
services.AddSingletonAs<XmlTagProcessor>() services.AddSingletonAs<XmlTagProcessor>()
.As<IDocumentProcessor>(); .As<IDocumentProcessor>();
services.AddSingletonAs<SecurityProcessor>()
.As<IDocumentProcessor>();
services.AddSingletonAs<ScopesProcessor>() services.AddSingletonAs<ScopesProcessor>()
.As<IOperationProcessor>(); .As<IOperationProcessor>();

7
src/Squidex/Areas/Api/Config/Swagger/XmlTagProcessor.cs

@ -8,6 +8,7 @@
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using NJsonSchema.Infrastructure; using NJsonSchema.Infrastructure;
using NSwag.Annotations; using NSwag.Annotations;
using NSwag.SwaggerGeneration.Processors; using NSwag.SwaggerGeneration.Processors;
@ -22,11 +23,11 @@ namespace Squidex.Areas.Api.Config.Swagger
{ {
foreach (var controllerType in context.ControllerTypes) foreach (var controllerType in context.ControllerTypes)
{ {
var tagAttribute = controllerType.GetTypeInfo().GetCustomAttribute<SwaggerTagAttribute>(); var attribute = controllerType.GetTypeInfo().GetCustomAttribute<ApiExplorerSettingsAttribute>();
if (tagAttribute != null) if (attribute != null)
{ {
var tag = context.Document.Tags.FirstOrDefault(x => x.Name == tagAttribute.Name); var tag = context.Document.Tags.FirstOrDefault(x => x.Name == attribute.GroupName);
if (tag != null) if (tag != null)
{ {

14
src/Squidex/Areas/Api/Controllers/Backups/RestoreController.cs

@ -20,6 +20,7 @@ namespace Squidex.Areas.Api.Controllers.Backups
/// <summary> /// <summary>
/// Restores backups. /// Restores backups.
/// </summary> /// </summary>
[ApiExplorerSettings(GroupName = nameof(Backups))]
[ApiModelValidation(true)] [ApiModelValidation(true)]
public class RestoreController : ApiController public class RestoreController : ApiController
{ {
@ -31,6 +32,12 @@ namespace Squidex.Areas.Api.Controllers.Backups
this.grainFactory = grainFactory; this.grainFactory = grainFactory;
} }
/// <summary>
/// Get current status.
/// </summary>
/// <returns>
/// 200 => Status returned.
/// </returns>
[HttpGet] [HttpGet]
[Route("apps/restore/")] [Route("apps/restore/")]
[ApiPermission(Permissions.AdminRestoreRead)] [ApiPermission(Permissions.AdminRestoreRead)]
@ -50,6 +57,13 @@ namespace Squidex.Areas.Api.Controllers.Backups
return Ok(response); return Ok(response);
} }
/// <summary>
/// Restore a backup.
/// </summary>
/// <param name="request">The backup to restore.</param>
/// <returns>
/// 204 => Restore operation started.
/// </returns>
[HttpPost] [HttpPost]
[Route("apps/restore/")] [Route("apps/restore/")]
[ApiPermission(Permissions.AdminRestoreCreate)] [ApiPermission(Permissions.AdminRestoreCreate)]

1
src/Squidex/Areas/Api/Controllers/Contents/ContentSwaggerController.cs

@ -15,6 +15,7 @@ using Squidex.Pipeline;
namespace Squidex.Areas.Api.Controllers.Contents namespace Squidex.Areas.Api.Controllers.Contents
{ {
[ApiExplorerSettings(IgnoreApi = true)]
public sealed class ContentSwaggerController : ApiController public sealed class ContentSwaggerController : ApiController
{ {
private readonly IAppProvider appProvider; private readonly IAppProvider appProvider;

2
src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs

@ -75,7 +75,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
} }
/// <summary> /// <summary>
/// GraphQL endpoint with batch support. /// GraphQL endpoint (Batch).
/// </summary> /// </summary>
/// <param name="app">The name of the app.</param> /// <param name="app">The name of the app.</param>
/// <param name="batch">The graphql queries.</param> /// <param name="batch">The graphql queries.</param>

40
src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemaSwaggerGenerator.cs

@ -10,12 +10,14 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using NJsonSchema; using NJsonSchema;
using NSwag; using NSwag;
using Squidex.Config;
using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.GenerateJsonSchema; using Squidex.Domain.Apps.Core.GenerateJsonSchema;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Pipeline.Swagger; using Squidex.Pipeline.Swagger;
using Squidex.Shared;
namespace Squidex.Areas.Api.Controllers.Contents.Generator namespace Squidex.Areas.Api.Controllers.Contents.Generator
{ {
@ -31,18 +33,20 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
private readonly string schemaName; private readonly string schemaName;
private readonly string schemaType; private readonly string schemaType;
private readonly string appPath; private readonly string appPath;
private readonly string appName;
static SchemaSwaggerGenerator() static SchemaSwaggerGenerator()
{ {
SchemaBodyDescription = SwaggerHelper.LoadDocs("schemabody"); SchemaBodyDescription = NSwagHelper.LoadDocs("schemabody");
SchemaQueryDescription = SwaggerHelper.LoadDocs("schemaquery"); SchemaQueryDescription = NSwagHelper.LoadDocs("schemaquery");
} }
public SchemaSwaggerGenerator(SwaggerDocument document, string path, Schema schema, Func<string, JsonSchema4, JsonSchema4> schemaResolver, PartitionResolver partitionResolver) public SchemaSwaggerGenerator(SwaggerDocument document, string appName, string appPath, Schema schema, Func<string, JsonSchema4, JsonSchema4> schemaResolver, PartitionResolver partitionResolver)
{ {
this.document = document; this.document = document;
appPath = path; this.appName = appName;
this.appPath = appPath;
schemaPath = schema.Name; schemaPath = schema.Name;
schemaName = schema.DisplayName(); schemaName = schema.DisplayName();
@ -97,6 +101,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.AddQueryParameter("orderby", JsonObjectType.String, "Optional OData order definition."); operation.AddQueryParameter("orderby", JsonObjectType.String, "Optional OData order definition.");
operation.AddResponse("200", $"{schemaName} content retrieved.", CreateContentsSchema(schemaName, contentSchema)); operation.AddResponse("200", $"{schemaName} content retrieved.", CreateContentsSchema(schemaName, contentSchema));
AddSecurity(operation, Permissions.AppContentsRead);
}); });
} }
@ -108,6 +114,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.Summary = $"Get a {schemaName} content."; operation.Summary = $"Get a {schemaName} content.";
operation.AddResponse("200", $"{schemaName} content found.", contentSchema); operation.AddResponse("200", $"{schemaName} content found.", contentSchema);
AddSecurity(operation, Permissions.AppContentsRead);
}); });
} }
@ -122,6 +130,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content."); operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content.");
operation.AddResponse("201", $"{schemaName} content created.", contentSchema); operation.AddResponse("201", $"{schemaName} content created.", contentSchema);
AddSecurity(operation, Permissions.AppContentsCreate);
}); });
} }
@ -135,6 +145,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription);
operation.AddResponse("200", $"{schemaName} content updated.", dataSchema); operation.AddResponse("200", $"{schemaName} content updated.", dataSchema);
AddSecurity(operation, Permissions.AppContentsUpdate);
}); });
} }
@ -148,6 +160,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription);
operation.AddResponse("200", $"{schemaName} content patched.", dataSchema); operation.AddResponse("200", $"{schemaName} content patched.", dataSchema);
AddSecurity(operation, Permissions.AppContentsUpdate);
}); });
} }
@ -159,6 +173,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.Summary = $"Publish a {schemaName} content."; operation.Summary = $"Publish a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content published."); operation.AddResponse("204", $"{schemaName} content published.");
AddSecurity(operation, Permissions.AppContentsPublish);
}); });
} }
@ -170,6 +186,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.Summary = $"Unpublish a {schemaName} content."; operation.Summary = $"Unpublish a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content unpublished."); operation.AddResponse("204", $"{schemaName} content unpublished.");
AddSecurity(operation, Permissions.AppContentsUnpublish);
}); });
} }
@ -181,6 +199,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.Summary = $"Archive a {schemaName} content."; operation.Summary = $"Archive a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content restored."); operation.AddResponse("204", $"{schemaName} content restored.");
AddSecurity(operation, Permissions.AppContentsRead);
}); });
} }
@ -192,6 +212,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.Summary = $"Restore a {schemaName} content."; operation.Summary = $"Restore a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content restored."); operation.AddResponse("204", $"{schemaName} content restored.");
AddSecurity(operation, Permissions.AppContentsRestore);
}); });
} }
@ -203,6 +225,8 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
operation.Summary = $"Delete a {schemaName} content."; operation.Summary = $"Delete a {schemaName} content.";
operation.AddResponse("204", $"{schemaName} content deleted."); operation.AddResponse("204", $"{schemaName} content deleted.");
AddSecurity(operation, Permissions.AppContentsDelete);
}); });
} }
@ -245,5 +269,13 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
return schema; return schema;
} }
private void AddSecurity(SwaggerOperation operation, string permission)
{
operation.Security.Add(new SwaggerSecurityRequirement
{
[Constants.SecurityDefinition] = new[] { Permissions.ForApp(permission, appName, schemaPath).Id }
});
}
} }
} }

4
src/Squidex/Areas/Api/Controllers/Contents/Generator/SchemasSwaggerGenerator.cs

@ -48,7 +48,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
public async Task<SwaggerDocument> Generate(HttpContext httpContext, IAppEntity app, IEnumerable<ISchemaEntity> schemas) public async Task<SwaggerDocument> Generate(HttpContext httpContext, IAppEntity app, IEnumerable<ISchemaEntity> schemas)
{ {
document = SwaggerHelper.CreateApiDocument(httpContext, urlOptions, app.Name); document = NSwagHelper.CreateApiDocument(httpContext, urlOptions, app.Name);
schemaGenerator = new SwaggerJsonSchemaGenerator(settings); schemaGenerator = new SwaggerJsonSchemaGenerator(settings);
schemaResolver = new SwaggerSchemaResolver(document, settings); schemaResolver = new SwaggerSchemaResolver(document, settings);
@ -79,7 +79,7 @@ namespace Squidex.Areas.Api.Controllers.Contents.Generator
foreach (var schema in schemas.Where(x => x.IsPublished).Select(x => x.SchemaDef)) foreach (var schema in schemas.Where(x => x.IsPublished).Select(x => x.SchemaDef))
{ {
new SchemaSwaggerGenerator(document, appBasePath, schema, AppendSchema, app.PartitionResolver()).GenerateSchemaOperations(); new SchemaSwaggerGenerator(document, app.Name, appBasePath, schema, AppendSchema, app.PartitionResolver()).GenerateSchemaOperations();
} }
} }

1
src/Squidex/Areas/Api/Controllers/Docs/DocsController.cs

@ -10,6 +10,7 @@ using Squidex.Infrastructure.Commands;
namespace Squidex.Areas.Api.Controllers.Docs namespace Squidex.Areas.Api.Controllers.Docs
{ {
[ApiExplorerSettings(IgnoreApi = true)]
public sealed class DocsController : ApiController public sealed class DocsController : ApiController
{ {
public DocsController(ICommandBus commandBus) public DocsController(ICommandBus commandBus)

1
src/Squidex/Areas/Api/Controllers/EventConsumers/EventConsumersController.cs

@ -18,6 +18,7 @@ using Squidex.Shared;
namespace Squidex.Areas.Api.Controllers.EventConsumers namespace Squidex.Areas.Api.Controllers.EventConsumers
{ {
[ApiExplorerSettings(IgnoreApi = true)]
public sealed class EventConsumersController : ApiController public sealed class EventConsumersController : ApiController
{ {
private readonly IGrainFactory grainFactory; private readonly IGrainFactory grainFactory;

52
src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NJsonSchema; using NJsonSchema;
@ -19,35 +20,44 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models
{ {
public async Task ProcessAsync(DocumentProcessorContext context) public async Task ProcessAsync(DocumentProcessorContext context)
{ {
var schema = context.SchemaResolver.GetSchema(typeof(RuleAction), false); try
if (schema != null)
{ {
var discriminator = new OpenApiDiscriminator var schema = context.SchemaResolver.GetSchema(typeof(RuleAction), false);
{
JsonInheritanceConverter = new JsonInheritanceConverter("actionType", typeof(RuleAction)), PropertyName = "actionType"
};
schema.DiscriminatorObject = discriminator;
schema.Properties["actionType"] = new JsonProperty
{
Type = JsonObjectType.String, IsRequired = true
};
foreach (var derived in RuleElementRegistry.Actions) if (schema != null)
{ {
var derivedSchema = await context.SchemaGenerator.GenerateAsync(derived.Value.Type, context.SchemaResolver); var discriminator = new OpenApiDiscriminator
{
JsonInheritanceConverter = new JsonInheritanceConverter("actionType", typeof(RuleAction)),
PropertyName = "actionType"
};
var oldName = context.Document.Definitions.FirstOrDefault(x => x.Value == derivedSchema).Key; schema.DiscriminatorObject = discriminator;
schema.Properties["actionType"] = new JsonProperty
{
Type = JsonObjectType.String,
IsRequired = true
};
if (oldName != null) foreach (var derived in RuleElementRegistry.Actions)
{ {
context.Document.Definitions.Remove(oldName); var derivedSchema = await context.SchemaGenerator.GenerateAsync(derived.Value.Type, context.SchemaResolver);
context.Document.Definitions.Add(derived.Key, derivedSchema);
var oldName = context.Document.Definitions.FirstOrDefault(x => x.Value == derivedSchema).Key;
if (oldName != null)
{
context.Document.Definitions.Remove(oldName);
context.Document.Definitions.Add(derived.Key, derivedSchema);
}
} }
}
RemoveFreezable(context, schema); RemoveFreezable(context, schema);
}
}
catch (KeyNotFoundException)
{
return;
} }
} }

4
src/Squidex/Areas/Api/Controllers/Rules/RulesController.cs

@ -250,7 +250,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
} }
/// <summary> /// <summary>
/// Enqueue the event to retry it immediate /// Retry the event immediately.
/// </summary> /// </summary>
/// <param name="app">The name of the app.</param> /// <param name="app">The name of the app.</param>
/// <param name="id">The event to enqueue.</param> /// <param name="id">The event to enqueue.</param>
@ -277,7 +277,7 @@ namespace Squidex.Areas.Api.Controllers.Rules
} }
/// <summary> /// <summary>
/// Cancels the event to not retry it again. /// Cancels the event and retries.
/// </summary> /// </summary>
/// <param name="app">The name of the app.</param> /// <param name="app">The name of the app.</param>
/// <param name="id">The event to enqueue.</param> /// <param name="id">The event to enqueue.</param>

1
src/Squidex/Areas/Api/Controllers/Rules/TwitterController.cs

@ -13,6 +13,7 @@ using static CoreTweet.OAuth;
namespace Squidex.Areas.Api.Controllers.Rules namespace Squidex.Areas.Api.Controllers.Rules
{ {
[ApiExplorerSettings(IgnoreApi = true)]
public sealed class TwitterController : Controller public sealed class TwitterController : Controller
{ {
private readonly TwitterOptions twitterOptions; private readonly TwitterOptions twitterOptions;

2
src/Squidex/Areas/Api/Controllers/Statistics/UsagesController.cs

@ -123,7 +123,7 @@ namespace Squidex.Areas.Api.Controllers.Statistics
} }
/// <summary> /// <summary>
/// Get storage usage in date range. /// Get asset usage by date.
/// </summary> /// </summary>
/// <param name="app">The name of the app.</param> /// <param name="app">The name of the app.</param>
/// <param name="fromDate">The from date.</param> /// <param name="fromDate">The from date.</param>

1
src/Squidex/Areas/Api/Controllers/Users/UserManagementController.cs

@ -21,6 +21,7 @@ using Squidex.Shared;
namespace Squidex.Areas.Api.Controllers.Users namespace Squidex.Areas.Api.Controllers.Users
{ {
[ApiModelValidation(true)] [ApiModelValidation(true)]
[ApiExplorerSettings(IgnoreApi = true)]
public sealed class UserManagementController : ApiController public sealed class UserManagementController : ApiController
{ {
private readonly UserManager<IdentityUser> userManager; private readonly UserManager<IdentityUser> userManager;

1
src/Squidex/Areas/IdentityServer/Controllers/Account/AccountController.cs

@ -29,6 +29,7 @@ using Squidex.Shared.Users;
namespace Squidex.Areas.IdentityServer.Controllers.Account namespace Squidex.Areas.IdentityServer.Controllers.Account
{ {
[ApiExplorerSettings(IgnoreApi = true)]
public sealed class AccountController : IdentityServerController public sealed class AccountController : IdentityServerController
{ {
private readonly SignInManager<IdentityUser> signInManager; private readonly SignInManager<IdentityUser> signInManager;

1
src/Squidex/Areas/IdentityServer/Controllers/IdentityServerController.cs

@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.Filters;
namespace Squidex.Areas.IdentityServer.Controllers namespace Squidex.Areas.IdentityServer.Controllers
{ {
[Area("IdentityServer")] [Area("IdentityServer")]
[ApiExplorerSettings(IgnoreApi = true)]
public abstract class IdentityServerController : Controller public abstract class IdentityServerController : Controller
{ {
public override void OnActionExecuting(ActionExecutingContext context) public override void OnActionExecuting(ActionExecutingContext context)

1
src/Squidex/Areas/IdentityServer/Controllers/Profile/ProfileController.cs

@ -26,6 +26,7 @@ using Squidex.Shared.Users;
namespace Squidex.Areas.IdentityServer.Controllers.Profile namespace Squidex.Areas.IdentityServer.Controllers.Profile
{ {
[Authorize] [Authorize]
[ApiExplorerSettings(IgnoreApi = true)]
public sealed class ProfileController : IdentityServerController public sealed class ProfileController : IdentityServerController
{ {
private readonly SignInManager<IdentityUser> signInManager; private readonly SignInManager<IdentityUser> signInManager;

6
src/Squidex/Pipeline/ApiPermissionAttribute.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license. // All rights reserved. Licensed under the MIT license.
// ========================================================================== // ==========================================================================
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
@ -21,6 +22,11 @@ namespace Squidex.Pipeline
{ {
private readonly string[] permissionIds; private readonly string[] permissionIds;
public IEnumerable<string> PermissionIds
{
get { return permissionIds; }
}
public ApiPermissionAttribute(params string[] ids) public ApiPermissionAttribute(params string[] ids)
{ {
AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme; AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme;

4
src/Squidex/Pipeline/Swagger/SwaggerHelper.cs → src/Squidex/Pipeline/Swagger/NSwagHelper.cs

@ -19,11 +19,11 @@ using Squidex.Config;
namespace Squidex.Pipeline.Swagger namespace Squidex.Pipeline.Swagger
{ {
public static class SwaggerHelper public static class NSwagHelper
{ {
public static string LoadDocs(string name) public static string LoadDocs(string name)
{ {
var assembly = typeof(SwaggerHelper).GetTypeInfo().Assembly; var assembly = typeof(NSwagHelper).GetTypeInfo().Assembly;
using (var resourceStream = assembly.GetManifestResourceStream($"Squidex.Docs.{name}.md")) using (var resourceStream = assembly.GetManifestResourceStream($"Squidex.Docs.{name}.md"))
{ {
Loading…
Cancel
Save