Activities of "ageiter"

You can publish an event in PalmaTenantDatabaseMigrationHandler

Ah yes, that's it. Thank you!

Ok, I've seen the problem. It's because my TenantEventHandler was called first and then PalmaTenantDatabaseMigrationHandler, which creates the admin user.

Probably you can't specify a order?

I would simply prefer to have my logic in a separate EventHandler, as there are also further steps (sending mail etc.) which have nothing to do with database migration...

    public async Task HandleEventAsync(TenantCreatedEto eventData)
    {
        await MigrateAndSeedForTenantAsync(
            eventData.Id,
            eventData.Properties.GetOrDefault("AdminEmail") ?? PalmaConsts.AdminEmailDefaultValue,
            eventData.Properties.GetOrDefault("AdminPassword") ?? PalmaConsts.AdminPasswordDefaultValue
        );

        using (_currentTenant.Change(eventData.Id))
        {
            // Set admin user as confirmed
            var adminUser = await _userManager.FindByEmailAsync(PalmaConsts.AdminEmailDefaultValue);
            if (adminUser != null)
            {
                adminUser.SetEmailConfirmed(true);
                await _userManager.UpdateAsync(adminUser);
            }
        }
    }

Another problem: After creating the tenant (TenantAppService.CreateAsync), I would like to change something about the user. But it seems that the user is not yet in the database. It is not (yet) found...

Is the transaction only completed after all EventHandlers have been handled? Or is this a timing problem?

public class TenantEventHandler : IDistributedEventHandler<TenantCreatedEto>, ITransientDependency
{
    private readonly IdentityUserManager _userManager;
    private readonly ICurrentTenant _currentTenant;

    public TenantEventHandler(IdentityUserManager userManager, ICurrentTenant currentTenant)
    {
        _userManager = userManager;
        _currentTenant = currentTenant;
    }

    public async Task HandleEventAsync(TenantCreatedEto eventData)
    {
        using (_currentTenant.Change(eventData.Id))
        {
            // Set admin user as confirmed
            var adminUser = await _userManager.FindByEmailAsync(PalmaConsts.AdminEmailDefaultValue);
            if (adminUser != null)
            {
                adminUser.SetEmailConfirmed(true);
                await _userManager.UpdateAsync(adminUser);
            }
        }
    }

[AllowAnonymous] works, thank you for the hint.

I am using version 8.2.2... maybe it's already fixed in 8.3?

maybe you can try

It's not that important to me, I just wanted to make a contribution to improving ABP.

My next problem: The tenant should be created automatically when a customer registers. Now, of course, I have a problem with the permissions, as certain rights are required to create a tenant and an anonymous user cannot have these.

I have already extended the TenantAppService and the CreateAsync method, but the permissions are taken from the base class.

How can I achieve my goal?

You don't need to extend TenantAppService, you can use data seeder.: https://abp.io/docs/latest/framework/infrastructure/data-seeding

Thank you, that worked.

Not yet definitely. We have to wait for a few decisions from the customer and I would therefore like to leave the question open so that we can ask again later if necessary.

This is easy to reproduce: Revoke a user's rights to the sessions. But he still has the rights for user management. Then click in actions menu to the item "Sessions". Popup opens, but the data cannot be loaded due to missing authorizations. Because the error is not caught, the popup cannot be closed and the page must be reloaded.

i could not reproduce the problem

Ok... These are the permissions on the role:

I am using version 8.2.2... maybe it's already fixed in 8.3?

This is currently my code. But when creating the customer user, it ends in an exception.

    public override async Task<SaasTenantDto> CreateAsync(SaasTenantCreateDto input)
    {
        // Set initial edition
        if (input.EditionId == null)
        {
            input.EditionId = (await _editionRepository.FindByDisplayNameAsync(PalmaConsts.EditionNameInitial)).Id;
        }

        // Get email & password for customer user (which is created later)
        var customerEmail = input.AdminEmailAddress;
        var customerPassword = input.AdminPassword;

        // Set default email & password for admin user to input
        input.AdminEmailAddress = PalmaConsts.AdminEmailDefaultValue;
        input.AdminPassword = PalmaConsts.AdminPasswordDefaultValue;

        // Create tenant (with default admin user)
        var tenant = await base.CreateAsync(input);

        // Create customer user
        using (CurrentTenant.Change(tenant.Id, tenant.Name))
        {
            var customerUser = await _userAppServce.CreateAsync(new IdentityUserCreateDto()
            {
                UserName = customerEmail,
                Email = customerEmail,
                Password = customerPassword,
                RoleNames = new[]
                {
                    PalmaConsts.RoleNameCustomer
                }
            });
        }

        // Seed initial data
        await SeedInitialDataAsync(tenant, input);

        return tenant;
    }

AbpAuthorizationException:

2024-09-16 16:26:12.176 +02:00 [WRN] Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown.
Volo.Abp.Authorization.AbpAuthorizationException: Exception of type 'Volo.Abp.Authorization.AbpAuthorizationException' was thrown.
   at Microsoft.AspNetCore.Authorization.AbpAuthorizationServiceExtensions.CheckAsync(IAuthorizationService authorizationService, AuthorizationPolicy policy)
   at Volo.Abp.Authorization.MethodInvocationAuthorizationService.CheckAsync(MethodInvocationAuthorizationContext context)
   at Volo.Abp.Authorization.AuthorizationInterceptor.AuthorizeAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
   at Volo.Abp.Auditing.AuditingInterceptor.ProcessWithNewAuditingScopeAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, ICurrentUser currentUser, IAuditingManager auditingManager, IAuditingHelper auditingHelper, IUnitOfWorkManager unitOfWorkManager)
   at Volo.Abp.Auditing.AuditingInterceptor.ProcessWithNewAuditingScopeAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, ICurrentUser currentUser, IAuditingManager auditingManager, IAuditingHelper auditingHelper, IUnitOfWorkManager unitOfWorkManager)
   at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Palma.Saas.PalmaTenantAppService.CreateAsync(SaasTenantCreateDto input)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
   at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Volo.Abp.BlazoriseUI.AbpCrudPageBase`10.CreateEntityAsync()

The admin user is automatically created when the new tenant is created. With the customer's e-mail address and password.

However, I would now like two users to be created. On the one hand the user for the customer (with the entered mail address as username) and on the other hand the admin user for us as host.

I have already extended the TenantAppService (of Volo.Saas.Host namespace) & TenantDataSeeder. Where would be the right point to realize this?

Is it best to write the CreateAsync method completely by myself? I would prefer to continue using base.CreateAsync() and add the other one afterwards.

Showing 1 to 10 of 243 entries
Made with ❤️ on ABP v9.0.0-preview Updated on September 19, 2024, 10:13