Base solution for your next web application
Open Closed

Automate the creation process of AppPermissions #996


User avatar
0
andis created

Is there anyway to automate the creation process of AppPermissions? Is there any particular reason to put AppAuthorizationProvider in .Core level? I intended to create AppPermissions for all Application Service, but I cannot use reflection as the AppAuthorizationProvider is in .Core level while all services are in .Application level


3 Answer(s)
  • User Avatar
    0
    manifestarium created

    Here you go. Adapt this to your needs:

    Core project - MyAppAuthorizationProvider.cs:

    using Abp.Authorization;
    using Abp.Localization;
    using Abp.MultiTenancy;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MyApp.Authorization
    {
        public class MyAppAuthorizationProvider : AuthorizationProvider
        {
            public override void SetPermissions(IPermissionDefinitionContext context)
            {
                List<PermissionInfo> permissionInfos = new List<PermissionInfo>();
    
                foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
    
                    if (!assembly.IsDynamic)
                    {
                        foreach (TypeInfo typeInfo in assembly.GetExportedTypes())
                        {
                            // Attributes on Fields (Constants)
                            foreach (FieldInfo fieldInfo in typeInfo.GetFields())
                            {
    
                                var permissionAttribute = fieldInfo.GetCustomAttribute<PermissionAttribute>(false);
                                if (permissionAttribute != null)
                                {
                                    permissionInfos.Add(
                                        new PermissionInfo()
                                        {
                                            Name = (string)fieldInfo.GetRawConstantValue(),
                                            DisplayName = permissionAttribute.DisplayName,
                                            IsGrantedByDefault = permissionAttribute.IsGrantedByDefault,
                                            MultiTenancySides = permissionAttribute.MultiTenancySides
                                        });
                                }
                            }
                        }
                    }
                }
    
                foreach (PermissionInfo permissionInfo in permissionInfos.OrderBy(p => p.Name))
                {
                    Permission parentPermission = null;
                    Permission newPermission = null;
                    if (permissionInfo.Name.Contains("."))
                    {
                        string parentName = permissionInfo.Name.Substring(0, permissionInfo.Name.LastIndexOf('.'));
                        parentPermission = context.GetPermissionOrNull(parentName);
                        if (parentPermission == null)
                        {
                            throw new Exception("Permission not defined: '" + parentName + "'");
                        }
                        newPermission = parentPermission.CreateChildPermission(
                            name: permissionInfo.Name,
                            displayName: F(permissionInfo.DisplayName),
                            isGrantedByDefault: permissionInfo.IsGrantedByDefault,
                            description: F(permissionInfo.Description),
                            multiTenancySides: permissionInfo.MultiTenancySides);
                    }
                    else
                    {
                        newPermission = context.CreatePermission(
                            name: permissionInfo.Name,
                            displayName: F(permissionInfo.DisplayName),
                            isGrantedByDefault: permissionInfo.IsGrantedByDefault,
                            description: F(permissionInfo.Description),
                            multiTenancySides: permissionInfo.MultiTenancySides);
                    }
    
                }
            }
    
            public class PermissionInfo
            {
                public string Name;
    
                public string DisplayName;
    
                public string Description;
    
                public MultiTenancySides MultiTenancySides;
    
                public bool IsGrantedByDefault;
            }
    
    
            /// <summary>
            /// Creates a fixed localizable string (avoids using localization - just pass it the text directly)
            /// </summary>
            private static ILocalizableString F(string value)
            {
                return new FixedLocalizableString(value);
            }
    
            private static ILocalizableString L(string name)
            {
                return new LocalizableString(name, MyAppConstants.LocalizationSourceName);
            }
        }
    }
    

    Core project - PermissionAttribute.cs

    using Abp.MultiTenancy;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MyApp.Authorization
    {
        public partial class PermissionAttribute : Attribute
        {
            // Note: The Name (not display name) of the property is defined by the name of the constant the attribute is applied to.
    
            public string DisplayName { get; set; }
    
            public string Description { get; set; }
    
            private MultiTenancySides _multiTenancySides = MultiTenancySides.Host | MultiTenancySides.Tenant;
    
            public MultiTenancySides MultiTenancySides
            {
                get { return _multiTenancySides; }
                set { _multiTenancySides = value; }
            }
    
            public bool IsGrantedByDefault { get; set; }
    
        }
    }
    

    Then, ANYWHERE in your solution, in ANY PROJECT, you can define classes like this:

    using MyApp.Authorization;
    using System.ComponentModel;
    
    namespace MyApp.Authorization
    {
        public static partial class PermissionNames
        {
            [Permission(DisplayName = "Administration")] // MultiTenancySides defaults to Host & Tenant if not specified. This way, the host AND customers (tenants) can have admin sections.
            public const string Administration = "Administration";
    
            [Permission(DisplayName = "Customer Management", MultiTenancySides = Abp.MultiTenancy.MultiTenancySides.Host)]
            public const string CustomerManagement = "Administration.CustomerManagement"; // Permissions will automatically be arranged into the proper hierarchy (parent/child) based on the Parent.Child.Grandchild dot-based naming pattern.
    
            [Permission(DisplayName = "Customer Portal", MultiTenancySides = Abp.MultiTenancy.MultiTenancySides.Tenant)]
            public const string CustomerPortal = "CustomerPortal"; // Only customers (tenants) can be assigned this permission
        }
    }
    

    And the core auth code will find the attributes on the constants and automagically create your permissions with the correct hierarchical structure

  • User Avatar
    0
    manifestarium created

    I wrote:

    // Note: The Name (not display name) of the property is defined by the name of the constant the attribute is applied to.
    

    But it should actually say this:

    // Note: The Name (not display name) of the property is defined by the value of the constant the attribute is applied to.
    
  • User Avatar
    0
    manifestarium created

    ONE MORE CORRECTION, SORRY! This time I tested it ;)

    using Abp.Authorization;
    using Abp.Localization;
    using Abp.MultiTenancy;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace MyApp.Authorization
    {
        public class MyAppAuthorizationProvider : AuthorizationProvider
        {
            public override void SetPermissions(IPermissionDefinitionContext context)
            {
                List<PermissionInfo> permissionInfos = new List<PermissionInfo>();
    
                foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
    
                    if (!assembly.IsDynamic)
                    {
                        foreach (TypeInfo typeInfo in assembly.GetExportedTypes())
                        {
                            // Attributes on Fields (Constants)
                            foreach (FieldInfo fieldInfo in typeInfo.GetFields())
                            {
    
                                var permissionAttribute = fieldInfo.GetCustomAttribute<PermissionAttribute>(false);
                                if (permissionAttribute != null)
                                {
                                    permissionInfos.Add(
                                        new PermissionInfo()
                                        {
                                            Name = (string)fieldInfo.GetRawConstantValue(),
                                            DisplayName = permissionAttribute.DisplayName,
                                            IsGrantedByDefault = permissionAttribute.IsGrantedByDefault,
                                            MultiTenancySides = permissionAttribute.MultiTenancySides
                                        });
                                }
                            }
                        }
                    }
                }
    
                var parentNameBuilder = new StringBuilder();
                foreach (PermissionInfo permissionInfo in permissionInfos.OrderBy(p => p.Name))
                {
                    if (!permissionInfo.Name.Contains("."))
                    {
                        // Create top level permission
                        var newPermission = context.CreatePermission(
                            name: permissionInfo.Name,
                            displayName: F(permissionInfo.DisplayName),
                            isGrantedByDefault: permissionInfo.IsGrantedByDefault,
                            description: F(permissionInfo.Description),
                            multiTenancySides: permissionInfo.MultiTenancySides);
                    }
                    else
                    {
                        // Create child permission under appropriate parent
                        var nameParts = permissionInfo.Name.Split('.');
                        parentNameBuilder.Clear();
                        parentNameBuilder.Append(nameParts[0]);
                        Permission parentPermission = context.GetPermissionOrNull(parentNameBuilder.ToString());
                        for (int i = 1; i < nameParts.Length - 1; i++)
                        {
                            parentNameBuilder.Append(".");
                            parentNameBuilder.Append(nameParts[i]);
                            parentPermission = parentPermission.Children.Where(p => string.Compare(p.Name, parentNameBuilder.ToString(), true) == 0).FirstOrDefault();
                        }
                        if (parentPermission == null)
                        {
                            throw new Exception("Parent permission not defined: '" + parentNameBuilder.ToString() + "'");
                        }
                        var newPermission = parentPermission.CreateChildPermission(
                            name: permissionInfo.Name,
                            displayName: F(permissionInfo.DisplayName),
                            isGrantedByDefault: permissionInfo.IsGrantedByDefault,
                            description: F(permissionInfo.Description),
                            multiTenancySides: permissionInfo.MultiTenancySides);
                    }
                }
            }
    
            public class PermissionInfo
            {
                public string Name;
    
                public string DisplayName;
    
                public string Description;
    
                public MultiTenancySides MultiTenancySides;
    
                public bool IsGrantedByDefault;
            }
    
    
            /// <summary>
            /// Creates a fixed localizable string (avoids using localization - just pass it the text directly)
            /// </summary>
            private static ILocalizableString F(string value)
            {
                return new FixedLocalizableString(value);
            }
    
            private static ILocalizableString L(string name)
            {
                return new LocalizableString(name, MyAppConstants.LocalizationSourceName);
            }
        }
    }