From ccad8db591129f5a9effb6469b477bb5c23ee229 Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Wed, 20 Sep 2023 11:45:46 +1000 Subject: Completed initial filter functionality --- Services/SecurityService.cs | 70 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) (limited to 'Services') diff --git a/Services/SecurityService.cs b/Services/SecurityService.cs index 9695254..c8dafd5 100644 --- a/Services/SecurityService.cs +++ b/Services/SecurityService.cs @@ -1,11 +1,13 @@ using Microsoft.EntityFrameworkCore; +using System.Data; namespace HyperBooru.Services; public class SecurityService { private IDbContextFactory dbFactory; - private Acl[] acls; + private Group[] groups; + private Acl[] acls; public SecurityService(IDbContextFactory dbFactory) { this.dbFactory = dbFactory; @@ -14,16 +16,78 @@ public class SecurityService { public void Reload() { using var db = dbFactory.CreateDbContext(); + + groups = db.Groups + .Include(g => g.MemberOf) + .ToArray(); + acls = db.Acls .Include(a => a.Rules) .ThenInclude(r => r.Principal) .ToArray(); } - public IEnumerable Filter(IEnumerable objects, ulong permissions) { + public IEnumerable Filter( + IEnumerable objects, + HBPrincipal principal, + ulong permissions) { + foreach(var obj in objects) { + var perms = GetPermissions(obj.Acl, principal); + if((perms & permissions) == permissions) + yield return obj; + } + } + + public IEnumerable Filter( + IEnumerable objects, + HBPrincipal principal, + T permissions) where T : Enum => + Filter(objects, principal, permissions); + + private ulong GetPermissions(Acl? acl, HBPrincipal principal) { + if(acl is null) + return ulong.MaxValue; + + bool hasAllowRules = acl.Rules + .Any(r => r.Action == AclRuleAction.Allow); + + ulong permissions = hasAllowRules ? 0 : ulong.MaxValue; + + var principals = GetGroupMemberShip(principal) + .Cast() + .Concat(new[] { principal }) + .ToArray(); + + acl.Rules.IntersectBy(principals, r => r.Principal); + + foreach(var rule in acl.Rules) { + if(!principals.Contains(rule.Principal)) + continue; + + if(rule.Action == AclRuleAction.Allow) + permissions |= rule.Permissions; + else + permissions &= ~rule.Permissions; + } + + return permissions; + } + + private List GetGroupMemberShip(HBPrincipal principal) { + var groups = principal.MemberOf.ToList(); + + while(true) { + var toAdd = this.groups + .Where(g => !groups.Contains(g)) + .ToArray(); + + if(toAdd.Count() == 0) + break; + + groups.AddRange(toAdd); } - return Enumerable.Empty(); + return groups; } } -- cgit v1.3