Base solution for your next web application

Activities of "JapNolt"

EDIT: I posted to soon. The code below works for sending messages to clients but does not help with tracking a count of clients or if a user is online.

I recently encountered the same problem and decided to use the Groups feature in SignalR. This blog article recommended that and per my limited testing, it works well https://consultwithgriff.com/signalr-connection-ids/

In the OnConnectedAsync, I add the connection to a group for the tenant and also to a group for the user. I would recommend that ANZ adopt this approach because I believe it would work with either a single server or a scaled out system.

I am willing to share more code if you wish.

Here's an example of how I extended the AbpCommonHub

` public class AbpCommonHubExtended : AbpCommonHub { private readonly IOnlineClientManager _onlineClientManager;

    public AbpCommonHubExtended(
        IOnlineClientManager onlineClientManager,
        IOnlineClientInfoProvider clientInfoProvider) : base(onlineClientManager, clientInfoProvider)
    {
        _onlineClientManager = onlineClientManager;
    }

    public override async Task OnConnectedAsync()
    {
        await base.OnConnectedAsync();

        var client = _onlineClientManager.GetByConnectionIdOrNull(Context.ConnectionId);

        await Groups.AddToGroupAsync(
            client.ConnectionId,
            GetGroupName_AllClientsForTenant(
                client.TenantId.GetValueOrDefault()));

        await Groups.AddToGroupAsync(
            client.ConnectionId,
            GetGroupName_AllClientsForUser(
                client.TenantId.GetValueOrDefault(),
                client.UserId.GetValueOrDefault()));
    }

    public static string GetGroupName_AllClientsForTenant(int tenantId)
    {
        return $"t_{tenantId}";
    }
    public static string GetGroupName_AllClientsForUser(int tenantId, long userId)
    {
        return $"t_{tenantId}_u_{userId}";
    }
}

`

Another solution that is possible is to use SignalR Groups although admittedly it does require changes in both the hub and also when sending the message. I have some thoughts about this on this other thread: https://support.aspnetzero.com/QA/Questions/11117/Microsoft-signalR-is-not-working-with-multiple-instances#answer-4522399e-6457-858f-7bdc-3a0504ccce6e

I saw here: https://support.aspnetzero.com/QA/Questions/7845/UserAccount-table-purpose-Multitenancy that it looks like the UserAccounts table is used just for the linked accounts feature. I was wondering if we don't want that feature can we override the Abp.Authorization.Users.UserAccountSynchronizer and simply not save that data there? We are wanting to use a different database for a tenant and they don't want that data outside their database.

If I don't care about using that feature either is it ok to override the UserAccountSynchronizer? Or is there something else I an do to not save that data?

Question

There is a security vulnerability on the register and login page as reported in this issue:

https://github.com/aspnetzero/aspnet-zero-core/issues/4649

Is there a workaround for this?

Our project is hosted in azure and is replicated across 3 nodes. There seems to be an issue with the Dashboard where we receive a "page not found" exception on a brand new dashboard(or after resetting to default) when clicking add new widget. The default dashboard definition creates a page with a unique id (guid), which seems to be cached locally but not in our redis cache, and so wont be the same id when the next api call is fetched and it hits a different node.

This video shows the issue: https://landiscomputer-my.sharepoint.com/:v:/g/personal/gavin_landistechnologies_com/EViEe61wZJlCvFYme4gIsdUBEknxr4_v-JVvViMdSOD4KQ?e=xg52jc

Also this shows every third request, works as expected, when the api hits the first node that generated the dashboard definition: https://landiscomputer-my.sharepoint.com/:v:/g/personal/gavin_landistechnologies_com/EVek59wkW5FHg5bQryj1vGIByoxZBx8qe5DQ5-ul63Zhpw?e=LwXmkL

What is the recommend solution to this?

Hi @japnolt

Sorry for the late reply. Are you using Redis on your app ?

Yes we are using redis on our app as well as using the per request redis.

Any update on this?

Here is the related error logs:

Audit Logs

Input Prams: { "input": { "dashboardName": "TenantDashboard", "application": "Angular", "pageId": "Page3e4759efcafa4ed5a09096a59fa2a175" } }

Error state: Abp.UI.UserFriendlyException: [Unknown page] at DashboardCustomization.DashboardCustomizationAppService.GetAllAvailableWidgetDefinitionsForPage(GetAvailableWidgetDefinitionsForPageInput input) in C:**\2**\src***.Application\DashboardCustomization\DashboardCustomizationAppService.cs:line 205 at lambda_method10582(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Logged|12_1(ControllerActionInvoker invoker) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

UserFriendlyException.Code:0 UserFriendlyException.Details:

App Service(Kudu)

WARN 2023-08-14 13:44:42,518 [62 ] Mvc.ExceptionHandling.AbpExceptionFilter - [Unknown page] Abp.UI.UserFriendlyException: [Unknown page] at ***.DashboardCustomization.DashboardCustomizationAppService.GetAllAvailableWidgetDefinitionsForPage(GetAvailableWidgetDefinitionsForPageInput input) in C:\**\**\2\s\src\***.Application\DashboardCustomization\DashboardCustomizationAppService.cs:line 205 at lambda_method10582(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

Alright, thanks. Is there any workaround we can use for now for this?

Showing 41 to 50 of 57 entries