using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace MoShiro.Backend.Api;
public static class EndpointConventions
{
/// 每个端点都必须有 operationId(snake_case,资源_动作)、summary 和 tag。
public static RouteHandlerBuilder Api(this RouteHandlerBuilder builder, string operationId, string summary, string tag) =>
builder.WithName(operationId).WithSummary(summary).WithTags(tag);
/// 声明端点需要的能力(授权的唯一依据);OpenAPI 里带上 x-moshiro-capability。
public static RouteHandlerBuilder Requires(this RouteHandlerBuilder builder, string capability) =>
builder.WithMetadata(new CapabilityRequirement(capability)).AddOpenApiOperationTransformer((operation, _, _) =>
{
operation.Extensions ??= new Dictionary();
operation.Extensions["x-moshiro-capability"] = new Microsoft.OpenApi.JsonNodeExtension(System.Text.Json.Nodes.JsonValue.Create(capability));
return Task.CompletedTask;
});
/// 匿名可访问的管理端点(登录):显式声明,对账测试才能区分「忘了声明」。
public static RouteHandlerBuilder AllowsAnonymous(this RouteHandlerBuilder builder) =>
builder.WithMetadata(new CapabilityRequirement(null));
public static RouteHandlerBuilder Returns(this RouteHandlerBuilder builder, int status = StatusCodes.Status200OK) =>
builder.Produces(status);
/// 登记该端点可能返回的错误状态(problem+json),让 OpenAPI 文档完整。
public static RouteHandlerBuilder ProducesProblems(this RouteHandlerBuilder builder, params int[] statuses)
{
foreach (int status in statuses)
{
builder.Produces(status, Problems.ContentType);
}
return builder;
}
}