From 299e58db28202be8706dee1c570c382e1489213b Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Mon, 9 Oct 2023 16:00:18 +1100 Subject: AclDialog --- Pages/Component/AclDialog.razor | 114 ++++++++++++++------------ Pages/Component/AclDialog.razor.css | 19 ----- Pages/Component/MiniPrincipalSelect.razor | 44 ++++++++++ Pages/Component/MiniPrincipalSelect.razor.css | 18 ++++ 4 files changed, 124 insertions(+), 71 deletions(-) create mode 100644 Pages/Component/MiniPrincipalSelect.razor create mode 100644 Pages/Component/MiniPrincipalSelect.razor.css (limited to 'Pages') diff --git a/Pages/Component/AclDialog.razor b/Pages/Component/AclDialog.razor index 0d24530..691e984 100644 --- a/Pages/Component/AclDialog.razor +++ b/Pages/Component/AclDialog.razor @@ -1,5 +1,5 @@ @using System.Numerics; -@inject IDbContextFactory dbFactory; +@inject HBContext db @implements IDialog @@ -7,19 +7,7 @@
@if(obj?.Acl is not null) { -
- @if(editOwner is not null) { - - - - - } else { - - editOwner = obj.Owner.ToString())> - @obj.Owner.ToString() - - } -
+ @@ -28,7 +16,13 @@ @foreach(var rule in obj.Acl.Rules.OrderByDescending(r => r.Action)) { - + @@ -42,30 +36,12 @@
Action
+
+ rule.Action = v ? AclRuleAction.Allow : AclRuleAction.Deny)/> +
+
@rule.Principal.ToString()

Add new
- } else { -

This item does not have any permissions set!

}
@if(ruleToEdit is not null && permissionCheckboxes is not null) { -
- @if(editSubject is not null) { - - - - - } else { - - editSubject = ruleToEdit.Principal.ToString())> - @if(ruleToEdit.Principal == WellKnownSid.NullSid) { - Select a user or group - } else { - @ruleToEdit.Principal.ToString() - } - - } -
- var permissions = Acl.GetPermissionDescriptions(obj!) + + var permissions = Acl.GetPermissionDescriptions(obj) .OrderByDescending(kv => BitOperations.PopCount(kv.Value)) .ThenBy(kv => kv.Value); foreach(var perm in permissionCheckboxes) { @@ -84,7 +60,9 @@ @if(obj?.Acl is not null) { - + }
@@ -94,16 +72,22 @@ public bool Visible { get => dialog.Visible; set { + if(value && obj is null) + throw new ArgumentException("Object must not be null!", "Object"); + dialog.Visible = value; if(value) StateHasChanged(); } } - private HBObject? obj; + private HBObject obj; private AclRule? ruleToEdit; private PermissionCheckbox[]? permissionCheckboxes; + private int lastHashCode; + private bool addedAcl; + private string? editOwner; private string? editSubject; @@ -117,32 +101,42 @@ Show(); } - public HBObject? Object { + public HBObject Object { get => obj; set { editOwner = null; CancelEditRule(); - if(value is null) { - obj = null; - return; - } - - using var db = dbFactory.CreateDbContext(); - obj = db.Objects .Include(o => o.Acl) .First(o => o.ObjectId == value.ObjectId); - if(obj.Acl is not null) + if (obj.Acl is not null) { db.Entry(obj.Acl).Collection(a => a.Rules).Load(); + addedAcl = false; + } else { + obj.Acl = new() { + Rules = new() + }; + addedAcl = true; + } + + lastHashCode = GetAclHashCode(obj.Acl); } } + public bool ApplyDisabled => + #if DEBUG + false; + #else + GetAclHashCode(obj.Acl!) == lastHashCode || + obj.Acl!.Rules.Select(r => r.Principal).Contains(WellKnownSid.NullSid); + #endif + private string GetActivePermissions(AclRule rule) { - var perms = Acl.GetPermissionDescriptions(obj!) - .Where(kv => (rule.Permissions & kv.Value) == kv.Value) - .ToList(); + var perms = Acl.GetPermissionDescriptions(obj) + .Where(kv => (rule.Permissions & kv.Value) == kv.Value) + .ToList(); // Filter the list of matching permissions to include the // most relevant encapsulation permissions only. E.g. if @@ -164,6 +158,11 @@ .Select(kv => kv.Key)); } + private void ApplyAcl() { + db.SaveChanges(); + Hide(); + } + private void AddRule() { var rule = new AclRule() { Principal = WellKnownSid.NullSid, @@ -171,20 +170,20 @@ Permissions = 0 }; - obj!.Acl!.Rules.Add(rule); + obj.Acl!.Rules.Add(rule); EditRule(rule); } private void RemoveRule(AclRule rule) { if(rule == ruleToEdit) CancelEditRule(); - obj!.Acl!.Rules.Remove(rule); + obj.Acl!.Rules.Remove(rule); } private void EditRule(AclRule rule) { ruleToEdit = rule; editSubject = null; - permissionCheckboxes = Acl.GetPermissionDescriptions(obj!) + permissionCheckboxes = Acl.GetPermissionDescriptions(obj) .OrderByDescending(kv => BitOperations.PopCount(kv.Value)) .ThenBy(kv => kv.Value) .Select(kv => new PermissionCheckbox(rule, kv)) @@ -196,6 +195,17 @@ permissionCheckboxes = null; } + // Special hash function to identify only the elements of + // the ACL that may have been changed by the user via this + // dialog. + private int GetAclHashCode(Acl acl) => + !acl.Rules.Any() ? 0 : acl.Rules + .Select(r => ( + r.Action, + r.Permissions, + r.Principal.GetHashCode()).GetHashCode()) + .Aggregate((a, v) => HashCode.Combine(a, v)); + private class PermissionCheckbox { public string Description { get; private init; } diff --git a/Pages/Component/AclDialog.razor.css b/Pages/Component/AclDialog.razor.css index c9ac518..3cab1c6 100644 --- a/Pages/Component/AclDialog.razor.css +++ b/Pages/Component/AclDialog.razor.css @@ -30,25 +30,6 @@ div.hcontainer > div > p { text-align: center; } -div.principal-select { - align-items: center; - display: flex; - flex-direction: row; - margin-bottom: 16px; -} - -div.principal-select * { - margin: 0; -} - -div.principal-select :not(:last-child) { - margin-right: 5px; -} - -div.principal-select input[type="text"] { - flex-grow: 1; -} - div.hcontainer > div:last-child > label { font-family: 'Lucida Console'; } diff --git a/Pages/Component/MiniPrincipalSelect.razor b/Pages/Component/MiniPrincipalSelect.razor new file mode 100644 index 0000000..2202b95 --- /dev/null +++ b/Pages/Component/MiniPrincipalSelect.razor @@ -0,0 +1,44 @@ +@inject ISecurityService securityService + +
+ @if(edit) { + + + + + } else { + + Edit(true))> + @if(SecurityIdentifier is null || SecurityIdentifier == WellKnownSid.NullSid) { + Please select a user or group + } else { + @securityService.TranslateName(SecurityIdentifier) + } + + } +
+ +@code { + [Parameter] + public string Label { get; set; } + + [Parameter] + public EventCallback OnChange { get; set; } + + private bool edit = false; + private string name; + + public SecurityIdentifier? SecurityIdentifier { get; set; } + + private void Edit(bool enableEdit) { + edit = enableEdit; + + if(enableEdit) + name = SecurityIdentifier is null ? "" : + securityService.TranslateName(SecurityIdentifier); + } + + private void Submit() { + Edit(false); + } +} \ No newline at end of file diff --git a/Pages/Component/MiniPrincipalSelect.razor.css b/Pages/Component/MiniPrincipalSelect.razor.css new file mode 100644 index 0000000..4b7a217 --- /dev/null +++ b/Pages/Component/MiniPrincipalSelect.razor.css @@ -0,0 +1,18 @@ +div { + align-items: center; + display: flex; + flex-direction: row; + margin-bottom: 16px; +} + +div * { + margin: 0; +} + +div :not(:last-child) { + margin-right: 5px; +} + +div input[type="text"] { + flex-grow: 1; +} -- cgit v1.3