feature: flag permissions

feature: flag permissions
This commit is contained in:
Gary Sharp
2025-07-20 10:45:55 +10:00
parent 7deead494b
commit be7ee4cae8
72 changed files with 5590 additions and 2109 deletions
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using Disco.Models.Services.Authorization;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Disco.Models.Repository
{
@@ -27,11 +29,20 @@ namespace Disco.Models.Repository
[DataType(DataType.MultilineText)]
public string OnUnassignmentExpression { get; set; }
[Column("Permissions")]
public string PermissionsJson { get; set; }
[NotMapped]
public FlagPermission Permissions
{
get => FlagPermission.FromFlag(this);
set => PermissionsJson = value?.ToJson();
}
public int? DefaultRemoveDays { get; set; }
public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
public override string ToString()
{
return Name;
}
=> Name;
}
}
@@ -19,26 +19,28 @@ namespace Disco.Models.Repository
public string AddedUserId { get; set; }
public DateTime? RemovedDate { get; set; }
public string RemovedUserId { get; set; }
public DateTime? RemoveDate { get; set; }
public string RemoveUserId { get; set; }
public string Comments { get; set; }
public string OnAssignmentExpressionResult { get; set; }
public string OnUnassignmentExpressionResult { get; set; }
[ForeignKey(nameof(DeviceFlagId)), InverseProperty("DeviceFlagAssignments")]
[ForeignKey(nameof(DeviceFlagId)), InverseProperty(nameof(Repository.DeviceFlag.DeviceFlagAssignments))]
public virtual DeviceFlag DeviceFlag { get; set; }
[ForeignKey(nameof(DeviceSerialNumber)), InverseProperty("DeviceFlagAssignments")]
[ForeignKey(nameof(DeviceSerialNumber)), InverseProperty(nameof(Repository.Device.DeviceFlagAssignments))]
public virtual Device Device { get; set; }
[ForeignKey("AddedUserId")]
[ForeignKey(nameof(AddedUserId))]
public virtual User AddedUser { get; set; }
[ForeignKey("RemovedUserId")]
[ForeignKey(nameof(RemovedUserId))]
public virtual User RemovedUser { get; set; }
[ForeignKey(nameof(RemoveUserId))]
public virtual User RemoveUser { get; set; }
public override string ToString()
{
return $"Device Flag Id: {DeviceFlagId}; Device Serial Number: {DeviceSerialNumber}; Added: {AddedDate:s}";
}
=> $"Device Flag Id: {DeviceFlagId}; Device Serial Number: {DeviceSerialNumber}; Added: {AddedDate:s}";
}
}
+121
View File
@@ -0,0 +1,121 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace Disco.Models.Repository
{
public class FlagPermission
{
private static readonly FlagPermission DefaultDeviceFlagPermissions = new FlagPermission(FlagType.Device, 0);
private static readonly FlagPermission DefaultUserFlagPermissions = new FlagPermission(FlagType.User, 0);
[JsonIgnore]
public FlagType FlagType { get; }
[JsonIgnore]
public int FlagId { get; }
public bool Inherit { get; set; }
public HashSet<string> CanShowSubjectIds { get; }
public HashSet<string> CanAssignSubjectIds { get; }
public HashSet<string> CanEditSubjectIds { get; }
public HashSet<string> CanRemoveSubjectIds { get; }
private FlagPermission(FlagType flagType, int flagId)
{
FlagType = flagType;
FlagId = flagId;
Inherit = true;
CanShowSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
CanAssignSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
CanEditSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
CanRemoveSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
public bool IsDefault()
{
return ReferenceEquals(this, DefaultDeviceFlagPermissions) ||
ReferenceEquals(this, DefaultUserFlagPermissions);
}
public bool IsSimple()
{
return CanShowSubjectIds.SetEquals(CanAssignSubjectIds) &&
CanAssignSubjectIds.SetEquals(CanEditSubjectIds) &&
CanEditSubjectIds.SetEquals(CanRemoveSubjectIds);
}
public bool HasSubjects()
{
return CanShowSubjectIds.Count > 0 ||
CanAssignSubjectIds.Count > 0 ||
CanEditSubjectIds.Count > 0 ||
CanRemoveSubjectIds.Count > 0;
}
public HashSet<string> AllSubjects()
{
var allSubjects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
allSubjects.UnionWith(CanShowSubjectIds);
allSubjects.UnionWith(CanAssignSubjectIds);
allSubjects.UnionWith(CanEditSubjectIds);
allSubjects.UnionWith(CanRemoveSubjectIds);
return allSubjects;
}
public static FlagPermission FromFlag(UserFlag userFlag)
{
if (userFlag.PermissionsJson == null)
return DefaultUserFlagPermissions;
var permission = new FlagPermission(FlagType.User, userFlag.Id);
JsonConvert.PopulateObject(userFlag.PermissionsJson, permission);
return permission;
}
public static FlagPermission FromFlag(DeviceFlag deviceFlag)
{
if (deviceFlag.PermissionsJson == null)
return DefaultDeviceFlagPermissions;
var permission = new FlagPermission(FlagType.Device, deviceFlag.Id);
JsonConvert.PopulateObject(deviceFlag.PermissionsJson, permission);
return permission;
}
public static FlagPermission Create(UserFlag userFlag, bool inherit, IEnumerable<string> canShow, IEnumerable<string> canAssign, IEnumerable<string> canEdit, IEnumerable<string> canRemove)
{
var permission = new FlagPermission(FlagType.User, userFlag.Id);
return Create(permission, inherit, canShow, canAssign, canEdit, canRemove);
}
public static FlagPermission Create(DeviceFlag deviceFlag, bool inherit, IEnumerable<string> canShow, IEnumerable<string> canAssign, IEnumerable<string> canEdit, IEnumerable<string> canRemove)
{
var permission = new FlagPermission(FlagType.Device, deviceFlag.Id);
return Create(permission, inherit, canShow, canAssign, canEdit, canRemove);
}
private static FlagPermission Create(FlagPermission permission, bool inherit, IEnumerable<string> canShow, IEnumerable<string> canAssign, IEnumerable<string> canEdit, IEnumerable<string> canRemove)
{
permission.Inherit = inherit;
if (canShow != null)
permission.CanShowSubjectIds.UnionWith(canShow);
if (canAssign != null)
permission.CanAssignSubjectIds.UnionWith(canAssign);
if (canEdit != null)
permission.CanEditSubjectIds.UnionWith(canEdit);
if (canRemove != null)
permission.CanRemoveSubjectIds.UnionWith(canRemove);
return permission;
}
public string ToJson()
{
if (IsDefault())
return null;
return JsonConvert.SerializeObject(this);
}
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace Disco.Models.Repository
{
public enum FlagType
{
User = 1,
Device = 2,
}
}
+15 -4
View File
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using Disco.Models.Services.Authorization;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Disco.Models.Repository
{
@@ -27,11 +29,20 @@ namespace Disco.Models.Repository
[DataType(DataType.MultilineText)]
public string OnUnassignmentExpression { get; set; }
[Column("Permissions")]
public string PermissionsJson { get; set; }
[NotMapped]
public FlagPermission Permissions
{
get => FlagPermission.FromFlag(this);
set => PermissionsJson = value?.ToJson();
}
public int? DefaultRemoveDays { get; set; }
public virtual IList<UserFlagAssignment> UserFlagAssignments { get; set; }
public override string ToString()
{
return Name;
}
=> Name;
}
}
@@ -19,26 +19,28 @@ namespace Disco.Models.Repository
public string AddedUserId { get; set; }
public DateTime? RemovedDate { get; set; }
public string RemovedUserId { get; set; }
public DateTime? RemoveDate { get; set; }
public string RemoveUserId { get; set; }
public string Comments { get; set; }
public string OnAssignmentExpressionResult { get; set; }
public string OnUnassignmentExpressionResult { get; set; }
[ForeignKey("UserFlagId"), InverseProperty("UserFlagAssignments")]
[ForeignKey(nameof(UserFlagId)), InverseProperty(nameof(Repository.UserFlag.UserFlagAssignments))]
public virtual UserFlag UserFlag { get; set; }
[ForeignKey("UserId"), InverseProperty("UserFlagAssignments")]
[ForeignKey(nameof(UserId)), InverseProperty(nameof(Repository.User.UserFlagAssignments))]
public virtual User User { get; set; }
[ForeignKey("AddedUserId")]
[ForeignKey(nameof(AddedUserId))]
public virtual User AddedUser { get; set; }
[ForeignKey("RemovedUserId")]
[ForeignKey(nameof(RemovedUserId))]
public virtual User RemovedUser { get; set; }
[ForeignKey(nameof(RemoveUserId))]
public virtual User RemoveUser { get; set; }
public override string ToString()
{
return $"User Flag Id: {UserFlagId}; User Id: {UserId}; Added: {AddedDate:s}";
}
=> $"User Flag Id: {UserFlagId}; User Id: {UserId}; Added: {AddedDate:s}";
}
}