namespace SharepointToolbox.Core.Models; /// /// Summary counts of permission entries grouped by risk level. /// Displayed in the summary panel when simplified mode is active. /// public record PermissionSummary( /// Label for this group (e.g. "High Risk", "Read Only"). string Label, /// The risk level this group represents. RiskLevel RiskLevel, /// Number of permission entries at this risk level. int Count, /// Number of distinct users at this risk level. int DistinctUsers ); /// /// Computes PermissionSummary groups from SimplifiedPermissionEntry collections. /// public static class PermissionSummaryBuilder { /// /// Risk level display labels. /// private static readonly Dictionary Labels = new() { [RiskLevel.High] = "High Risk", [RiskLevel.Medium] = "Medium Risk", [RiskLevel.Low] = "Low Risk", [RiskLevel.ReadOnly] = "Read Only", }; /// /// Builds summary counts grouped by risk level from a collection of simplified entries. /// Always returns all 4 risk levels, even if count is 0, for consistent UI binding. /// public static IReadOnlyList Build( IEnumerable entries) { var grouped = entries .GroupBy(e => e.RiskLevel) .ToDictionary(g => g.Key, g => g.ToList()); return Enum.GetValues() .Select(level => { var items = grouped.GetValueOrDefault(level, new List()); var distinctUsers = items .SelectMany(e => e.UserLogins.Split(';', StringSplitOptions.RemoveEmptyEntries)) .Select(u => u.Trim()) .Where(u => u.Length > 0) .Distinct(StringComparer.OrdinalIgnoreCase) .Count(); return new PermissionSummary( Label: Labels[level], RiskLevel: level, Count: items.Count, DistinctUsers: distinctUsers); }) .ToList(); } }