using FluentAssertions; using Microsoft.Extensions.Configuration; using NSubstitute; using ProposalSystem.Api.Controllers; using ProposalSystem.Domain.Entities; using ProposalSystem.Tests.Helpers; using Xunit; namespace ProposalSystem.Tests.Controllers; public class AuthControllerRoleSyncTests { [Fact(DisplayName = "SEC-29: Cognito role sync logs user id, not email")] public async Task RoleChange_LogsUserIdNotEmail() { var email = "pii@example.com"; var user = new User { Id = Guid.NewGuid(), CognitoSub = "sub-role-sync", Email = email, DisplayName = "Test User", Role = UserRole.Dispatcher, IsActive = true, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow, }; var (controller, db, logger) = CreateController(user); var synced = await controller.SyncCognitoUserAsync( user.CognitoSub, email, user.DisplayName, UserRole.Admin, CancellationToken.None); synced.Id.Should().Be(user.Id); synced.Email.Should().Be(email); synced.Role.Should().Be(UserRole.Admin); logger.Messages.Should().ContainSingle(); logger.Messages[0].Should().Contain(user.Id.ToString()); logger.Messages[0].Should().NotContain(email); logger.Messages[0].Should().Contain(UserRole.Dispatcher.ToString()); logger.Messages[0].Should().Contain(UserRole.Admin.ToString()); db.Dispose(); } [Fact(DisplayName = "SEC-29: Cognito role sync does not log when role is unchanged")] public async Task UnchangedRole_DoesNotLog() { var user = new User { Id = Guid.NewGuid(), CognitoSub = "sub-unchanged", Email = "pii@example.com", DisplayName = "Test User", Role = UserRole.Admin, IsActive = true, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow, }; var (controller, db, logger) = CreateController(user); await controller.SyncCognitoUserAsync( user.CognitoSub, user.Email, user.DisplayName, UserRole.Admin, CancellationToken.None); logger.Messages.Should().BeEmpty(); db.Dispose(); } private static (AuthController Controller, Infrastructure.Data.ProposalDbContext Db, CapturingLogger Logger) CreateController(User seed) { var db = DbContextFactory.Create(); db.Users.Add(seed); db.SaveChanges(); var logger = new CapturingLogger(); var controller = new AuthController( db, Substitute.For(), new ConfigurationBuilder().Build(), logger); return (controller, db, logger); } }