using System.ComponentModel.DataAnnotations.Schema; namespace HyperBooru; public enum AclRuleAction { Allow, Deny } public class Acl { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int AclId { get; set; } public HBObject Subject { get; set; } public List Rules { get; set; } public static Type GetAclType(HBObject obj) { var attrib = Attribute.GetCustomAttribute(obj.GetType(), typeof(AclTypeAttribute), true); return (attrib as AclTypeAttribute)?.Type ?? typeof(ObjectPermissions); } public static IEnumerable> GetPermissionDescriptions(HBObject obj) { var aclType = GetAclType(obj); foreach(var val in Enum.GetValues(aclType)) { var attrib = (AclPermissionAttribute?) Attribute.GetCustomAttribute( aclType.GetMember(val.ToString()!).First(), typeof(AclPermissionAttribute)); yield return new(attrib?.Name ?? val.ToString()!, (ulong) val); } } } public class Acl : Acl where T : Enum { public Type Type => typeof(T); public new List> Rules { get => base.Rules.Cast>().ToList(); set => base.Rules = value.Cast().ToList(); } } public class AclRule { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int AclRuleId { get; set; } public SecurityIdentifier Principal { get; set; } public AclRuleAction Action { get; set; } [Column(TypeName = "bigint")] public ulong Permissions { get; set; } } public class AclRule : AclRule where T : Enum { public Type Type => typeof(T); public new T Permissions { get => (T) (object) base.Permissions; set => base.Permissions = (ulong) (object) value; } } public class AclTypeAttribute : Attribute { public Type Type { get; private init; } public AclTypeAttribute(Type aclType) { if(!aclType.IsEnum) throw new ArgumentException(); Type = aclType; } } public class AclPermissionAttribute : Attribute { public string? Name { get; set; } public AclPermissionAttribute() {} public AclPermissionAttribute(string name) => Name = name; }