using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using KArtSell.Host.Security; using Microsoft.IdentityModel.Tokens; using Xunit; namespace KArtSell.Host.UnitTests.Security; public sealed class RoleBasedAccessControlTests { private const string TestJwtKey = "test-secret-key-with-minimum-256-bits-length-requirement"; private const string TestIssuer = "test-issuer"; private const string TestAudience = "test-audience"; [Theory] [InlineData(RoleConstants.Admin)] [InlineData(RoleConstants.SecurityOfficer)] [InlineData(RoleConstants.User)] [InlineData(RoleConstants.Viewer)] public void GenerateToken_WithValidRole_CreatesClaim(string role) { // Arrange var username = "testuser"; // Act var token = GenerateTestToken(username, role); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; // Assert var roleClaim = jwtToken?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role); Assert.NotNull(roleClaim); Assert.Equal(role, roleClaim!.Value); } [Fact] public void RoleConstants_ContainsAllExpectedRoles() { // Act & Assert Assert.Contains(RoleConstants.Admin, RoleConstants.AllRoles); Assert.Contains(RoleConstants.SecurityOfficer, RoleConstants.AllRoles); Assert.Contains(RoleConstants.User, RoleConstants.AllRoles); Assert.Contains(RoleConstants.Viewer, RoleConstants.AllRoles); Assert.Equal(4, RoleConstants.AllRoles.Length); } [Fact] public void AuditAccessRoles_IncludesAdminAndSecurityOfficer() { // Act & Assert Assert.Contains(RoleConstants.Admin, RoleConstants.AuditAccessRoles); Assert.Contains(RoleConstants.SecurityOfficer, RoleConstants.AuditAccessRoles); Assert.Equal(2, RoleConstants.AuditAccessRoles.Length); } [Theory] [InlineData(RoleConstants.Admin, true)] [InlineData(RoleConstants.SecurityOfficer, true)] [InlineData(RoleConstants.User, false)] [InlineData(RoleConstants.Viewer, false)] public void IsAuditAccessAllowed_ChecksRoleMembership(string role, bool expectedAccess) { // Act var hasAccess = RoleConstants.AuditAccessRoles.Contains(role); // Assert Assert.Equal(expectedAccess, hasAccess); } [Fact] public void ExtractRoleFromToken_ReturnsCorrectRole() { // Arrange var username = "testuser"; var expectedRole = RoleConstants.Admin; var token = GenerateTestToken(username, expectedRole); // Act var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; var actualRole = jwtToken?.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value; // Assert Assert.Equal(expectedRole, actualRole); } private static string GenerateTestToken(string username, string role) { var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TestJwtKey)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var claims = new[] { new Claim(ClaimTypes.NameIdentifier, username), new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, role), new Claim("auth_mode", "jwt") }; var token = new JwtSecurityToken( issuer: TestIssuer, audience: TestAudience, claims: claims, expires: DateTime.UtcNow.AddMinutes(60), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); } }