Phase 1 WP-2–10: Repositories, audit service, security & auth (LDAP, JWT, roles, policies, data protection)
- WP-2: SecurityRepository + CentralUiRepository with audit log queries - WP-3: AuditService with transactional guarantee (same SaveChangesAsync) - WP-4: Optimistic concurrency tests (deployment records vs template last-write-wins) - WP-5: Seed data (SCADA-Admins → Admin role mapping) - WP-6: LdapAuthService (direct bind, TLS enforcement, group query) - WP-7: JwtTokenService (HMAC-SHA256, 15-min refresh, 30-min idle timeout) - WP-8: RoleMapper (LDAP groups → roles with site-scoped deployment) - WP-9: Authorization policies (Admin/Design/Deployment + site scope handler) - WP-10: Shared Data Protection keys via EF Core 141 tests pass, zero warnings.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
using ScadaLink.Commons.Interfaces.Repositories;
|
||||
|
||||
namespace ScadaLink.Security;
|
||||
|
||||
public class RoleMapper
|
||||
{
|
||||
private readonly ISecurityRepository _securityRepository;
|
||||
|
||||
public RoleMapper(ISecurityRepository securityRepository)
|
||||
{
|
||||
_securityRepository = securityRepository ?? throw new ArgumentNullException(nameof(securityRepository));
|
||||
}
|
||||
|
||||
public async Task<RoleMappingResult> MapGroupsToRolesAsync(
|
||||
IReadOnlyList<string> ldapGroups,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var allMappings = await _securityRepository.GetAllMappingsAsync(ct);
|
||||
|
||||
var matchedRoles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
var permittedSiteIds = new HashSet<string>();
|
||||
var hasDeploymentRole = false;
|
||||
var hasDeploymentWithScopeRules = false;
|
||||
|
||||
foreach (var mapping in allMappings)
|
||||
{
|
||||
// Match LDAP group names (case-insensitive)
|
||||
if (!ldapGroups.Any(g => g.Equals(mapping.LdapGroupName, StringComparison.OrdinalIgnoreCase)))
|
||||
continue;
|
||||
|
||||
matchedRoles.Add(mapping.Role);
|
||||
|
||||
if (mapping.Role.Equals("Deployment", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
hasDeploymentRole = true;
|
||||
|
||||
// Check for site scope rules
|
||||
var scopeRules = await _securityRepository.GetScopeRulesForMappingAsync(mapping.Id, ct);
|
||||
if (scopeRules.Count > 0)
|
||||
{
|
||||
hasDeploymentWithScopeRules = true;
|
||||
foreach (var rule in scopeRules)
|
||||
{
|
||||
permittedSiteIds.Add(rule.SiteId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// System-wide deployment: user has Deployment role but no site scope rules restrict them
|
||||
var isSystemWide = hasDeploymentRole && !hasDeploymentWithScopeRules;
|
||||
|
||||
return new RoleMappingResult(
|
||||
matchedRoles.ToList(),
|
||||
permittedSiteIds.ToList(),
|
||||
isSystemWide);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user