using Microsoft.AspNetCore.Diagnostics; namespace GameList.Infrastructure; public static class PlayerIdentityExtensions { public const string PlayerCookieName = "player"; public static IApplicationBuilder UsePlayerIdentity(this IApplicationBuilder app) { app.Use(async (ctx, next) => { var cookieOptions = new CookieOptions { HttpOnly = true, SameSite = SameSiteMode.Strict, Secure = !app.ApplicationServices.GetRequiredService().IsDevelopment(), IsEssential = true, Expires = DateTimeOffset.UtcNow.AddYears(1) }; Guid playerId; if (!ctx.Request.Cookies.TryGetValue(PlayerCookieName, out var value) || !Guid.TryParse(value, out playerId)) { playerId = Guid.NewGuid(); } ctx.Response.Cookies.Append(PlayerCookieName, playerId.ToString(), cookieOptions); ctx.Items[PlayerCookieName] = playerId; await next(); }); return app; } public static IApplicationBuilder UseGlobalExceptionLogging(this IApplicationBuilder app) { app.UseExceptionHandler(handler => { handler.Run(async context => { var feature = context.Features.Get(); var logger = context.RequestServices.GetRequiredService().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; } }