using System; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; namespace Kyoo.Abstractions.Models.Permissions { /// /// The kind of permission needed. /// public enum Kind { Read, Write, Create, Delete } /// /// The group of the permission. /// public enum Group { Overall, Admin } /// /// Specify permissions needed for the API. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class PermissionAttribute : Attribute, IFilterFactory { /// /// The needed permission as string. /// public string Type { get; } /// /// The needed permission kind. /// public Kind Kind { get; } /// /// The group of this permission /// public Group Group { get; } /// /// Ask a permission to run an action. /// /// /// The type of the action /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)). /// /// The kind of permission needed /// /// The group of this permission (allow grouped permission like overall.read /// for all read permissions of this group) /// public PermissionAttribute(string type, Kind permission, Group group = Group.Overall) { if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase)) type = type[..^3]; Type = type.ToLower(); Kind = permission; Group = group; } /// public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) { return serviceProvider.GetRequiredService().Create(this); } /// public bool IsReusable => true; /// /// Return this permission attribute as a string /// /// The string representation. public string AsPermissionString() { return Type; } } /// /// Specify one part of a permissions needed for the API (the kind or the type). /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class PartialPermissionAttribute : Attribute, IFilterFactory { /// /// The needed permission type. /// public string Type { get; } /// /// The needed permission kind. /// public Kind Kind { get; } /// /// Ask a permission to run an action. /// /// /// With this attribute, you can only specify a type or a kind. /// To have a valid permission attribute, you must specify the kind and the permission using two attributes. /// Those attributes can be dispatched at different places (one on the class, one on the method for example). /// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will /// lead to unspecified behaviors. /// /// /// The type of the action /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)). /// public PartialPermissionAttribute(string type) { if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase)) type = type[..^3]; Type = type.ToLower(); } /// /// Ask a permission to run an action. /// /// /// With this attribute, you can only specify a type or a kind. /// To have a valid permission attribute, you must specify the kind and the permission using two attributes. /// Those attributes can be dispatched at different places (one on the class, one on the method for example). /// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will /// lead to unspecified behaviors. /// /// The kind of permission needed public PartialPermissionAttribute(Kind permission) { Kind = permission; } /// public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) { return serviceProvider.GetRequiredService().Create(this); } /// public bool IsReusable => true; } /// /// A service to validate permissions /// public interface IPermissionValidator { /// /// Create an IAuthorizationFilter that will be used to validate permissions. /// This can registered with any lifetime. /// /// The permission attribute to validate /// An authorization filter used to validate the permission IFilterMetadata Create(PermissionAttribute attribute); /// /// Create an IAuthorizationFilter that will be used to validate permissions. /// This can registered with any lifetime. /// /// /// A partial attribute to validate. See . /// /// An authorization filter used to validate the permission IFilterMetadata Create(PartialPermissionAttribute attribute); } }