| | | 1 | | using Elsa.Common.Models; |
| | | 2 | | using Elsa.ExternalAuthentication.Contracts; |
| | | 3 | | using Elsa.ExternalAuthentication.Models; |
| | | 4 | | using Elsa.ExternalAuthentication.Services; |
| | | 5 | | |
| | | 6 | | namespace Elsa.ExternalAuthentication.Stores.InMemory; |
| | | 7 | | |
| | | 8 | | /// <summary> |
| | | 9 | | /// Single-node default connection store. Durable hosts replace this registration with their persistence implementation. |
| | | 10 | | /// </summary> |
| | | 11 | | public sealed class InMemoryIdentityProviderConnectionStore : IIdentityProviderConnectionStore |
| | | 12 | | { |
| | 29 | 13 | | private readonly object _sync = new(); |
| | 29 | 14 | | private readonly Dictionary<string, IdentityProviderConnection> _connections = new(StringComparer.Ordinal); |
| | | 15 | | |
| | | 16 | | public ValueTask<Page<IdentityProviderConnection>> FindAsync(ConnectionFilter filter, CancellationToken cancellation |
| | | 17 | | { |
| | 79 | 18 | | cancellationToken.ThrowIfCancellationRequested(); |
| | 79 | 19 | | lock (_sync) |
| | | 20 | | { |
| | 79 | 21 | | IEnumerable<IdentityProviderConnection> query = _connections.Values; |
| | 79 | 22 | | if (!string.IsNullOrWhiteSpace(filter.Search)) |
| | | 23 | | { |
| | 0 | 24 | | var search = filter.Search.Trim(); |
| | 0 | 25 | | query = query.Where(x => x.Key.Contains(search, StringComparison.OrdinalIgnoreCase) || x.DisplayName.Con |
| | | 26 | | } |
| | | 27 | | |
| | 79 | 28 | | if (filter.Scope is { } scope) |
| | 0 | 29 | | query = query.Where(x => string.Equals(x.TenantId, scope.TenantId, StringComparison.Ordinal)); |
| | 79 | 30 | | if (!string.IsNullOrWhiteSpace(filter.AdapterType)) |
| | 0 | 31 | | query = query.Where(x => string.Equals(x.AdapterType, filter.AdapterType, StringComparison.Ordinal)); |
| | 79 | 32 | | if (filter.IsEnabled.HasValue) |
| | 0 | 33 | | query = query.Where(x => x.IsEnabled == filter.IsEnabled.Value); |
| | 79 | 34 | | if (filter.IsArchived.HasValue) |
| | 0 | 35 | | query = query.Where(x => x.ArchivedAt.HasValue == filter.IsArchived.Value); |
| | | 36 | | |
| | 79 | 37 | | var connections = query |
| | 67 | 38 | | .OrderBy(x => x.TenantId, StringComparer.Ordinal) |
| | 67 | 39 | | .ThenBy(x => x.DisplayOrder) |
| | 67 | 40 | | .ThenBy(x => x.Key, StringComparer.Ordinal) |
| | 67 | 41 | | .ThenBy(x => x.Id, StringComparer.Ordinal) |
| | 79 | 42 | | .Select(IdentityProviderConnectionCloner.Clone) |
| | 79 | 43 | | .ToArray(); |
| | 79 | 44 | | return ValueTask.FromResult(Page.Of<IdentityProviderConnection>(connections, connections.Length)); |
| | | 45 | | } |
| | 79 | 46 | | } |
| | | 47 | | |
| | | 48 | | public ValueTask<IdentityProviderConnection?> FindByIdAsync(string id, CancellationToken cancellationToken = default |
| | | 49 | | { |
| | 38 | 50 | | cancellationToken.ThrowIfCancellationRequested(); |
| | 38 | 51 | | lock (_sync) |
| | 38 | 52 | | return ValueTask.FromResult(_connections.TryGetValue(id, out var connection) ? IdentityProviderConnectionClo |
| | 38 | 53 | | } |
| | | 54 | | |
| | | 55 | | public ValueTask<ConnectionMutationResult> CreateAsync(IdentityProviderConnection connection, CancellationToken canc |
| | | 56 | | { |
| | 30 | 57 | | cancellationToken.ThrowIfCancellationRequested(); |
| | 30 | 58 | | lock (_sync) |
| | | 59 | | { |
| | 39 | 60 | | if (_connections.ContainsKey(connection.Id) || _connections.Values.Any(x => string.Equals(x.TenantId, connec |
| | 0 | 61 | | return ValueTask.FromResult<ConnectionMutationResult>(new ConnectionMutationResult.DuplicateKey()); |
| | | 62 | | |
| | 30 | 63 | | var stored = IdentityProviderConnectionCloner.Clone(connection); |
| | 30 | 64 | | stored.Revision = 1; |
| | 30 | 65 | | _connections.Add(stored.Id, stored); |
| | 30 | 66 | | return ValueTask.FromResult<ConnectionMutationResult>(new ConnectionMutationResult.Created(IdentityProviderC |
| | | 67 | | } |
| | 30 | 68 | | } |
| | | 69 | | |
| | | 70 | | public ValueTask<ConnectionMutationResult> UpdateAsync(IdentityProviderConnection connection, long expectedRevision, |
| | | 71 | | { |
| | 19 | 72 | | cancellationToken.ThrowIfCancellationRequested(); |
| | 19 | 73 | | lock (_sync) |
| | | 74 | | { |
| | 19 | 75 | | if (!_connections.TryGetValue(connection.Id, out var current)) |
| | 0 | 76 | | return ValueTask.FromResult<ConnectionMutationResult>(new ConnectionMutationResult.NotFound()); |
| | 19 | 77 | | if (current.Revision != expectedRevision) |
| | 2 | 78 | | return ValueTask.FromResult<ConnectionMutationResult>(new ConnectionMutationResult.RevisionConflict(curr |
| | 34 | 79 | | if (_connections.Values.Any(x => !string.Equals(x.Id, connection.Id, StringComparison.Ordinal) && string.Equ |
| | 0 | 80 | | return ValueTask.FromResult<ConnectionMutationResult>(new ConnectionMutationResult.DuplicateKey()); |
| | | 81 | | |
| | 17 | 82 | | var stored = IdentityProviderConnectionCloner.Clone(connection); |
| | 17 | 83 | | stored.Revision = current.Revision + 1; |
| | 17 | 84 | | _connections[stored.Id] = stored; |
| | 17 | 85 | | return ValueTask.FromResult<ConnectionMutationResult>(new ConnectionMutationResult.Updated(IdentityProviderC |
| | | 86 | | } |
| | 19 | 87 | | } |
| | | 88 | | } |