Abp: Add Permission Dynamically by Tenant

Created on 22 Jun 2020  路  4Comments  路  Source: abpframework/abp

Hi,
I need to add permission Dynamically by Tenant.
I got it that way with the "Permission DefinitionProvider" and the permissions loaded right, but when I change Tenant, it doesn't update the list of permissions on the screen. This works if I restart the API application. Is there a way to resolve this? I'm using Angular 9.

Thanks by this excelent framework!!
I intend to make some videos in Portuguese for the community.

My Code:

 public class CustomerPortalPermissionDefinitionProvider : PermissionDefinitionProvider, ITransientDependency
    {
        private IRepository<Cliente, int> _customerRepository;
        private readonly ICurrentTenant _currentTenant;

        public CustomerPortalPermissionDefinitionProvider(IRepository<Cliente, int> customerRepository, ICurrentTenant currentTenant)
        {
            _customerRepository = customerRepository;
            _currentTenant = currentTenant;
        }
        public override void Define(IPermissionDefinitionContext context)
        {

            var grpCustomer = context.AddGroup("Customer");

            var customerManagement =  grpCustomer.AddPermission("Customer_Management", null, MultiTenancySides.Tenant);
            customerManagement.AddChild("Customer_Management_Create");
            customerManagement.AddChild("Customer_Management_Edit");
            customerManagement.AddChild("Customer_Management_Delete");

            var visualizar = customerManagement.AddChild("Customer_Management_View");
            var customers = _customerRepository.Where(c => c.TenantId == _currentTenant.Id).ToList();
            foreach (var item in customers)
            {
                visualizar.AddChild("Customer_" + item.Id);
            }

        }
    }

image

Most helpful comment

The easiest way is to customize PermissionDefinitionManager and set DI life to transient(Will be initialized every time), like this:

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IPermissionDefinitionManager))]

public class MyPermissionDefinitionManager : PermissionDefinitionManager,ITransientDependency
{
    public MyPermissionDefinitionManager(
        IOptions<AbpPermissionOptions> options,
        IServiceProvider serviceProvider)
        : base(options, serviceProvider)
    {
    }

    public override PermissionDefinition Get(string name)
    {
        try
        {
            return base.Get(name);
        }
        catch (Exception e)
        {
            return MyPermissionDefinition.CreatePermissionDefinition(name);
        }

    }
}

public class MyPermissionDefinition : PermissionDefinition
{
    protected internal MyPermissionDefinition(string name, ILocalizableString displayName = null, MultiTenancySides multiTenancySide = MultiTenancySides.Both, bool isEnabled = true)
        : base(name, displayName, multiTenancySide, isEnabled)
    {
    }


    public static PermissionDefinition CreatePermissionDefinition(string name)
    {
        return new MyPermissionDefinition(name,isEnabled:false);
    }
}

This way can achieve your purpose, but it is not a best practice. Another way is that you can define the Refresh method in the custom PermissionDefinitionManager class and call it when switching tenants.

All 4 comments

I think that's not how the tenants are intended to be used.
You can't define permissions per tenant, since the permission provider runs only once (i think).

I think that's not how the tenants are intended to be used.
You can't define permissions per tenant, since the permission provider runs only once (i think).

Thanks @NecatiMeral for the comment. As far as I could see, that's right. I'm trying to find a way to refresh the "Define" method, but without success yet!

The easiest way is to customize PermissionDefinitionManager and set DI life to transient(Will be initialized every time), like this:

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IPermissionDefinitionManager))]

public class MyPermissionDefinitionManager : PermissionDefinitionManager,ITransientDependency
{
    public MyPermissionDefinitionManager(
        IOptions<AbpPermissionOptions> options,
        IServiceProvider serviceProvider)
        : base(options, serviceProvider)
    {
    }

    public override PermissionDefinition Get(string name)
    {
        try
        {
            return base.Get(name);
        }
        catch (Exception e)
        {
            return MyPermissionDefinition.CreatePermissionDefinition(name);
        }

    }
}

public class MyPermissionDefinition : PermissionDefinition
{
    protected internal MyPermissionDefinition(string name, ILocalizableString displayName = null, MultiTenancySides multiTenancySide = MultiTenancySides.Both, bool isEnabled = true)
        : base(name, displayName, multiTenancySide, isEnabled)
    {
    }


    public static PermissionDefinition CreatePermissionDefinition(string name)
    {
        return new MyPermissionDefinition(name,isEnabled:false);
    }
}

This way can achieve your purpose, but it is not a best practice. Another way is that you can define the Refresh method in the custom PermissionDefinitionManager class and call it when switching tenants.

The easiest way is to customize PermissionDefinitionManager and set DI life to transient(Will be initialized every time), like this:

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IPermissionDefinitionManager))]

public class MyPermissionDefinitionManager : PermissionDefinitionManager,ITransientDependency
{
    public MyPermissionDefinitionManager(
        IOptions<AbpPermissionOptions> options,
        IServiceProvider serviceProvider)
        : base(options, serviceProvider)
    {
    }

    public override PermissionDefinition Get(string name)
    {
        try
        {
            return base.Get(name);
        }
        catch (Exception e)
        {
            return MyPermissionDefinition.CreatePermissionDefinition(name);
        }

    }
}

public class MyPermissionDefinition : PermissionDefinition
{
    protected internal MyPermissionDefinition(string name, ILocalizableString displayName = null, MultiTenancySides multiTenancySide = MultiTenancySides.Both, bool isEnabled = true)
        : base(name, displayName, multiTenancySide, isEnabled)
    {
    }


    public static PermissionDefinition CreatePermissionDefinition(string name)
    {
        return new MyPermissionDefinition(name,isEnabled:false);
    }
}

This way can achieve your purpose, but it is not a best practice. Another way is that you can define the Refresh method in the custom PermissionDefinitionManager class and call it when switching tenants.

Works Like a Charm!! 馃槃 Thanks @liangshiw

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wocar picture wocar  路  3Comments

hikalkan picture hikalkan  路  3Comments

vfabregat picture vfabregat  路  3Comments

wocar picture wocar  路  3Comments

mehdihadeli picture mehdihadeli  路  3Comments