Open Closed

User Tracking In ABP Framework #2000


0
[email protected] created

Hi,

We are trying to implement a User tracking system inside our application. Basically we want to know who is logged on currently in the site. We have been investigating several ways to do this, and we were going to implement something like the following:

public interface IActiveUserRepository
{
    Task AddUserAysnc(UserCircuit user);
    Task<IList<UserCircuit>> GetUsers();
}

public class InMemoryActiveUserRepository : IActiveUserRepository
{
    private readonly Dictionary<string, UserCircuit> _activeUsers = new();

    public Task AddUserAysnc(UserCircuit user)
    {
        if (!_activeUsers.ContainsKey(user.UserId))
            _activeUsers.Add(user.UserId, user);

        return Task.CompletedTask;
    }

    public async Task<IList<UserCircuit>> GetUsers()
    {
        return await Task.Run(() => _activeUsers.Values.ToList());
    }
}

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    private readonly IActiveUserRepository _users;

    public CustomAuthStateProvider(IActiveUserRepository users)
    {
        _users = users;
        AuthenticationStateChanged += OnAuthenticationStateChanged;
    }

    private async void OnAuthenticationStateChanged(Task<AuthenticationState> task)
    {
        var user = (await task).User;
        if (user.Identity.IsAuthenticated)
        {
            await _users.AddUserAysnc(new UserCircuit { UserId = user.Identity.Name });
        }
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        throw new System.NotImplementedException();
    }
}

//public class TrackingCircuitHandler : CircuitHandler
//{
//    private readonly HashSet<Circuit> circuits = new();

//    public override Task OnConnectionUpAsync(Circuit circuit,
//        CancellationToken cancellationToken)
//    {
//        circuits.Add(circuit);

//        return Task.CompletedTask;
//    }

//    public override Task OnConnectionDownAsync(Circuit circuit,
//        CancellationToken cancellationToken)
//    {
//        circuits.Remove(circuit);

//        return Task.CompletedTask;
//    }

//    public int ConnectedCircuits => circuits.Count;

//    public IList<Circuit> ActiveCircuits => circuits.ToList();
//}

public class UserCircuit
{
    public string CircuitId { get; set; }
    public string UserId { get; set; }
    public string Username { get; set; } = "Anonymous";
}

The question I have is , how do I access the AuthenticationStateProvider in ABP Framework? When I try to add the AuthenticationStateProvider via Dependecey Injection, I get an error since it already exists in the container.

Is there something out-of-box implemented by the ABP framework, that I can user to get all currently logged in users of the site? If not how is AuthenticationStateProvider implemented / exposed in the ABP framework?

Any help would be greatly appreciated.

Thanks,

Jesse

  • ABP Framework version: v4.4.2
  • UI type: Blazor Server
  • DB provider: EF Core

2 Answer(s)
  • 0
    maliming created
    Support Team

    hi

    The AuthenticationStateProvider is service of Blazor Server not of abp.

    https://github.com/dotnet/aspnetcore/blob/release/5.0/src/Components/Server/src/DependencyInjection/ComponentServiceCollectionExtensions.cs#L80

    You can inject it directly instead of creating a subclass of it.

    return await Task.Run(() => _activeUsers.Values.ToList());

    Use return Task.FromResult(_activeUsers.Values.ToList()); insteadof Task.Run

  • 0
    [email protected] created

    Thanks Maliming.....I figured the issue out, and something wasn't being injected properly. It had nothing to do with ABP code.....

    Thanks for your help.

    Jesse