/// <summary>
        /// Retrieves all the applications associated with the specified redirect_uri.
        /// </summary>
        /// <param name="address">The redirect_uri associated with the applications.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
        /// <returns>The client applications corresponding to the specified redirect_uri.</returns>
        public IAsyncEnumerable <TApplication> FindByRedirectUriAsync(
            [NotNull] string address, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(address))
            {
                throw new ArgumentException("The address cannot be null or empty.", nameof(address));
            }

            var parameters = new
            {
                Method  = nameof(FindByRedirectUriAsync),
                Address = address
            };

            if (_cache.TryGetValue(parameters, out ImmutableArray <TApplication> applications))
            {
                return(applications.ToAsyncEnumerable());
            }

            async IAsyncEnumerable <TApplication> ExecuteAsync()
            {
                var applications = ImmutableArray.CreateRange(await _store.FindByRedirectUriAsync(
                                                                  address, cancellationToken).ToListAsync(cancellationToken));

                foreach (var application in applications)
                {
                    await AddAsync(application, cancellationToken);
                }

                using (var entry = _cache.CreateEntry(parameters))
                {
                    foreach (var application in applications)
                    {
                        var signal = await CreateExpirationSignalAsync(application, cancellationToken);

                        if (signal == null)
                        {
                            throw new InvalidOperationException("An error occurred while creating an expiration signal.");
                        }

                        entry.AddExpirationToken(signal);
                    }

                    entry.SetSize(applications.Length);
                    entry.SetValue(applications);
                }

                foreach (var application in applications)
                {
                    yield return(application);
                }
            }

            return(ExecuteAsync());
        }
예제 #2
0
    public async Task FindByRedirectUriAsync_Should_Return_Empty_If_Not_Found()
    {
        var applications = await _applicationStore.FindByRedirectUriAsync("non-existing-uri", CancellationToken.None).ToListAsync();

        applications.Count.ShouldBe(0);
    }