Activities of "alexander.nikonov"

I understand. I suspect it could be a back-end issue with Identity Server, so that token revocation is not successful. Could you please tell me how to troubleshoot this? I may send our Identity Server log for the period of logging out, so maybe you would notice the root cause. Here are one (sometimes two) requests which triggers after I click the "Logout" button: Afterwards I'm getting API requests from my component which are not supposed to be run, because I'm logging out - so they produce error 401. And eventually I'm landed to Home page without logging out.

Saying honestly, I still hoped I would be able to use unsubscriber$ in the component base class to control everything. It's a pity there's no some observable i can watch to change it... I would prefer not to scatter the changes around different classes (e.g. HttpInterceptor, etc.)

Well, at least it's possible make it working using AbpPermissionOptions.. I don't know why it requires it. But seems like I managed to make "dynamic" permission definition provider work properly combining "static" and "dynamic" values:

    private IDictionary<string, PermissionGroupDefinition> _dynamicPermissionGroupDefinitions = new Dictionary<string, PermissionGroupDefinition>();
    protected IDictionary<string, PermissionGroupDefinition> PermissionGroupDefinitions
    {
        get
        {
            var staticGroupDefinitions = _lazyPermissionGroupDefinitions.Value;
            var combinedGroupDefinitions = new Dictionary<string, PermissionGroupDefinition>(staticGroupDefinitions);
            foreach (var userAddedGroupDefinition in _dynamicPermissionGroupDefinitions)
            {
                combinedGroupDefinitions[userAddedGroupDefinition.Key] = userAddedGroupDefinition.Value;
            }
            return combinedGroupDefinitions;
        }
    }
    private readonly Lazy<Dictionary<string, PermissionGroupDefinition>> _lazyPermissionGroupDefinitions;

    private IDictionary<string, PermissionDefinition> _dynamicPermissionDefinitions = new Dictionary<string, PermissionDefinition>();
    protected IDictionary<string, PermissionDefinition> PermissionDefinitions
    {
        get
        {
            var staticDefinitions = _lazyPermissionDefinitions.Value;
            var combinedDefinitions = new Dictionary<string, PermissionDefinition>(staticDefinitions);
            foreach (var userAddedDefinition in _dynamicPermissionDefinitions)
            {
                combinedDefinitions[userAddedDefinition.Key] = userAddedDefinition.Value;
            }
            return combinedDefinitions;
        }
    }
    private readonly Lazy<Dictionary<string, PermissionDefinition>> _lazyPermissionDefinitions;

    protected AbpPermissionOptions Options { get; }

    private readonly IServiceProvider _serviceProvider;

    public ExtendedStaticPermissionDefinitionStore(
        IServiceProvider serviceProvider,
        IOptions<AbpPermissionOptions> options)
    {
        _serviceProvider = serviceProvider;
        Options = options.Value;

        _lazyPermissionDefinitions = new Lazy<Dictionary<string, PermissionDefinition>>(
            CreatePermissionDefinitions,
            isThreadSafe: true
        );

        _lazyPermissionGroupDefinitions = new Lazy<Dictionary<string, PermissionGroupDefinition>>(
            CreatePermissionGroupDefinitions,
            isThreadSafe: true
        );
    }

    public void AddPermissionDefinitionProvider(IPermissionDefinitionProvider permissionDefinitionProvider)
    {
        using (var scope = _serviceProvider.CreateScope())
        {
            var context = new PermissionDefinitionContext(scope.ServiceProvider);

            permissionDefinitionProvider.PreDefine(context);
            permissionDefinitionProvider.Define(context);
            permissionDefinitionProvider.PostDefine(context);

            foreach (var group in context.Groups)
            {
                _dynamicPermissionGroupDefinitions[group.Key] = group.Value;
            }

            var permissions = new Dictionary<string, PermissionDefinition>();

            foreach (var groupDefinition in _dynamicPermissionGroupDefinitions.Values)
            {
                foreach (var permission in groupDefinition.Permissions)
                {
                    AddPermissionToDictionaryRecursively(permissions, permission);
                }
            }

            foreach (var permission in permissions)
            {
                _dynamicPermissionDefinitions[permission.Key] = permission.Value;
            }
        }
    }
    

Probably would come in handy for someone. Closing the ticket... Thanks for inspiration!

Sure.

3 files here: Extension class which makes use of this "dynamic" provider,

overridden Static Store where the exception happens:

var providers = Options
    .DefinitionProviders
    .Select(p => scope.ServiceProvider.GetRequiredService(p) as IPermissionDefinitionProvider)
    .ToList()

if I don't use the Configure<AbpPermissionOptions> approach

and the PortalAccessPermissionDefinitionProvider itself.

Yes, I can and it works. However, I'd prefer to mark the class with attribute like DisableConventionalRegistration and be sure it is ignored everywhere. With this approach:

    Configure&lt;AbpPermissionOptions&gt;(options =>
    {
        options.DefinitionProviders.Remove(typeof(PortalAccessPermissionDefinitionProvider));
    })

I need to remember doing it in every project which uses the given class...

This approach works - I've already checked it before. But the problem is that I have hundreds of components, each of which has dozen of API calls. The components use base class which contains unsubscriber$ and it is used in ngOnDestroy to be nullified and complete. Thanks to that, when I go to another component, any API anywhere is properly unsubscribed (takeUntil(this.unsubscriber$)).

Making use of one more check means I need to add this filter(...) in all those API calls. And this is not a very good approach, IMHO.... I'd prefer to make changes in the base class unsubscriber$ only - to cover logout scenario...

I think I've almost managed to do this. However, quick question. How to prevent PermissionDefinitionProvider from being automatically handled by ABP? I've decorated it with DisableConventionalRegistration. But this is not enough, because Static Store uses one more mechanism, Options.DefinitionProviders, to read them. So in addition to DisableConventionalRegistration I need to manually remove it from IPermissionOptions DefinitionProviders collection (something for ABP to think about).

But probably there's a more comfortable way to make ABP ignore the provider?

The requested service 'AbxEps.CT.Core.Permissions.PortalAccessPermissionDefinitionProvider' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency. Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'AbxEps.CT.Core.Permissions.PortalAccessPermissionDefinitionProvider' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency. at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable1 parameters) at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType) at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetRequiredService(Type serviceType) at AbxEps.CT.ModulePermission.ExtendedStaticPermissionDefinitionStore.<>c__DisplayClass17_0.<CreatePermissionGroupDefinitions>b__0(Type p) at System.Linq.Enumerable.SelectIListIterator2.ToList() at AbxEps.CT.ModulePermission.ExtendedStaticPermissionDefinitionStore.CreatePermissionGroupDefinitions() at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) --- End of stack trace from previous location --- at System.Lazy`1.CreateValue() at AbxEps.CT.ModulePermission.ExtendedStaticPermissionDefinitionStore.get_PermissionGroupDefinitions() at AbxEps.CT.ModulePermission.ExtendedStaticPermissionDefinitionStore.GetGroupsAsync()

I understand that. And I see the code of StaticPermissionDefinitionStore:

public StaticPermissionDefinitionStore(
    IServiceProvider serviceProvider,
    IOptions&lt;AbpPermissionOptions&gt; options)
{
    _serviceProvider = serviceProvider;
    Options = options.Value;

    _lazyPermissionDefinitions = new Lazy&lt;Dictionary&lt;string, PermissionDefinition&gt;>(
        CreatePermissionDefinitions,
        isThreadSafe: true
    );

    _lazyPermissionGroupDefinitions = new Lazy&lt;Dictionary&lt;string, PermissionGroupDefinition&gt;>(
        CreatePermissionGroupDefinitions,
        isThreadSafe: true
    );
}

I understand that I can override the method which creates the groups:

protected virtual Dictionary&lt;string, PermissionGroupDefinition&gt; CreatePermissionGroupDefinitions()
{
    using (var scope = _serviceProvider.CreateScope())
    {
        var context = new PermissionDefinitionContext(scope.ServiceProvider);

        var providers = Options
            .DefinitionProviders
            .Select(p => scope.ServiceProvider.GetRequiredService(p) as IPermissionDefinitionProvider)
            .ToList(); // `CorePermissionDefinitionProvider` is still not known here - this list is created when `StaticPermissionDefinitionStore` singleton is instantiated, but prior to the moment the first request from client is sent
        ...                
}

But how will it help me? The method determines the way to retrieve the providers, not the moment in time they are retrieved. This method is invoked when StaticPermissionDefinitionStore singleton is instantiated: at this time I still don't have my CorePermissionDefinitionProvider available - it's added to the collection only when the application is authenticated and sends the first authenticated request.

Probably I don't see something obvious?

Hi. I've used the Guard you provided and put breakpoint in canActivate method. So when I click "Logout" - I'm being redirected... by the moment the breakpoint is fired, the hasValidAccessToken is true and I'm landed to Home page (instead of Login page of Identity Server). If it is the problem of server-side - like the revocation is not done correctly or some token is not cleared or something else - I ask you to help me sort this out. I've put the fragment of the log from Identity Server above if it could come in handy. Unfortunately, I cannot send the project (it's commercial) or reproduce this on some test project (it would take a while trying to create such project). What I can do is to follow your instructions as for what to check and where.

hi

I found a new discuss, You can take a look https://github.com/abpframework/abp/issues/4448

I've seen this discussion before... The workaround with making PermissionDefinitionManager a ITransientDependency and using try-catch block looks like a last resort. @realLiangshiwei mentions an alternative - using "Refresh" method, but does not go into details. I wonder what does this "Refresh" method need to look like, probably this one would fit me: in my middleware I would need to "refresh" the list of static permissions so that static permissions would "see" a newly-added permission definition provider... But looking at the relevant ABP classes, I'm not sure what is the proper way to do that.

Showing 21 to 30 of 267 entries
Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11