using Microsoft.EntityFrameworkCore; using ZB.MOM.WW.OtOpcUa.Configuration.Entities; namespace ZB.MOM.WW.OtOpcUa.Configuration.Services; /// /// EF Core implementation of . Enforces the /// "exactly one of (ClusterId, IsSystemWide)" invariant at the write surface so a /// malformed row can't land in the DB. /// public sealed class LdapGroupRoleMappingService(OtOpcUaConfigDbContext db) : ILdapGroupRoleMappingService { public async Task> GetByGroupsAsync( IEnumerable ldapGroups, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(ldapGroups); var groupSet = ldapGroups.ToList(); if (groupSet.Count == 0) return []; return await db.LdapGroupRoleMappings .AsNoTracking() .Where(m => groupSet.Contains(m.LdapGroup)) .ToListAsync(cancellationToken) .ConfigureAwait(false); } public async Task> ListAllAsync(CancellationToken cancellationToken) => await db.LdapGroupRoleMappings .AsNoTracking() .OrderBy(m => m.LdapGroup) .ThenBy(m => m.ClusterId) .ToListAsync(cancellationToken) .ConfigureAwait(false); public async Task CreateAsync(LdapGroupRoleMapping row, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(row); ValidateInvariants(row); if (row.Id == Guid.Empty) row.Id = Guid.NewGuid(); if (row.CreatedAtUtc == default) row.CreatedAtUtc = DateTime.UtcNow; db.LdapGroupRoleMappings.Add(row); await db.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return row; } public async Task DeleteAsync(Guid id, CancellationToken cancellationToken) { var existing = await db.LdapGroupRoleMappings.FindAsync([id], cancellationToken).ConfigureAwait(false); if (existing is null) return; db.LdapGroupRoleMappings.Remove(existing); await db.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } private static void ValidateInvariants(LdapGroupRoleMapping row) { if (string.IsNullOrWhiteSpace(row.LdapGroup)) throw new InvalidLdapGroupRoleMappingException("LdapGroup must not be empty."); if (row.IsSystemWide && !string.IsNullOrEmpty(row.ClusterId)) throw new InvalidLdapGroupRoleMappingException( "IsSystemWide=true requires ClusterId to be null. A fleet-wide grant cannot also be cluster-scoped."); if (!row.IsSystemWide && string.IsNullOrEmpty(row.ClusterId)) throw new InvalidLdapGroupRoleMappingException( "IsSystemWide=false requires a populated ClusterId. A cluster-scoped grant needs its target cluster."); } }