|  |  | 1 |  | using System.Security.Claims; | 
|  |  | 2 |  | using Microsoft.AspNetCore.Authorization; | 
|  |  | 3 |  |  | 
|  |  | 4 |  | namespace LGDXRobotCloud.API.Authorisation; | 
|  |  | 5 |  |  | 
|  | 144 | 6 |  | public class ValidateLgdxUserAccessHandler( | 
|  | 144 | 7 |  |   IHttpContextAccessor httpContextAccessor | 
|  | 144 | 8 |  | ) : AuthorizationHandler<ValidateLgdxUserAccessRequirement> | 
|  |  | 9 |  | { | 
|  | 144 | 10 |  |   private readonly HttpContext _httpContext = httpContextAccessor.HttpContext ?? throw new ArgumentException(nameof(http | 
|  |  | 11 |  |  | 
|  |  | 12 |  |   private static bool IsValidApplication(string str) | 
|  | 144 | 13 |  |   { | 
|  | 144 | 14 |  |     return string.Equals(str, "LGDXRobotCloud.API", StringComparison.CurrentCultureIgnoreCase); | 
|  | 144 | 15 |  |   } | 
|  |  | 16 |  |  | 
|  |  | 17 |  |   private bool HasAccess(string str) | 
|  | 60 | 18 |  |   { | 
|  | 60 | 19 |  |     string method = _httpContext.Request.Method; | 
|  | 60 | 20 |  |     if (string.Equals(str, "FullAccess", StringComparison.CurrentCultureIgnoreCase)) | 
|  | 12 | 21 |  |     { | 
|  |  | 22 |  |       // Has full access | 
|  | 12 | 23 |  |       return true; | 
|  |  | 24 |  |     } | 
|  | 48 | 25 |  |     if (string.Equals(str, "Read", StringComparison.CurrentCultureIgnoreCase)) | 
|  | 12 | 26 |  |     { | 
|  |  | 27 |  |       // Has read access | 
|  | 12 | 28 |  |       return string.Equals(method, "GET", StringComparison.CurrentCultureIgnoreCase); | 
|  |  | 29 |  |     } | 
|  | 36 | 30 |  |     else if (string.Equals(str, "Write", StringComparison.CurrentCultureIgnoreCase)) | 
|  | 12 | 31 |  |     { | 
|  |  | 32 |  |       // Has write access | 
|  | 12 | 33 |  |       return string.Equals(method, "POST", StringComparison.CurrentCultureIgnoreCase) || | 
|  | 12 | 34 |  |              string.Equals(method, "PUT", StringComparison.CurrentCultureIgnoreCase); | 
|  |  | 35 |  |     } | 
|  | 24 | 36 |  |     else if (string.Equals(str, "Delete", StringComparison.CurrentCultureIgnoreCase)) | 
|  | 12 | 37 |  |     { | 
|  |  | 38 |  |       // Has delete access | 
|  | 12 | 39 |  |       return string.Equals(method, "DELETE", StringComparison.CurrentCultureIgnoreCase); | 
|  |  | 40 |  |     } | 
|  | 12 | 41 |  |     return false; | 
|  | 60 | 42 |  |   } | 
|  |  | 43 |  |  | 
|  |  | 44 |  |   private bool HasAreaAccess(string str) | 
|  | 121 | 45 |  |   { | 
|  | 121 | 46 |  |     string? area = _httpContext.Request.RouteValues["area"]?.ToString(); | 
|  | 121 | 47 |  |     if (string.IsNullOrWhiteSpace(area)) | 
|  | 20 | 48 |  |     { | 
|  | 20 | 49 |  |       return false; | 
|  |  | 50 |  |     } | 
|  | 101 | 51 |  |     return string.Equals(area, str, StringComparison.CurrentCultureIgnoreCase); | 
|  | 121 | 52 |  |   } | 
|  |  | 53 |  |  | 
|  |  | 54 |  |   private bool HasControllerAccess(string str) | 
|  | 60 | 55 |  |   { | 
|  | 60 | 56 |  |     string? controller = _httpContext.Request.RouteValues["controller"]?.ToString(); | 
|  | 60 | 57 |  |     if (string.IsNullOrWhiteSpace(controller)) | 
|  | 20 | 58 |  |     { | 
|  | 20 | 59 |  |       return false; | 
|  |  | 60 |  |     } | 
|  | 40 | 61 |  |     return string.Equals(controller, str, StringComparison.CurrentCultureIgnoreCase); | 
|  | 60 | 62 |  |   } | 
|  |  | 63 |  |  | 
|  |  | 64 |  |   protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidateLgdxUserAccessRequirement  | 
|  | 144 | 65 |  |   { | 
|  | 288 | 66 |  |     List<Claim> scopes = context.User.FindAll(c => c.Type == "scope").ToList(); | 
|  |  | 67 |  |     // Extract scope | 
|  |  | 68 |  |     // format: LGDXRobotCloud.API/Area/Controller/<Access> | 
|  | 696 | 69 |  |     foreach (Claim scope in scopes) | 
|  | 144 | 70 |  |     { | 
|  | 144 | 71 |  |       var scopeSplit = scope.Value.Split("/"); | 
|  | 144 | 72 |  |       if (scopeSplit.Length == 2) | 
|  | 21 | 73 |  |       { | 
|  |  | 74 |  |         // format: LGDXRobotCloud.API/<Access> | 
|  | 21 | 75 |  |         if (IsValidApplication(scopeSplit[0]) && HasAccess(scopeSplit[1])) | 
|  | 8 | 76 |  |         { | 
|  | 8 | 77 |  |           context.Succeed(requirement); | 
|  | 8 | 78 |  |           return Task.CompletedTask; | 
|  |  | 79 |  |         } | 
|  | 13 | 80 |  |       } | 
|  | 123 | 81 |  |       else if (scopeSplit.Length == 3) | 
|  | 61 | 82 |  |       { | 
|  |  | 83 |  |         // format: LGDXRobotCloud.API/Area/<Access> | 
|  | 61 | 84 |  |         if (IsValidApplication(scopeSplit[0]) && HasAreaAccess(scopeSplit[1]) && HasAccess(scopeSplit[2])) | 
|  | 8 | 85 |  |         { | 
|  | 8 | 86 |  |           context.Succeed(requirement); | 
|  | 8 | 87 |  |           return Task.CompletedTask; | 
|  |  | 88 |  |         } | 
|  | 53 | 89 |  |       } | 
|  | 62 | 90 |  |       else if (scopeSplit.Length == 4) | 
|  | 62 | 91 |  |       { | 
|  |  | 92 |  |         // format: LGDXRobotCloud.API/Area/Controller/<Access> | 
|  | 62 | 93 |  |         if (IsValidApplication(scopeSplit[0]) && | 
|  | 62 | 94 |  |             HasAreaAccess(scopeSplit[1]) && | 
|  | 62 | 95 |  |             HasControllerAccess(scopeSplit[2]) && | 
|  | 62 | 96 |  |             HasAccess(scopeSplit[3])) | 
|  | 8 | 97 |  |         { | 
|  | 8 | 98 |  |           context.Succeed(requirement); | 
|  | 8 | 99 |  |           return Task.CompletedTask; | 
|  |  | 100 |  |         } | 
|  | 54 | 101 |  |       } | 
|  | 120 | 102 |  |     } | 
|  | 120 | 103 |  |     context.Fail(); | 
|  | 120 | 104 |  |     return Task.CompletedTask; | 
|  | 144 | 105 |  |   } | 
|  |  | 106 |  | } |