The biggest issue cause the pages that contain a swimlane datatable component. I can observe that the page size is correct until the table data gets loaded: after this, the column widths are not properly calculated, so the grid does not fit the card container and makes it wider than a visible window area. The scrollable area is not present either and thus, the grid also does not fit a visible window height.
Here is the screenshot to give you the idea:

Also, the mentioned ABP pages ignore page resize event.
We have a central management of permissions used across the solutions in one of the solutions. We use Redis to store the permissions and this part works fine.
The issue is that in order to display the localized names of permissions, we need to include DomainSharedModule of each solution into the management solution which does not seem right and creates coupling:
[DependsOn(typeof(OtherSolution1DomainSharedModule), typeof(...) ...)]
public class ManagementDomainSharedModule : AbpModule { ... }
How to avoid coupling, but still be able to display the localized names of all the permissions from the cache?
8.1.3 / OpenIDServer / Angular
I have noticed that an inactive login can successfully login from "Linked accounts" dialog. To fix this, I have added the following code into OpenIDServer project:
    public class AbxValidateUserStatusHandler : IOpenIddictServerHandler<ProcessSignInContext>, ITransientDependency
    {
        private readonly IdentityUserManager _userManager;
        private readonly IAbxUserRepository _abxUserRepository;
        private readonly IStringLocalizer<CentralToolsResource> _stringLocalizer;
    
        public AbxValidateUserStatusHandler
        (
            IdentityUserManager userManager,
            IStringLocalizer<CentralToolsResource> stringLocalizer,
            IAbxUserRepository abxUserRepository
        )
        {
            _userManager = userManager;
            _stringLocalizer = stringLocalizer;
            _abxUserRepository = abxUserRepository;
        }
    
        public async ValueTask HandleAsync(ProcessSignInContext context)
        {
            var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;
            if (!string.IsNullOrWhiteSpace(userId))
            {
                var user = await _userManager.FindByIdAsync(userId);
    
                var abxUser = await _abxUserRepository.GetAsync(user.Id);
                if (abxUser != null)
                {
                    var dateNow = DateTime.Now.Date;
                    if (abxUser.ValidFrom.HasValue && dateNow < abxUser.ValidFrom.Value)
                    {
                        context.Reject
                        (
                            error: OpenIddictConstants.Errors.AccessDenied,
                            description: _stringLocalizer.GetString("Login:InvalidDateForUser")
                        );
                        return;
                    }
                    if (abxUser.ValidTo.HasValue && dateNow > abxUser.ValidTo.Value)
                    {
                        context.Reject
                        (
                            error: OpenIddictConstants.Errors.AccessDenied,
                            description: _stringLocalizer.GetString("Login:InvalidDateForUser")
                        );
                        return;
                    }
                }
            }
        }
    }
    
Basically it works. But not very nice: A) the '/connect/token' response returns code 400 and the following JSON:
    {
      "error": "access_denied",
      "error_description": "This user name is not valid anymore. Please contact your system-administrator"
    }
But error_description is ignored and I only see this:
 I guess this is the reason:
I guess this is the reason:
    this.handleLinkLoginError = (err) => {
            this.toaster.error(err.error?.error); // should be err.error?.error_description ... as everywhere
            return of(null);
    };
B) afterwards, the following ABP method returns js error, because res is null:
    linkLogin(input) {
        return this.identityLinkLoginService.linkLogin(input).pipe(catchError(this.handleLinkLoginError), switchMap(res => {
        if (res.tenant_domain) { // res is NULL!
C) my API calls on home page are invoked (they should not, because nothing has changed - i did not switch to another login) - probably i need to add additional check in my HttpInterceptor to stop this:
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (this.isLoggingOut && !req.url.endsWith('/connect/revocat')) { // too bad we need to hardcode the exact url for logging out
            return EMPTY;
        }
        //another check to handle unsuccessful linked login?
I am trying to retrieve repository using a primitive factory. And getting a proxy wrapper class instead:
Unable to cast object of type 'Castle.Proxies.IBasicRepository
1Proxy_52' to type 'AbxFileManagers.IFileRepository1[AbxFileManagers.IFileEntity]'.
I do not want to inject all the repositories into class constructor, because there are too many of them. Also I saw the recommendation to disable audit logging for my entities - that would allegedly eliminate proxy creation. I do not want it either, I do want to keep audit logging things.
Interface:
public interface IFileRepository<TFile> : IRepository<TFile, Guid> where TFile : class, IFileEntity
Implementation:
[ExposeServices(typeof(IFileRepository<>))]
public class EfCoreFileRepository<TFile> : EfCoreRepository<CoreDbContext, TFile, Guid>, IFileRepository<TFile> where TFile : class, IFileEntity
Factory:
public class FileRepositoryFactory : IScopedDependency
{
    private readonly IServiceProvider _serviceProvider;
    public FileRepositoryFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }
    public IFileRepository<TFile> GetRepository<TFile>(...) where TFile : class, IFileEntity
    {
        ...
        var repositoryType = typeof(IFileRepository<>).MakeGenericType(entityType);
        return (IFileRepository<TFile>)_serviceProvider.GetRequiredService(repositoryType);
    }
}
One of the classes:
public class FixCharacterLargeObject : FixCharacterLargeObjectEntity, IFileEntity
Its interface:
public interface IFileEntity : IEntity<Guid>, IMayHaveCreatorName, IMayHaveLastModifierName, IHasCreationTime, IHasModificationTime
I use a single generic class EfCoreFileRepository, because all the IFileEntityentities share the same methods, I did not want to duplicate the code.
I also tried to make EfCoreFileRepository abstract and inherit from it, but the error is the same.
If this is the best way to accomplish the goal - please let me know (and return the point - I will close the ticket):
    public dynamic GetRepository(AbxFileLocation location, AbxFileType type)
    {
        var repositoryType = typeof(IFileRepository<>).MakeGenericType(AbxFileEntityFactory.GetEntityType(location, type));
    
        var repository = _serviceProvider.GetRequiredService(repositoryType);
    
        if (repository is Castle.DynamicProxy.IProxyTargetAccessor proxyAccessor)
        {
            return proxyAccessor.DynProxyGetTarget(); // Return the real repository implementation
        }
    
        return repository;
    }
We utilize a Hangfire server. So far its module has used a standard EF setup suggested by ABP framework:
public class BatchEntityFrameworkCoreModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.AddAbpDbContext<BatchDbContext>(options =>
        {
            ...
        });
        context.Services.AddAbpDbContext<InternalCoreDbContext>(options =>
        {
            ...
        });
        Configure<AbpDbContextOptions>(options =>
        {
            options.PreConfigure(abpDbContextConfigurationContext =>
            {
                abpDbContextConfigurationContext.DbContextOptions.UseLoggerFactory(LoggerFactory.Create(loggingBuilder => loggingBuilder.AddConsole()));                    
                abpDbContextConfigurationContext.DbContextOptions.EnableSensitiveDataLogging();
            });
           
            options.UseOracle(options => options.MaxBatchSize(100));
            options.UseMultiDb(context.Services.GetConfiguration());
        });
        context.Services.AddTransient<IAuditPropertySetter, Abp.DataExtensions.Entities.LogAuditPropertySetter>();        
        AbxEfSettingProvider.Initialize(context.Services.GetConfiguration());
    }
}
However when we run two time-consuming jobs on this server, the second job raises the exception, if the first job is still in progress:
An attempt was made to use the context instance while it is being configured. A DbContext instance cannot be used inside 'OnConfiguring' since it is still being configured at this point. This can happen if a second operation is started on this context instance before a previous operation completed. Any instance members are not guaranteed to be thread safe.
I have found the solution where a user switches from DbContext to DbContextFactory using the setup:
builder.Services.AddDbContextFactory<PowerBlazorDbContext>(opt => opt.UseSqlServer(builder.Configuration.GetConnectionString("PowerBlazorDb")));    
And then uses the following DI:
public class PowerService : IPowerService
{
    private readonly IDbContextFactory<PowerBlazorDbContext> _contextFactory;
    public PowerService(IDbContextFactory<PowerBlazorDbContext> contextFactory)
    {
        _contextFactory = contextFactory;
    }
    //Accessing the DbContext
    public async Task<...> SomethingAsync(...)
    {
        await using var _context = await _contextFactory.CreateDbContextAsync();
        ...
    }
}
How should we properly switch from AddAbpDbContext to AddDbContextFactory? Or you may have other solutions?
I have already reported this bug before and you adviced me to replace some classes. I did this in the domain module (and closed the bug hoping it would help):
public static class IServiceCollectionExtension
{
    public static void ConfigureStores(this IServiceCollection services)
    {
        services.AddOpenIddict()
            .AddCore(builder =>
            {
                builder
                    .AddApplicationStore<AbxAbpOpenIddictApplicationStore>()
                    .AddAuthorizationStore<AbxAbpOpenIddictAuthorizationStore>()
                    .AddTokenStore<AbxAbpOpenIddictTokenStore>();
            });
    }
}
However I still get the same weird exception - but now with my class name:
[09:50:22 INF] Lock is acquired for TokenCleanupBackgroundWorker [09:50:22 ERR] An exception was thrown while activating Volo.Abp.OpenIddict.Tokens.TokenCleanupService -> ?:OpenIddict.Abstractions.IOpenIddictTokenManager -> Volo.Abp.OpenIddict.Tokens.AbpTokenManager -> Volo.Abp.OpenIddict.Tokens.AbpOpenIddictTokenCache -> AbxEps.OpenIddict.Stores.AbxAbpOpenIddictTokenStore. Autofac.Core.DependencyResolutionException: An exception was thrown while activating Volo.Abp.OpenIddict.Tokens.TokenCleanupService -> ?:OpenIddict.Abstractions.IOpenIddictTokenManager -> Volo.Abp.OpenIddict.Tokens.AbpTokenManager -> Volo.Abp.OpenIddict.Tokens.AbpOpenIddictTokenCache -> AbxEps.OpenIddict.Stores.AbxAbpOpenIddictTokenStore. ---> Autofac.Core.DependencyResolutionException: None of the constructors found on type 'AbxEps.OpenIddict.Stores.AbxAbpOpenIddictTokenStore' can be invoked with the available services and parameters: Cannot resolve parameter 'Volo.Abp.OpenIddict.Tokens.IOpenIddictTokenRepository repository' of constructor 'Void .ctor(Volo.Abp.OpenIddict.Tokens.IOpenIddictTokenRepository, Volo.Abp.Uow.IUnitOfWorkManager, Volo.Abp.Guids.IGuidGenerator, Volo.Abp.OpenIddict.Applications.IOpenIddictApplicationRepository, Volo.Abp.OpenIddict.Authorizations.IOpenIddictAuthorizationRepository, Volo.Abp.OpenIddict.AbpOpenIddictIdentifierConverter, Volo.Abp.OpenIddict.IOpenIddictDbConcurrencyExceptionHandler)'.
See https://autofac.rtfd.io/help/no-constructors-bindable for more info. at Autofac.Core.Activators.Reflection.ReflectionActivator.<>c__DisplayClass14_0.<UseSingleConstructorActivation>b__0(ResolveRequestContext context, Action
1 next) at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Builder.RegistrationBuilder3.<>c__DisplayClass39_0.<OnActivated>b__0(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action1 next) --- End of inner exception stack trace --- at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action1 next) at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest& request) at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest& request) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Volo.Abp.OpenIddict.Tokens.TokenCleanupBackgroundWorker.DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) at Volo.Abp.OpenIddict.Tokens.TokenCleanupBackgroundWorker.DoWorkAsync(PeriodicBackgroundWorkerContext workerContext) at Volo.Abp.BackgroundWorkers.AsyncPeriodicBackgroundWorkerBase.DoWorkAsync(CancellationToken cancellationToken) [09:50:22 ERR] ---------- Exception Data ---------- ActivatorChain = Volo.Abp.OpenIddict.Tokens.TokenCleanupService -> ?:OpenIddict.Abstractions.IOpenIddictTokenManager -> Volo.Abp.OpenIddict.Tokens.AbpTokenManager -> Volo.Abp.OpenIddict.Tokens.AbpOpenIddictTokenCache -> AbxEps.OpenIddict.Stores.AbxAbpOpenIddictTokenStore
I can see this exception after I leave my site unattented overnight (I hibernate my computer at night). Please try to reproduce this bug or at least analyze the exception and offer me the solution. Thank you.
How to avoid this error or even a warning?
WRN (admin) A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.MyObject.Equipment.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Location.System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.MyObject.Equipment.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Component.Configurations.Location. at System.Text.Json.ThrowHelper.ThrowJsonException_SerializerCycleDetected(Int32 maxDepth) at System.Text.Json.Serialization.JsonConverter
1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.Serialization.Metadata.JsonPropertyInfo1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer) at System.Text.Json.Serialization.Converters.ObjectDefaultConverter1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.Serialization.JsonConverter1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.Serialization.Metadata.JsonTypeInfo1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed) at System.Text.Json.Serialization.Metadata.JsonTypeInfo1.SerializeAsObject(Utf8JsonWriter writer, Object rootValue) ... at Volo.Abp.Json.SystemTextJson.JsonConverters.ObjectToInferredTypesConverter.Write(Utf8JsonWriter writer, Object objectToWrite, JsonSerializerOptions options) at System.Text.Json.Serialization.JsonConverter1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.Serialization.JsonConverter1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.Serialization.Metadata.JsonTypeInfo1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed) at System.Text.Json.JsonSerializer.WriteString[TValue](TValue& value, JsonTypeInfo1 jsonTypeInfo) at Volo.Abp.Caching.Utf8JsonDistributedCacheSerializer.Serialize[T](T obj) at Volo.Abp.Caching.DistributedCache`2.<>c__DisplayClass51_0.<
Please make note that I already use this setting in my HttpApiHostModule:
private static void ConfigureSerialization(ServiceConfigurationContext context)
{
    context.Services.AddControllers().AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);
}
But obviously it is not enough for the cache.
Another note is that I really have navigation properties in both cases and I do use them in the EntityFramework code. I just want to exclude circular from the consideration, i.e. if I take component.Configurations - I do not want to read Component from each Configuration and if  take configuration.Component - I do not want further read Configurations of each Component.
I still can't get logout to work consistently in my Angular applications.
First of all, I commented the line - just for your information:
    {
        path: '',
        pathMatch: 'full',
        loadChildren: () => import('@my-home-page-package').then(m => m.MyHomeModule),
        // canActivate: [AuthGuard] // This was a logout blocker
    }
Now: A) If i use this code:
    @Injectable()
    export class MyServerErrorInterceptor implements HttpInterceptor {
      constructor(private router: Router) { }
      intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(
          catchError((error: HttpErrorResponse) => {
            if (error.status === 401) {
              this.router.navigate(['/']);
              return EMPTY;
            } else {
              return throwError(error);
            }
          })
        );
      }
    }
and click "Logout" link in the user menu, the logout seems to be working as expected from tab 1 in the browser. However if I have another page being open from the same site in tab 2 - it is not redirected to Login page: instead, I come up with an empty (no navigation menu) home page shown in this tab;
B) If i replace ['/'] with ['/login'] in the code above - both tabs react on this, however I end up with the endless loop, when both tabs try to do something and it never ends;
Also - if i have only one tab of the application opened in the browser, I still have a weird situation, when after getting connect/revocat request (twice, btw - ??) and several 401 API requests, I see (so i see traditional openid-configuration and so forth), so I am not actually logged out - but redirected to a home page;
C) If i emulate the situation with a token expiration - removing "local storage" data in the browser, I expect to be redirected to Login page on the next request attempt (instead of giving me error 401). So the setting (B) provides this, however setting (A) redirects me to a no-menu home page;
And in general, logout process visually does not look good: I expect if a user clicks "Logout" - he is redirected to Login page straight away. Instead, I see the navigation menu is being disappeared and still observing a home page while some server operations are taking place;
I have some Middleware in my OpenID Server module to do cleaning work on httpContext.Request.Path.Value == "/connect/logout" scenario (B) (but works fine with scenario (A) - the exception does not happen). So I commented it, but it RANDOMLY affected the described scenario (sometimes it did, sometimes it did not):
    public async Task InvokeAsync(HttpContext httpContext, IAbxRequestContext requestContext, IdentityUserManager userManager)
    {
        await _next(httpContext);
    
        if (httpContext.Request.Path.Value == "/connect/logout")
        {
            await OnSessionEndRequestAsync(httpContext, userManager);
        }
    }
    
    private async Task OnSessionEndRequestAsync(HttpContext httpContext, IdentityUserManager userManager)
    {
        try
        {
            var user = await userManager.GetUserAsync(httpContext.User); //IF IT GETS INVOKED AND CRASHES - IT SEEMS TO AFFECT THE LOGOUT
            //Some cleaning routine - accessing DB, removing entries
        }
        catch(Exception ex)
        {
            _logger.LogError(ex, "Session End handling error");
        }
    }
Thus, I have no clue what might be a real root cause of the logout issue.
I kindly ask you to provide me with the correct settings (code) for a front-end and a back-end settings which might be relevant to the situation.
I cannot provide you with our code, sorry.
My suggestion is to start with a root cause of the exception in the call above. It is:
at System.Threading.CancellationToken.ThrowOperationCanceledException() at System.Threading.CancellationToken.ThrowIfCancellationRequested() at Volo.Abp.Identity.IdentityUserStore.FindByIdAsync(String userId, CancellationToken cancellationToken) at Castle.Proxies.IdentityUserManagerProxy.FindByIdAsync_callback(String userId) at Castle.Proxies.Invocations.UserManager
1_FindByIdAsync.InvokeMethodOnTarget() at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.DynamicProxy.AbstractInvocation.ProceedInfo.Invoke() at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func3 proceed) at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo) at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue1.ProceedAsync() at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
whereas httpContext.User is OK (data is ok and it is authenticated).
Moving to Redis server and dynamic permissions allowed us to simplify the process of Role / Permission management. So now Redis cache contains permissions of all the running solutions.
However, one problem remained: localization. One of the solutions contains Role / Permission management page which displays ALL the permissions. But each permission localized name resides in the corresponding solution. We don't want to move the permission localization to a separate project.
The most simple way to resolve this would be to consume all the solutions' Domain.Shared projects:
    options.Resources
        .Add<PermissionManagementResource>("en")
        .AddBaseTypes(typeof(SolutionAResource), typeof(SolutionBResource), typeof(SolutionCResource))
But it would create a coupling we want to avoid. We might have a new solution D in future - which means we will have to modify the code above again.
The question is - what is an alternative way to have localization from all the solutions always actual, but still be able to do search by a localized name after receiving the permissions from all the solutions using
    var permissionListResultDto = await _permissionAppService.GetAsync(RolePermissionValueProvider.ProviderName, role.Name);
    
?
 
                                