Open Closed

Is it possible to create tenants by a user which logged in under usual tenant, NOT under 'null'-tenant? #362


User avatar
0
alexander.nikonov created
  • ABP Framework version: v3.0.5
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): Identity Server Seperated

Hi, we are using Tenants functionality and noticed it's only possible to create a tenant in UI by a user logged in under a 'null'-tenant (super tenant?) We need to create tenants by a user, logged in under ANOTHER tenant - we have a custom tree-like structure of tenants in our system.


5 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    This is by design. A tenant must be under the host. But you can do this in the following ways:

    1. Change permissions about tenants scope:
    
    var tenantPermission = context.GetPermissionOrNull(SaasHostPermissions.Tenants.Default);
    
    tenantPermission.MultiTenancySide = MultiTenancySides.Both;
    
    foreach (var tenantPermissionChild in tenantPermission.Children)
    {
        tenantPermissionChild.MultiTenancySide = MultiTenancySides.Both;
    }
    
    var editionPermission = context.GetPermissionOrNull(SaasHostPermissions.Editions.Default);
    
    editionPermission.MultiTenancySide = MultiTenancySides.Both;
    
    foreach (var editionPermissionChild in editionPermission.Children)
    {
        editionPermissionChild.MultiTenancySide = MultiTenancySides.Both;
    }
    
    1. Create a table to store information about tenants under the tenant. Example:
    public class TenantInfo : AggregateRoot<Guid>, IMultiTenant
    {
        public Guid? TenantId { get; }
    
        public Guid RelatedTenantId { get; set; }
    
        public string Name { get; set; }
    
        ......
    }
    
    1. Override the tenant creation method:
    [Dependency(ReplaceServices = true)]
    [Authorize(SaasHostPermissions.Tenants.Default)]
    public class MyTenantService : TenantAppService
    {
        private readonly IRepository<TenantInfo, Guid> _tenantInfoRepository;
    
        public MyTenantService(
            ITenantRepository tenantRepository,
            IEditionRepository editionRepository,
            ITenantManager tenantManager,
            IDataSeeder dataSeeder,
            IRepository<TenantInfo, Guid> tenantInfoRepository) :
            base(tenantRepository,
                editionRepository,
                tenantManager,
                dataSeeder)
        {
            _tenantInfoRepository = tenantInfoRepository;
        }
    
        [Authorize(SaasHostPermissions.Tenants.Create)]
        public override async Task<SaasTenantDto> CreateAsync(SaasTenantCreateDto input)
        {
            SaasTenantDto result = null;
    
            using (CurrentTenant.Change(null))
            {
                result = await base.CreateAsync(input);
            }
    
    
            await _tenantInfoRepository.InsertAsync(new TenantInfo()
            {
                Name = result.Name,
                RelatedTenantId = result.Id
            });
    
            return result;
        }
    }
    
  • User Avatar
    0
    alexander.nikonov created

    Hi,

    thank you, would give it a try, but two questions right away:

    Change permissions about tenants scope

    where this needs to be placed?

    public class TenantInfo : AggregateRoot, IMultiTenant

    we already use the table for our Tenant entity (it has Id and MasterId for tenant id and master tenant id correspondingly). It also has 1:1 ABP tenant entity:

        public class Tenant : SoftDeleteLogEntity<int>
        {
            ...
            public int? MasterId { get; set; }
            public Tenant MasterTenant { get; set; }
            public Guid AbpId { get; set; } // it is ABP tenant's id
            public AbpTenant AbpTenant { get; set; } // it is ABP tenant
            ...
        }
            
        public abstract class SoftDeleteLogEntity<TKey> : LogEntity<TKey>, IMayHaveDeleterName, ISoftDelete, IDeletionAuditedObject {...}
        public abstract class LogEntity<TKey> : AuditedEntity<TKey>, IMayHaveCreatorName, IMayHaveLastModifierName {...}
    

    but we did not implement IMultiTenant. Now, when I'd like to do that - I can see TenantId has to be Guid, but in our table Id (MasterId too, accordingly) is Integer (it was customer's decision)... How to overcome this problem? Is it OK just to implement a 'fake' Guid TenantId field and not use it?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer
    1. Add to PermissionDefinitionProvider derived class, Usually under the Permissions folder of the .Application.Contracts project.
    2. No problem, you can use the int type as the primary key And you don’t need to implement IMultiTenant. You should always switch to the host when operating your own tenant entity.
    [Authorize(SaasHostPermissions.Tenants.Create)]
    public override async Task<SaasTenantDto> CreateAsync(SaasTenantCreateDto input)
    {
        var currentMyTenant = await _myTenantRepository.FindAsync(x => x.AbpTenantId == CurrentTenant.Id);
    
        using (CurrentTenant.Change(null))
        {
            var result = await base.CreateAsync(input);
    
            await _myTenantRepository.InsertAsync(new MyTenant()
            {
                AbpTenantId = result.Id,
                MasterTenant = currentMyTenant,
                MasterId = currentMyTenant.Id
            });
    
            return result;
        }
    }
    
  • User Avatar
    0
    alexander.nikonov created

    Thank you. I will give it a try later on, because requirements have changed. Could you please explain why I cannot reopen another ticket (which I closed) or add answer? When I'm trying to do that, I receive the message saying I am not authorized to do that (I AM logged in).

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Please try one more.

Made with ❤️ on ABP v9.0.0-preview. Updated on October 07, 2024, 08:52