using System.Security.Claims; using Microsoft.AspNetCore.Http; namespace SpaceGame.Api.Auth.Simulation; public sealed class HttpContextPlayerIdentityResolver(IHttpContextAccessor httpContextAccessor) : IPlayerIdentityResolver { public const string EffectivePlayerHeaderName = "X-Act-As-Player-Id"; public Guid? GetCurrentPlayerId() { var subject = httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier) ?? httpContextAccessor.HttpContext?.User.FindFirstValue("sub"); return Guid.TryParse(subject, out var playerId) ? playerId : null; } public Guid GetRequiredPlayerId() => GetCurrentPlayerId() ?? throw new InvalidOperationException("Authenticated player identity is required."); public Guid? GetEffectivePlayerId() { var currentPlayerId = GetCurrentPlayerId(); if (!CanAccessGm()) { return currentPlayerId; } var requestedIdentity = httpContextAccessor.HttpContext?.Request.Headers[EffectivePlayerHeaderName].FirstOrDefault(); return Guid.TryParse(requestedIdentity, out var effectivePlayerId) ? effectivePlayerId : currentPlayerId; } public Guid GetRequiredEffectivePlayerId() => GetEffectivePlayerId() ?? throw new InvalidOperationException("Authenticated player identity is required."); public bool CanAccessGm() { var user = httpContextAccessor.HttpContext?.User; return user?.IsInRole("gm") == true || user?.IsInRole("admin") == true; } }