diff --git a/Badge/Badge.csproj b/Badge/Badge.csproj index 88b487a..6a44431 100644 --- a/Badge/Badge.csproj +++ b/Badge/Badge.csproj @@ -9,14 +9,12 @@ true true Linux - partial - false - + diff --git a/Badge/Controllers/OAuthController.cs b/Badge/Controllers/OAuthController.cs index 434149d..0230877 100644 --- a/Badge/Controllers/OAuthController.cs +++ b/Badge/Controllers/OAuthController.cs @@ -9,6 +9,7 @@ using Net.Sdk.Web; using System.Core.Extensions; using System.Diagnostics.CodeAnalysis; using System.Extensions; +using System.Runtime.CompilerServices; namespace Badge.Controllers; @@ -55,6 +56,7 @@ public sealed class OAuthController } [GeneratePost("token")] + [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining | MethodImplOptions.PreserveSig)] public async Task GetOAuthToken( HttpContext httpContext, CancellationToken cancellationToken) diff --git a/Badge/Dockerfile b/Badge/Dockerfile index 99beb5a..38b0a15 100644 --- a/Badge/Dockerfile +++ b/Badge/Dockerfile @@ -13,6 +13,7 @@ RUN dotnet restore RUN dotnet clean RUN dotnet build -c $BUILD_CONFIGURATION -o /app/build RUN dotnet publish Badge.csproj -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=true -v detailed +RUN dotnet --info >> /app/publish/dotnet.info FROM mcr.microsoft.com/dotnet/runtime-deps:8.0 AS final ENV ASPNETCORE_ENVIRONMENT=Production diff --git a/Badge/Program.cs b/Badge/Program.cs index 98e2261..fec2e81 100644 --- a/Badge/Program.cs +++ b/Badge/Program.cs @@ -1,9 +1,10 @@ using Badge.Controllers; +using Badge.Controllers.Models; using Badge.Extensions; -using Badge.Options; -using Microsoft.Extensions.Options; +using Badge.Filters; +using Badge.Models; +using Microsoft.AspNetCore.Mvc; using Net.Sdk.Web; -using Net.Sdk.Web.Options; using Net.Sdk.Web.Websockets.Extensions; using System.Runtime.CompilerServices; @@ -46,16 +47,136 @@ namespace Badge .UseWwwRoot() .UseAntiforgeryMiddleware() .UseUserAuthentication() - .UseHealthChecks() - .UseRoutes(); - - app.MapPost("/test", async (HttpContext context, OAuthController route) => - { - var cancellationToken = context.RequestAborted; - return await route.GetOAuthToken(context, cancellationToken); - }); + .UseHealthChecks(); + //.UseRoutes(); //This call doesn't work. When built with NativeAOT, some of the mappings don't await but instead they return and try to serialize Task + UseRoutes2(app); //This is a copy of UseRoutes and placed below. This works for some reason and the mapping always await and never try to serialize Task app.Run(); } + + // Identical copy of UseRoutes + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization | MethodImplOptions.PreserveSig)] + public static WebApplication UseRoutes2(WebApplication builder) + { + builder.MapPost("/api/users/login", (HttpContext httpContext, UsersController route, [FromBody] UsernameWithPassword payload) => + { + var cancellationToken = httpContext.RequestAborted; + return route.Login(payload, httpContext, cancellationToken); + }); + builder.MapPost("/api/users/create", (HttpContext httpContext, UsersController route, [FromBody] UsernameWithPassword payload) => + { + var cancellationToken = httpContext.RequestAborted; + return route.Create(payload, httpContext, cancellationToken); + }); + builder.MapGet("/api/users/me", (HttpContext httpContext, UsersController route, [FromServices] AuthenticatedUser authenticatedUser) => + { + var cancellationToken = httpContext.RequestAborted; + return route.Me(authenticatedUser); + }) + .AddEndpointFilter(); + builder.MapGet("/api/applications/{applicationId}/redirect-uris/", (HttpContext httpContext, RedirectUriController route, [FromServices] AuthenticatedUser authenticatedUser, string applicationId) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetRedirectUris(authenticatedUser, applicationId, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapPost("/api/applications/{applicationId}/redirect-uris/", (HttpContext httpContext, RedirectUriController route, [FromServices] AuthenticatedUser authenticatedUser, string applicationId, [FromBody] List redirectUris) => + { + var cancellationToken = httpContext.RequestAborted; + return route.PostRedirectUris(authenticatedUser, applicationId, redirectUris, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapGet("/api/applications/{applicationId}/secrets/", (HttpContext httpContext, ClientSecretController route, string applicationId, [FromServices] AuthenticatedUser authenticatedUser) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetClientSecrets(applicationId, authenticatedUser, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapPost("/api/applications/{applicationId}/secrets/", (HttpContext httpContext, ClientSecretController route, string applicationId, [FromServices] AuthenticatedUser authenticatedUser) => + { + var cancellationToken = httpContext.RequestAborted; + return route.CreateClientSecret(applicationId, authenticatedUser, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapDelete("/api/applications/{applicationId}/secrets/{clientSecretId}", (HttpContext httpContext, ClientSecretController route, string applicationId, [FromServices] AuthenticatedUser authenticatedUser, string clientSecretId) => + { + var cancellationToken = httpContext.RequestAborted; + return route.DeleteClientSecret(applicationId, authenticatedUser, clientSecretId, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapPost("/api/applications/{applicationId}/secrets/{clientSecretId}/detail", (HttpContext httpContext, ClientSecretController route, string applicationId, [FromServices] AuthenticatedUser authenticatedUser, string clientSecretId, [FromBody] UpdateClientSecretDetailRequest? request) => + { + var cancellationToken = httpContext.RequestAborted; + return route.UpdateClientSecretDetail(applicationId, authenticatedUser, clientSecretId, request, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapGet("/api/applications/me", (HttpContext httpContext, ApplicationController route, [FromServices] AuthenticatedUser authenticatedUser) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetApplications(authenticatedUser, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapGet("/api/applications/{applicationId}/info", (HttpContext httpContext, ApplicationController route, string applicationId) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetApplicationInfo(applicationId, cancellationToken); + }); + builder.MapGet("/api/applications/{applicationId}", (HttpContext httpContext, ApplicationController route, string applicationId, [FromServices] AuthenticatedUser authenticatedUser) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetApplication(applicationId, authenticatedUser, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapPost("/api/applications/create", (HttpContext httpContext, ApplicationController route, [FromBody] CreateApplicationRequest createApplicationRequest, [FromServices] AuthenticatedUser authenticatedUser) => + { + var cancellationToken = httpContext.RequestAborted; + return route.CreateApplication(createApplicationRequest, authenticatedUser, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapPost("/api/applications/{applicationId}/scopes", (HttpContext httpContext, ApplicationController route, [FromBody] UpdateApplicationScopesRequest updateApplicationScopesRequest, [FromServices] AuthenticatedUser authenticatedUser, string applicationId) => + { + var cancellationToken = httpContext.RequestAborted; + return route.UpdateApplicationScopes(updateApplicationScopesRequest, authenticatedUser, applicationId, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapGet("/api/status/", (HttpContext httpContext, StatusController route) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetStatus(); + }); + builder.MapGet("/api/oauth/.well-known/openid-configuration", (HttpContext httpContext, OAuthController route) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetDiscoveryDocument(); + }); + builder.MapGet("/api/oauth/.well-known/jwks.json", (HttpContext httpContext, OAuthController route) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetJwks(cancellationToken); + }); + builder.MapGet("/api/oauth/userinfo", (HttpContext httpContext, OAuthController route) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetUserInfo(httpContext, cancellationToken); + }) + .AddEndpointFilter(); + builder.MapPost("/api/oauth/token", (HttpContext httpContext, OAuthController route) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetOAuthToken(httpContext, cancellationToken); + }); + builder.MapGet("/api/oauth/scopes", (HttpContext httpContext, OAuthController route) => + { + var cancellationToken = httpContext.RequestAborted; + return route.GetOauthScopes(); + }); + builder.MapPost("/api/oauth/authorize", (HttpContext httpContext, OAuthController route, [FromServices] AuthenticatedUser authenticatedUser, [FromBody] AuthorizeRequest request) => + { + var cancellationToken = httpContext.RequestAborted; + return route.Authorize(authenticatedUser, request, cancellationToken); + }) + .AddEndpointFilter(); + return builder; + } } } diff --git a/Badge/SerializationContext.cs b/Badge/SerializationContext.cs index aad4c2b..8617c38 100644 --- a/Badge/SerializationContext.cs +++ b/Badge/SerializationContext.cs @@ -33,7 +33,6 @@ namespace Badge; [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(OAuthResponse))] [JsonSerializable(typeof(UserInfoResponse))] -[JsonSerializable(typeof(Task))] public partial class SerializationContext : JsonSerializerContext { } diff --git a/Badge/linker.xml b/Badge/linker.xml deleted file mode 100644 index 52139d6..0000000 --- a/Badge/linker.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - -