< Summary

Information
Class: Elsa.Identity.Services.MemoryUserStore
Assembly: Elsa.Identity
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/Services/MemoryUserStore.cs
Line coverage
100%
Covered lines: 34
Uncovered lines: 0
Coverable lines: 34
Total lines: 94
Line coverage: 100%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
SaveAsync(...)100%11100%
DeleteAsync(...)100%22100%
FindManyAsync(...)100%11100%
FindAsync(...)100%11100%
Filter(...)100%11100%
IsVisible(...)100%11100%
ApplyCurrentTenant(...)100%44100%
Clone(...)100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Identity/Services/MemoryUserStore.cs

#LineLine coverage
 1using Elsa.Common.Entities;
 2using Elsa.Common.Multitenancy;
 3using Elsa.Common.Services;
 4using Elsa.Identity.Contracts;
 5using Elsa.Identity.Entities;
 6using Elsa.Identity.Models;
 7
 8namespace Elsa.Identity.Services;
 9
 10/// <summary>
 11/// Represents an in-memory user store.
 12/// </summary>
 13/// <remarks>
 14/// Ambient tenant is applied here rather than in callers.
 15/// EF owns that via <c>SetTenantIdFilter</c> / <c>ApplyTenantId</c>; Memory must compensate.
 16/// Null tenant IDs are visible only to the default tenant.
 17/// </remarks>
 18public class MemoryUserStore : IUserStore
 19{
 20    private readonly MemoryStore<User> _store;
 21    private readonly ITenantAccessor _tenantAccessor;
 22
 23    /// <summary>
 24    /// Initializes a new instance of the <see cref="MemoryUserStore"/> class.
 25    /// </summary>
 2026    public MemoryUserStore(MemoryStore<User> store, ITenantAccessor tenantAccessor)
 27    {
 2028        _store = store;
 2029        _tenantAccessor = tenantAccessor;
 2030    }
 31
 32    /// <inheritdoc />
 33    public Task SaveAsync(User user, CancellationToken cancellationToken = default)
 34    {
 2935        lock (_store.Sync)
 36        {
 2937            ApplyCurrentTenant(user);
 6238            MemoryIdentityUniqueness.EnsureAvailable(_store, user, x => x.Name, "name");
 5239            _store.Save(user, x => x.Id);
 2640        }
 41
 2642        return Task.CompletedTask;
 43    }
 44
 45    /// <inheritdoc />
 46    public Task DeleteAsync(UserFilter filter, CancellationToken cancellationToken = default)
 47    {
 248        lock (_store.Sync)
 49        {
 250            _store.DeleteWhere(user =>
 651                IsVisible(user) && filter.Apply(new[] { user }.AsQueryable()).Any());
 252        }
 53
 254        return Task.CompletedTask;
 55    }
 56
 57    /// <inheritdoc />
 58    public Task<IEnumerable<User>> FindManyAsync(UserFilter filter, CancellationToken cancellationToken = default)
 59    {
 460        var result = _store.Query(query => Filter(query, filter)).Select(Clone).ToList();
 261        return Task.FromResult<IEnumerable<User>>(result);
 62    }
 63
 64    /// <inheritdoc />
 65    public Task<User?> FindAsync(UserFilter filter, CancellationToken cancellationToken = default)
 66    {
 3267        var result = _store.Query(query => Filter(query, filter)).Select(Clone).FirstOrDefault();
 1668        return Task.FromResult(result);
 69    }
 70
 71    private IQueryable<User> Filter(IQueryable<User> queryable, UserFilter filter) =>
 1872        filter.Apply(queryable.WhereVisibleToTenant(_tenantAccessor.TenantId));
 73
 474    private bool IsVisible(Entity entity) => TenantVisibility.IsVisible(entity.TenantId, _tenantAccessor.TenantId);
 75
 76    private void ApplyCurrentTenant(Entity entity)
 77    {
 2978        if (entity.TenantId == Tenant.AgnosticTenantId)
 579            return;
 80
 2481        entity.TenantId ??= _tenantAccessor.TenantId;
 2482    }
 83
 84    private static User Clone(User user) =>
 1785        new()
 1786        {
 1787            Id = user.Id,
 1788            Name = user.Name,
 1789            TenantId = user.TenantId,
 1790            HashedPassword = user.HashedPassword,
 1791            HashedPasswordSalt = user.HashedPasswordSalt,
 1792            Roles = user.Roles.ToList()
 1793        };
 94}