Files
GameList/Infrastructure/PlayerIdentityExtensions.cs
2026-02-05 20:39:12 +01:00

59 lines
2.2 KiB
C#

using System.Security.Claims;
using GameList.Domain;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Diagnostics;
namespace GameList.Infrastructure;
public static class PlayerIdentityExtensions
{
public const string PlayerCookieName = "player";
public const string AdminClaim = "is_admin";
public const string AdminPolicy = "AdminOnly";
public static async Task SignInPlayerAsync(HttpContext ctx, Player player)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, player.Id.ToString()),
new Claim(ClaimTypes.Name, player.Username),
new Claim(AdminClaim, player.IsAdmin ? "true" : "false")
};
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await ctx.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
}
public static Task SignOutPlayerAsync(HttpContext ctx) => ctx.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
public static IApplicationBuilder UseGlobalExceptionLogging(this IApplicationBuilder app)
{
app.UseExceptionHandler(handler =>
{
handler.Run(async context =>
{
var feature = context.Features.Get<IExceptionHandlerFeature>();
var logger = context.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger("GlobalException");
if (feature?.Error != null)
{
logger.LogError(feature.Error, "Unhandled exception");
}
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
context.Response.ContentType = "application/json";
await context.Response.WriteAsJsonAsync(new { error = "Unexpected server error" });
});
});
return app;
}
public static IEndpointRouteBuilder MapHealthChecks(this IEndpointRouteBuilder endpoints)
{
endpoints.MapGet("/health", () => Results.Ok(new { status = "ok" }));
return endpoints;
}
}