Activities of "alexander.nikonov"

hi

I think there is no problem with this.

Restore my question points then please if not done yet.

Eventually I've resolved thie issue. I've split the shared project DbContexts into 2 - one contains the entities which are shared in the consuming project, another one contains the entities which use the same table as the entities in the consuming project. Please, replenish my point for this question.

I've tried to resolved the issue with the code below (separating DbContexts):

public static void ConfigureCoreInternal(this ModelBuilder builder, Action<CoreModelBuilderConfigurationOptions> optionsAction = null)
...

EntityFramework Module:

[DependsOn(typeof(CoreDomainModule), typeof(AbpEntityFrameworkCoreModule))]
public class CoreEntityFrameworkCoreModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.AddAbpDbContext<CoreDbContext>(options =>
        {
            options.AddDefaultRepository<ModuleLicence>();
            options.AddDefaultRepository<CompanyLicence>();
            options.AddDefaultRepository<Tenant>();
        });
    }
}

The method which does DB work:

public async Task<List<string>> GetAccessibleModulesAsync(int abxTenantId)
{
    using (var uow = _unitOfWorkManager.Begin())
    {
        var tenants = await _tenantRepository.GetQueryableAsync();
        var companyLicences = await _companyLicenceRepository.GetQueryableAsync();
        var moduleLicences = await _moduleLicenceRepository.GetQueryableAsync();

        var query = from tenant in tenants.Where(x => x.Id == abxTenantId).Take(1)
                    join companyLicence in companyLicences on tenant.CompanyId equals companyLicence.CompanyId
                    join moduleLicence in moduleLicences on companyLicence.LicenceId equals moduleLicence.LicenceId
                    select moduleLicence.ModuleId;

        return query.Distinct().ToList();
    }
}

Application Module where I add my custom class AbxPermissionChecker:

[DependsOn(...., typeof(CoreApplicationModule))]
public class CentralToolsApplicationModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        var configuration = context.Services.GetConfiguration();

        Configure<AbpAutoMapperOptions>(options =>
        {
            options.AddMaps<CentralToolsApplicationModule>();
        });

        ....
        context.Services.Replace(ServiceDescriptor.Transient<IPermissionChecker, AbxPermissionChecker>()); // REPLACING ABP PermissionChecker!
    }
}

But still getting the above exception

What is a proper way of isolating entities in the DbContext of the project which is shared? Maybe this is the only root of the problem?

  • ABP Framework version: v5.1.2
  • UI type: Angular
  • DB provider: EF Core
  • Identity Server Separated (Angular)

I am trying to create a custom implementation of IPermissionChecker in the shared project and consume this implementation in several projects. Currently I'm having the problem with this implementation. Here is the checker:

[Dependency(ReplaceServices = false)]
public class AbxPermissionChecker : IPermissionChecker
{
    private PermissionChecker _abpPermissionChecker;
    private IServiceProvider _serviceProvider;
    private readonly ILicencePermissionChecker _licencePermissionChecker;

    public AbxPermissionChecker
    (
        PermissionChecker abpPermissionChecker,
        IServiceProvider serviceProvider,
        ILicencePermissionChecker licencePermissionChecker
    )
    {
        _abpPermissionChecker = abpPermissionChecker;
        _serviceProvider = serviceProvider;
        _licencePermissionChecker = licencePermissionChecker;
    }

    public async Task<bool> IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
    {
        using var scope = _serviceProvider.CreateScope();

        var abxRequestContext = scope.ServiceProvider.GetRequiredService<IAbxRequestContext>();

        return await _licencePermissionChecker.IsGrantedAsync(abxRequestContext.AbxTenantId, abxRequestContext.AbxModuleId) && await _abpPermissionChecker.IsGrantedAsync(claimsPrincipal, name);
    }

    public Task<bool> IsGrantedAsync(string name)
    {
        return _abpPermissionChecker.IsGrantedAsync(name);
    }

    public Task<MultiplePermissionGrantResult> IsGrantedAsync(string[] names)
    {
        return _abpPermissionChecker.IsGrantedAsync(names);
    }

    public Task<MultiplePermissionGrantResult> IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string[] names)
    {
        return _abpPermissionChecker.IsGrantedAsync(claimsPrincipal, names);
    }
}

public class PermissionManager : DomainService
{
    private readonly IRepository<Tenant, int> _tenantRepository;
    private readonly IRepository<ModuleLicence> _moduleLicenceRepository;
    private readonly IRepository<CompanyLicence> _companyLicenceRepository;

    public PermissionManager
    (
        IRepository<Tenant, int> tenantRepository,
        IRepository<ModuleLicence> moduleLicenceRepository,
        IRepository<CompanyLicence> companyLicenceRepository
    )
    {
        _tenantRepository = tenantRepository;
        _moduleLicenceRepository = moduleLicenceRepository;
        _companyLicenceRepository = companyLicenceRepository;
    }

    public async Task<List<string>> GetAccessibleModulesAsync(int abxTenantId)
    {
        var tenants = await _tenantRepository.GetQueryableAsync();
        var companyLicences = await _companyLicenceRepository.GetQueryableAsync();
        var moduleLicences = await _moduleLicenceRepository.GetQueryableAsync();

        var query = from tenant in tenants.Where(x => x.Id == abxTenantId).Take(1)
                    join companyLicence in companyLicences on tenant.CompanyId equals companyLicence.CompanyId
                    join moduleLicence in moduleLicences on companyLicence.LicenceId equals moduleLicence.LicenceId
                    select moduleLicence.ModuleId;

        return query.Distinct().ToList();
    }
}

The exception I'm getting in the consuming project when accessing PermissionManager method:

Autofac.Core.DependencyResolutionException: An exception was thrown while activating Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationController -> Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationAppService -> AbxEps.CT.Core.Permissions.AbxPermissionChecker -> AbxEps.CT.Core.Permissions.AbxLicencePermissionChecker -> AbxEps.CT.Core.Permissions.PermissionManager. ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'AbxEps.CT.Core.Permissions.PermissionManager' can be invoked with the available services and parameters: Cannot resolve parameter 'Volo.Abp.Domain.Repositories.IRepository2[AbxEps.CT.Core.Tenants.Tenant,System.Int32] tenantRepository' of constructor 'Void .ctor(Volo.Abp.Domain.Repositories.IRepository2[AbxEps.CT.Core.Tenants.Tenant,System.Int32], Volo.Abp.Domain.Repositories.IRepository1[AbxEps.CT.Core.ModuleLicences.ModuleLicence], Volo.Abp.Domain.Repositories.IRepository1[AbxEps.CT.Core.CompanyLicences.CompanyLicence])'.

Now let me explain what I'm trying to achieve. CoreDbContext in the shared project contains SIMPLIFIED models of entities which are ALREADY bound in the consuming project. Since I cannot bind the model to the same table name twice in the same DbContext as well as I don't want to MOVE a complex model binding from consuming project to the shared project, I decided to use two independent DbContext:

public static void ConfigureCore(
    this ModelBuilder builder,
    Action<CoreModelBuilderConfigurationOptions> optionsAction = null
) {
    builder.Entity<CompanyLicence>(b =>
    {
        b.ToTable("CT_CA_COMP_LIC", CentralToolsConsts.DbSchema);
        .... simplified binding
    }

public static void ConfigureConsuming(
    this ModelBuilder builder,
    Action<ConsumingModelBuilderConfigurationOptions> optionsAction = null
) {
    builder.Entity<CompanyLicence>(b =>
    {
        b.ToTable("CT_CA_COMP_LIC", CentralToolsConsts.DbSchema);
        .... advanced binding
    }

Or, I can keep using AppService - with RemoteService(IsEnabled = false)] as mentioned in my code, right? I do not expose NotificationAppService outside. In such case there's no difference between using it or converting it to DomainService, as far as I understand. I even don't inherit ApplicationService class...

Even if I use DomainService or Repository directly - how will it differ from using IApplicationService in the way I used it in terms of trust? I really need kind of pass "trust" from Received method into AppService (or other level) method where I would act on behalf of this user which usually is an authenticated ICurrentUser if used from frontend application. What I have at my disposal is just this user's Id and Tenant inside Received method.

I have a separate IdentityServer.

One of the projects has RabbitMQ receiver, where all other projects send the data too. This receiver needs to insert data into DB based on the received RabbitMQ input and it uses INotificationAppService in the same project to do that. See the code below.

When I do not use Authorization attribute - it of course works OK. But I want to make it work secure - i.e. if I do not use typical request authorization (since there is no request in question here) RabbitMQ needs to be trusted somehow inside AppService.

So what are your proposals again - even if you mean not to use AppService at all here? Could you please write a couple of code lines to describe the idea?

public override async Task<object> Received(BasicDeliverEventArgs @event)
{
    var notificationCacheRabbitMqEto = @event.ToDataObject<NotificationRabbitMqEto>();

    var hubContext = _serviceProvider.GetService<IHubContext<NotificationHub>>();

    using (var scope = _serviceProvider.CreateScope())
    {
        try
        {
            var notificationAppService = scope.ServiceProvider.GetRequiredService<INotificationAppService>();
            var newNotification = await notificationAppService.CreateAsync(new NotificationCreateDto
            {
                TenantId = notificationCacheRabbitMqEto.TenantId,
                Login = notificationCacheRabbitMqEto.Login,
                Level = (int)notificationCacheRabbitMqEto.Level,
                Title = notificationCacheRabbitMqEto.Title,
                Details = notificationCacheRabbitMqEto.Details,
                IsActive = true,
                IsImportant = notificationCacheRabbitMqEto.IsImportant,
                CreatorName = GetTrimmedCreatorName(notificationCacheRabbitMqEto.Login), //Like so?
                LastModifierName = GetTrimmedCreatorName(notificationCacheRabbitMqEto.Login) //Like so?
            });

            await hubContext.Clients.Group(notificationCacheRabbitMqEto.Login).SendAsync("notificationReceived", newNotification);
        }
        catch (Exception ex)
        {
            Log.Error(ex.Message);
        }
    }

    return Task.FromResult<object>(null);
}
    
[RemoteService(IsEnabled = false)]
//[Authorize]
public class NotificationAppService : INotificationAppService
{
    private readonly IServiceProvider _serviceProvider;
    private readonly INotificationRepository _notificationRepository;
    private readonly IStringLocalizer<CommonUIResource> _stringLocalizer;
    private readonly IUnitOfWorkManager _unitOfWorkManager;
    private readonly IObjectMapper _objectMapper;

    public NotificationAppService
    (
        IServiceProvider serviceProvider,
        INotificationRepository notificationRepository,
        IStringLocalizer<CommonUIResource> stringLocalizer,
        IUnitOfWorkManager unitOfWorkManager,
        IObjectMapper objectMapper
    )
    {
        _serviceProvider = serviceProvider;
        _notificationRepository = notificationRepository;
        _stringLocalizer = stringLocalizer;
        _unitOfWorkManager = unitOfWorkManager;
        _objectMapper = objectMapper;
    }
    ...
}

public interface INotificationAppService : IApplicationService, ITransientDependency {
    ...
}
  • ABP Framework version: v5.1.2
  • UI type: Angular
  • DB provider: EF Core
  • Identity Server Separated (Angular)

What is correct way to authorize RabbitMQ user so that I could invoke AppService methods from RabbitMQ receiver or sender? In the meantime both CurrentTenant and CurrentUser are null. Please write the example of the code.

You should not remove Authorize, We recommend that you pass the access token to complete the authentication.

https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-7.0#built-in-jwt-authentication https://ocelot.readthedocs.io/en/latest/features/websockets.html

I've already seen and used it before. As I said, passing token in URL doesn't seem very prominent. But this confuses me at Ocelot at NOT SUPPORTED section: "Authentication - If anyone requests it we might be able to do something with basic authentication."

So what is the underline here? Does authentication for Ocelot + SignalR does not suggest another way of request authentication besides passing token via URL?

UPDATE.

It started to work after I removed [Authorize] attribute from my Hub class. Does it mean that currently SignalR is working without authentication? I know that SignalR does not work with headers, but I don't want to pass token via URL. Should I ever worry about that, if my SignalRService code works within AppComponent which is available only for authorized user?

Probably you can suggest another approach to be on safe side? In addition to using tokens, I used to create token cookie in my HttpApi.Host project middleware and added it later on to each request like this (for instance, for Hangfire dashboard page), but at some point cookie functionality got broken - probably after introducing Ocelot gateway, not sure...

Showing 241 to 250 of 375 entries
Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on September 16, 2025, 10:35