From f1390eaa1c45e9128b07cb55d6e4a8a5a175c140 Mon Sep 17 00:00:00 2001 From: Dev Date: Tue, 7 Apr 2026 14:06:17 +0200 Subject: [PATCH] feat(08-01): add RiskLevel enum and PermissionLevelMapping helper - RiskLevel enum with High, Medium, Low, ReadOnly tiers - PermissionLevelMapping maps 11 standard SharePoint roles to plain-language labels - Case-insensitive lookup with Medium fallback for unknown roles - GetHighestRisk and GetSimplifiedLabels for row-level formatting Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Core/Helpers/PermissionLevelMapping.cs | 95 +++++++++++++++++++ SharepointToolbox/Core/Models/RiskLevel.cs | 17 ++++ 2 files changed, 112 insertions(+) create mode 100644 SharepointToolbox/Core/Helpers/PermissionLevelMapping.cs create mode 100644 SharepointToolbox/Core/Models/RiskLevel.cs diff --git a/SharepointToolbox/Core/Helpers/PermissionLevelMapping.cs b/SharepointToolbox/Core/Helpers/PermissionLevelMapping.cs new file mode 100644 index 0000000..bc296fb --- /dev/null +++ b/SharepointToolbox/Core/Helpers/PermissionLevelMapping.cs @@ -0,0 +1,95 @@ +using SharepointToolbox.Core.Models; + +namespace SharepointToolbox.Core.Helpers; + +/// +/// Maps SharePoint built-in permission level names to human-readable labels and risk levels. +/// Used by SimplifiedPermissionEntry and export services to translate raw role names +/// into plain-language descriptions that non-technical users can understand. +/// +public static class PermissionLevelMapping +{ + /// + /// Result of looking up a SharePoint role name. + /// + public record MappingResult(string Label, RiskLevel RiskLevel); + + /// + /// Known SharePoint built-in permission level mappings. + /// Keys are case-insensitive via the dictionary comparer. + /// + private static readonly Dictionary Mappings = new(StringComparer.OrdinalIgnoreCase) + { + // High risk — full administrative access + ["Full Control"] = new("Full control (can manage everything)", RiskLevel.High), + ["Site Collection Administrator"] = new("Site collection admin (full control)", RiskLevel.High), + + // Medium risk — can modify content + ["Contribute"] = new("Can edit files and list items", RiskLevel.Medium), + ["Edit"] = new("Can edit files, lists, and pages", RiskLevel.Medium), + ["Design"] = new("Can edit pages and use design tools", RiskLevel.Medium), + ["Approve"] = new("Can approve content and list items", RiskLevel.Medium), + ["Manage Hierarchy"] = new("Can create sites and manage pages", RiskLevel.Medium), + + // Low risk — read access + ["Read"] = new("Can view files and pages", RiskLevel.Low), + ["Restricted Read"] = new("Can view pages only (no download)", RiskLevel.Low), + + // Read-only — most restricted + ["View Only"] = new("Can view files in browser only", RiskLevel.ReadOnly), + ["Restricted View"] = new("Restricted view access", RiskLevel.ReadOnly), + }; + + /// + /// Gets the human-readable label and risk level for a SharePoint role name. + /// Returns the mapped result for known roles; for unknown/custom roles, + /// returns the raw name as-is with Medium risk level. + /// + public static MappingResult GetMapping(string roleName) + { + if (string.IsNullOrWhiteSpace(roleName)) + return new MappingResult(roleName, RiskLevel.Low); + + return Mappings.TryGetValue(roleName.Trim(), out var result) + ? result + : new MappingResult(roleName.Trim(), RiskLevel.Medium); + } + + /// + /// Resolves a semicolon-delimited PermissionLevels string into individual mapping results. + /// This handles the PermissionEntry.PermissionLevels format (e.g. "Full Control; Contribute"). + /// + public static IReadOnlyList GetMappings(string permissionLevels) + { + if (string.IsNullOrWhiteSpace(permissionLevels)) + return Array.Empty(); + + return permissionLevels + .Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(GetMapping) + .ToList(); + } + + /// + /// Returns the highest (most dangerous) risk level from a semicolon-delimited permission levels string. + /// Used for row-level color coding when an entry has multiple roles. + /// + public static RiskLevel GetHighestRisk(string permissionLevels) + { + var mappings = GetMappings(permissionLevels); + if (mappings.Count == 0) return RiskLevel.Low; + + // High < Medium < Low < ReadOnly in enum order — Min gives highest risk + return mappings.Min(m => m.RiskLevel); + } + + /// + /// Converts a semicolon-delimited PermissionLevels string into a simplified labels string. + /// E.g. "Full Control; Contribute" becomes "Full control (can manage everything); Can edit files and list items" + /// + public static string GetSimplifiedLabels(string permissionLevels) + { + var mappings = GetMappings(permissionLevels); + return string.Join("; ", mappings.Select(m => m.Label)); + } +} diff --git a/SharepointToolbox/Core/Models/RiskLevel.cs b/SharepointToolbox/Core/Models/RiskLevel.cs new file mode 100644 index 0000000..78b4022 --- /dev/null +++ b/SharepointToolbox/Core/Models/RiskLevel.cs @@ -0,0 +1,17 @@ +namespace SharepointToolbox.Core.Models; + +/// +/// Classifies a SharePoint permission level by its access risk. +/// Used for color coding in both WPF DataGrid and HTML export. +/// +public enum RiskLevel +{ + /// Full Control, Site Collection Administrator — can delete site, manage permissions. + High, + /// Contribute, Edit, Design — can modify content. + Medium, + /// Read, Restricted View — can view but not modify. + Low, + /// View Only — most restricted legitimate access. + ReadOnly +}