- 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)
-
0
Hi,
This is by design. A tenant must be under the host. But you can do this in the following ways:
- 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; }
- 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; } ...... }
- 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; } }
-
0
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 hasId
andMasterId
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 seeTenantId
has to beGuid
, but in our tableId
(MasterId
too, accordingly) isInteger
(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? -
0
- Add to
PermissionDefinitionProvider
derived class, Usually under thePermissions
folder of the.Application.Contracts
project. - No problem, you can use the
int
type as the primary key And you don’t need to implementIMultiTenant
. 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; } }
- Add to
-
0
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).
-
0
Please try one more.