public override async Task<IResourceDataResult> FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            bool cacheEnabled = this.cacheResolver.IsAsynchronousSupported;
            if (!cacheEnabled)
            {
                return await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);
            }

            bool isDelete = request.Action == ResourceAction.Delete;
            bool isCustomDataPropertyRequest = request.Uri.ResourcePath.ToString().Contains("/customData/");

            if (isCustomDataPropertyRequest && isDelete)
            {
                logger.Trace($"Request {request.Action} {request.Uri} is a custom data property delete, deleting cached property name if exists", "WriteCacheFilter.FilterAsync");
                await this.UncacheCustomDataPropertyAsync(request.Uri.ResourcePath, logger, cancellationToken).ConfigureAwait(false);
            }
            else if (isDelete)
            {
                logger.Trace($"Request {request.Action} {request.Uri} is a resource deletion, purging from cache if exists", "WriteCacheFilter.FilterAsync");
                var cacheKey = this.GetCacheKey(request);
                await this.UncacheAsync(request.Type, cacheKey, cancellationToken).ConfigureAwait(false);
            }

            var result = await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);

            bool isEmailVerificationResponse = result.Type == typeof(IEmailVerificationToken);
            if (isEmailVerificationResponse)
            {
                logger.Trace($"Request {request.Action} {request.Uri} is an email verification request, purging account from cache if exists", "WriteCacheFilter.FilterAsync");
                await this.UncacheAccountOnEmailVerificationAsync(result, cancellationToken).ConfigureAwait(false);
            }

            bool possibleCustomDataUpdate = (request.Action == ResourceAction.Create || request.Action == ResourceAction.Update) &&
                AbstractExtendableInstanceResource.IsExtendable(request.Type);
            if (possibleCustomDataUpdate)
            {
                await this.CacheNestedCustomDataUpdatesAsync(request, result, logger, cancellationToken).ConfigureAwait(false);
            }

            if (IsCacheable(request, result))
            {
                logger.Trace($"Caching request {request.Action} {request.Uri}", "WriteCacheFilter.FilterAsync");
                await this.CacheAsync(result.Type, result.Body, logger, cancellationToken).ConfigureAwait(false);
            }

            return result;
        }
        internal DefaultDataStore(IClient client, IRequestExecutor requestExecutor, string baseUrl, IJsonSerializer serializer, ILogger logger, IUserAgentBuilder userAgentBuilder, ICacheProvider cacheProvider, TimeSpan identityMapExpiration)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            if (requestExecutor == null)
            {
                throw new ArgumentNullException(nameof(requestExecutor));
            }

            if (string.IsNullOrEmpty(baseUrl))
            {
                throw new ArgumentNullException(nameof(baseUrl));
            }

            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            if (cacheProvider == null)
            {
                throw new ArgumentNullException(nameof(cacheProvider), "Use NullCacheProvider if you wish to turn off caching.");
            }

            this.baseUrl          = baseUrl;
            this.logger           = logger;
            this.requestExecutor  = requestExecutor;
            this.cacheProvider    = cacheProvider;
            this.cacheResolver    = new DefaultCacheResolver(cacheProvider, this.logger);
            this.userAgentBuilder = userAgentBuilder;

            this.client            = client;
            this.serializer        = new JsonSerializationProvider(serializer);
            this.identityMap       = new MemoryCacheIdentityMap <ResourceData>(identityMapExpiration, this.logger);
            this.resourceFactory   = new DefaultResourceFactory(this, this.identityMap);
            this.resourceConverter = new DefaultResourceConverter();

            this.uriQualifier = new UriQualifier(baseUrl);

            this.defaultAsyncFilters = this.BuildDefaultAsyncFilterChain();
            this.defaultSyncFilters  = this.BuildDefaultSyncFilterChain();
        }
        public override async Task<IResourceDataResult> FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            bool cacheEnabled =
                this.cacheResolver.IsAsynchronousSupported
                && this.IsCacheRetrievalEnabled(request)
                && !request.SkipCache;
            if (cacheEnabled)
            {
                logger.Trace($"Checking cache for resource {request.Uri}", "ReadCacheFilter.FilterAsync");
                var result = await this.GetCachedResourceDataAsync(request, logger, cancellationToken).ConfigureAwait(false);

                if (result != null)
                {
                    logger.Trace($"Cache hit for {request.Uri}; returning cached data", "ReadCacheFilter.FilterAsync");
                    return result; // short-circuit the remainder of the filter chain
                }

                logger.Trace($"Cache miss for {request.Uri}", "ReadCacheFilter.FilterAsync");
            }

            return await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);
        }
        async Task<IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            var result = await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);

            if (!IsCreateOrUpdate(request))
            {
                return result; // short-circuit
            }

            if (!IsAccountStoreMapping(result))
            {
                return result; // short-circuit
            }

            var applicationHref = GetContainerHref("application", result);
            if (!string.IsNullOrEmpty(applicationHref))
            {
                var application = await chain.DataStore.GetResourceSkipCacheAsync<IApplication>(applicationHref, cancellationToken).ConfigureAwait(false);
                var allMappings = await application.GetAccountStoreMappings().ToListAsync(cancellationToken).ConfigureAwait(false);

                logger.Trace($"AccountStoreMapping update detected; refreshing all {allMappings.Count} AccountStoreMappings in cache for Application '{applicationHref}'", "AccountStoreMappingCacheInvalidationFilter.FilterAsync");

                return result; // done
            }

            var organizationHref = GetContainerHref("organization", result);
            if (!string.IsNullOrEmpty(organizationHref))
            {
                var organization = await chain.DataStore.GetResourceSkipCacheAsync<IOrganization>(organizationHref, cancellationToken).ConfigureAwait(false);
                var allMappings = await organization.GetAccountStoreMappings().ToListAsync(cancellationToken).ConfigureAwait(false);

                logger.Trace($"AccountStoreMapping update detected; refreshing all {allMappings.Count} AccountStoreMappings in cache for Organization '{organizationHref}'", "AccountStoreMappingCacheInvalidationFilter.FilterAsync");

                return result; // done
            }

            throw new NotSupportedException($"Unsupported AccountStore container type: {request.Type.Name}");
        }
        public override async Task <IResourceDataResult> FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            bool cacheEnabled =
                this.cacheResolver.IsAsynchronousSupported &&
                this.IsCacheRetrievalEnabled(request) &&
                !request.SkipCache;

            if (cacheEnabled)
            {
                logger.Trace($"Checking cache for resource {request.Uri}", "ReadCacheFilter.FilterAsync");
                var result = await this.GetCachedResourceDataAsync(request, logger, cancellationToken).ConfigureAwait(false);

                if (result != null)
                {
                    logger.Trace($"Cache hit for {request.Uri}; returning cached data", "ReadCacheFilter.FilterAsync");
                    return(result); // short-circuit the remainder of the filter chain
                }

                logger.Trace($"Cache miss for {request.Uri}", "ReadCacheFilter.FilterAsync");
            }

            return(await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false));
        }
 public abstract Task<IResourceDataResult> FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken);
 Task<IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
 {
     if (request.Action == ResourceAction.Delete)
     {
         return Task.FromResult<IResourceDataResult>(
             new DefaultResourceDataResult(ResourceAction.Delete, null, null, 204, null));
     }
     else
     {
         return chain.FilterAsync(request, logger, cancellationToken);
     }
 }
 Task<IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
 {
     if (request.Action == ResourceAction.Create)
     {
         return Task.FromResult<IResourceDataResult>(new DefaultResourceDataResult(
             ResourceAction.Create,
             typeof(IDictionary<string, object>),
             request.Uri,
             httpStatus: 200,
             body: new Dictionary<string, object>() { { "Foo", "bar" } }));
     }
     else
     {
         return chain.FilterAsync(request, logger, cancellationToken);
     }
 }
 Task <IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
 {
     return(this.filterFunc(request, chain, logger, cancellationToken));
 }
 Task<IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
 {
     return this.filterFunc(request, chain, logger, cancellationToken);
 }
        public override async Task <IResourceDataResult> FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            bool cacheEnabled = this.cacheResolver.IsAsynchronousSupported;

            if (!cacheEnabled)
            {
                return(await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false));
            }

            bool isDelete = request.Action == ResourceAction.Delete;
            bool isCustomDataPropertyRequest = request.Uri.ResourcePath.ToString().Contains("/customData/");

            if (isCustomDataPropertyRequest && isDelete)
            {
                logger.Trace($"Request {request.Action} {request.Uri} is a custom data property delete, deleting cached property name if exists", "WriteCacheFilter.FilterAsync");
                await this.UncacheCustomDataPropertyAsync(request.Uri.ResourcePath, logger, cancellationToken).ConfigureAwait(false);
            }
            else if (isDelete)
            {
                logger.Trace($"Request {request.Action} {request.Uri} is a resource deletion, purging from cache if exists", "WriteCacheFilter.FilterAsync");
                var cacheKey = this.GetCacheKey(request);
                await this.UncacheAsync(request.Type, cacheKey, cancellationToken).ConfigureAwait(false);
            }

            var result = await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);

            bool isEmailVerificationResponse = result.Type == typeof(IEmailVerificationToken);

            if (isEmailVerificationResponse)
            {
                logger.Trace($"Request {request.Action} {request.Uri} is an email verification request, purging account from cache if exists", "WriteCacheFilter.FilterAsync");
                await this.UncacheAccountOnEmailVerificationAsync(result, cancellationToken).ConfigureAwait(false);
            }

            bool possibleCustomDataUpdate = (request.Action == ResourceAction.Create || request.Action == ResourceAction.Update) &&
                                            AbstractExtendableInstanceResource.IsExtendable(request.Type);

            if (possibleCustomDataUpdate)
            {
                await this.CacheNestedCustomDataUpdatesAsync(request, result, logger, cancellationToken).ConfigureAwait(false);
            }

            if (IsCacheable(request, result))
            {
                logger.Trace($"Caching request {request.Action} {request.Uri}", "WriteCacheFilter.FilterAsync");
                await this.CacheAsync(result.Type, result.Body, logger, cancellationToken).ConfigureAwait(false);
            }

            return(result);
        }
        async Task <IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            var result = await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);

            if (!IsCreateOrUpdate(request))
            {
                return(result); // short-circuit
            }

            if (!IsAccountStoreMapping(result))
            {
                return(result); // short-circuit
            }

            var applicationHref = GetContainerHref("application", result);

            if (!string.IsNullOrEmpty(applicationHref))
            {
                var application = await chain.DataStore.GetResourceSkipCacheAsync <IApplication>(applicationHref, cancellationToken).ConfigureAwait(false);

                var allMappings = await application.GetAccountStoreMappings().ToListAsync(cancellationToken).ConfigureAwait(false);

                logger.Trace($"AccountStoreMapping update detected; refreshing all {allMappings.Count} AccountStoreMappings in cache for Application '{applicationHref}'", "AccountStoreMappingCacheInvalidationFilter.FilterAsync");

                return(result); // done
            }

            var organizationHref = GetContainerHref("organization", result);

            if (!string.IsNullOrEmpty(organizationHref))
            {
                var organization = await chain.DataStore.GetResourceSkipCacheAsync <IOrganization>(organizationHref, cancellationToken).ConfigureAwait(false);

                var allMappings = await organization.GetAccountStoreMappings().ToListAsync(cancellationToken).ConfigureAwait(false);

                logger.Trace($"AccountStoreMapping update detected; refreshing all {allMappings.Count} AccountStoreMappings in cache for Organization '{organizationHref}'", "AccountStoreMappingCacheInvalidationFilter.FilterAsync");

                return(result); // done
            }

            throw new NotSupportedException($"Unsupported AccountStore container type: {request.Type.Name}");
        }
示例#13
0
 Task <IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
 {
     if (request.Action == ResourceAction.Delete)
     {
         return(Task.FromResult <IResourceDataResult>(
                    new DefaultResourceDataResult(ResourceAction.Delete, null, null, 204, null)));
     }
     else
     {
         return(chain.FilterAsync(request, logger, cancellationToken));
     }
 }
示例#14
0
 Task <IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
 {
     if (request.Action == ResourceAction.Create)
     {
         return(Task.FromResult <IResourceDataResult>(new DefaultResourceDataResult(
                                                          ResourceAction.Create,
                                                          typeof(IDictionary <string, object>),
                                                          request.Uri,
                                                          httpStatus: 200,
                                                          body: new Dictionary <string, object>()
         {
             { "Foo", "bar" }
         })));
     }
     else
     {
         return(chain.FilterAsync(request, logger, cancellationToken));
     }
 }
        async Task<IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            var result = await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);

            return FilterCore(result);
        }
示例#16
0
 public abstract Task <IResourceDataResult> FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken);
        async Task <IResourceDataResult> IAsynchronousFilter.FilterAsync(IResourceDataRequest request, IAsynchronousFilterChain chain, ILogger logger, CancellationToken cancellationToken)
        {
            var result = await chain.FilterAsync(request, logger, cancellationToken).ConfigureAwait(false);

            return(FilterCore(result));
        }