public async Task <IActionResult> ManifestGetAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, FunctionConstants.FunctionGet, Route = "packageManifests/{packageIdentifier?}")]
            HttpRequest req,
            string packageIdentifier,
            ILogger log)
        {
            Dictionary <string, string>   headers   = null;
            ApiDataPage <PackageManifest> manifests = new ApiDataPage <PackageManifest>();

            try
            {
                // Parse Headers
                headers = HeaderProcessor.ToDictionary(req.Headers);

                manifests = await this.dataStore.GetPackageManifests(packageIdentifier, req.Query);
            }
            catch (DefaultException e)
            {
                log.LogError(e.ToString());
                return(ActionResultHelper.ProcessError(e.InternalRestError));
            }
            catch (Exception e)
            {
                log.LogError(e.ToString());
                return(ActionResultHelper.UnhandledError(e));
            }

            return(manifests.Items.Count switch
            {
                0 => new NoContentResult(),
                1 => new ApiObjectResult(new ApiResponse <PackageManifest>(manifests.Items.First(), manifests.ContinuationToken)),
                _ => new ApiObjectResult(new ApiResponse <List <PackageManifest> >(manifests.Items.ToList(), manifests.ContinuationToken)),
            });
Ejemplo n.º 2
0
        /// <inheritdoc />
        public async Task <ApiDataPage <Package> > GetPackages(string packageIdentifier, IQueryCollection queryParameters)
        {
            // Process Continuation token
            string continuationToken = null;

            if (queryParameters != null)
            {
                continuationToken = queryParameters[QueryConstants.ContinuationToken];
            }

            continuationToken = continuationToken != null?StringEncoder.DecodeContinuationToken(continuationToken) : null;

            // Create feed options
            FeedOptions feedOptions = new FeedOptions
            {
                ResponseContinuationTokenLimitInKb = CosmosConnectionConstants.ResponseContinuationTokenLimitInKb,
                EnableCrossPartitionQuery          = true,
                MaxItemCount        = FunctionSettingsConstants.MaxResultsPerPage,
                RequestContinuation = continuationToken,
            };

            // Get iQueryable
            IQueryable <CosmosPackageManifest> query = this.cosmosDatabase.GetIQueryable <CosmosPackageManifest>(feedOptions);

            if (!string.IsNullOrWhiteSpace(packageIdentifier))
            {
                query = query.Where(package => package.PackageIdentifier.Equals(packageIdentifier));
            }

            // Finalize Query
            IDocumentQuery <CosmosPackageManifest> documentQuery = query.AsDocumentQuery();

            // Fetch Current Package
            ApiDataPage <CosmosPackageManifest> apiDataDocument =
                await this.cosmosDatabase.GetByDocumentQuery <CosmosPackageManifest>(documentQuery);

            // Get Versions and convert.
            ApiDataPage <Package> packages = new ApiDataPage <Package>();

            foreach (CosmosPackageManifest result in apiDataDocument.Items)
            {
                packages.Items.Add(result.ToPackage());
            }

            packages.ContinuationToken = apiDataDocument.ContinuationToken != null?StringEncoder.EncodeContinuationToken(apiDataDocument.ContinuationToken) : null;

            return(packages);
        }
Ejemplo n.º 3
0
        /// <inheritdoc />
        public async Task <ApiDataPage <Locale> > GetLocales(string packageIdentifier, string packageVersion, string packageLocale, IQueryCollection queryParameters)
        {
            // Process Continuation token
            string continuationToken = null;

            if (queryParameters != null)
            {
                continuationToken = queryParameters[QueryConstants.ContinuationToken];
            }

            continuationToken = continuationToken != null?StringEncoder.DecodeContinuationToken(continuationToken) : null;

            // Fetch Current Package
            CosmosDocument <CosmosPackageManifest> cosmosDocument =
                await this.cosmosDatabase.GetByIdAndPartitionKey <CosmosPackageManifest>(packageIdentifier, packageIdentifier);

            // Get Versions and convert.
            ApiDataPage <Locale> locales = new ApiDataPage <Locale>();

            locales.Items             = cosmosDocument.Document.GetLocale(packageLocale, packageVersion).Select(locale => new Locale(locale)).ToList();
            locales.ContinuationToken = null;
            return(locales);
        }
        public async Task <IActionResult> ManifestSearchPostAsync(
            [HttpTrigger(AuthorizationLevel.Anonymous, FunctionConstants.FunctionPost, Route = "manifestSearch")]
            HttpRequest req,
            ILogger log)
        {
            Dictionary <string, string>          headers                = null;
            ManifestSearchRequest                manifestSearch         = null;
            ApiDataPage <ManifestSearchResponse> manifestSearchResponse = new ApiDataPage <ManifestSearchResponse>();

            try
            {
                // Parse Headers
                headers = HeaderProcessor.ToDictionary(req.Headers);

                // Get Manifest Search Request and Validate.
                manifestSearch = await Parser.StreamParser <ManifestSearchRequest>(req.Body, log);

                ApiDataValidator.Validate(manifestSearch);

                manifestSearchResponse = await this.dataStore.SearchPackageManifests(manifestSearch, headers, req.Query);
            }
            catch (DefaultException e)
            {
                log.LogError(e.ToString());
                return(ActionResultHelper.ProcessError(e.InternalRestError));
            }
            catch (Exception e)
            {
                log.LogError(e.ToString());
                return(ActionResultHelper.UnhandledError(e));
            }

            return(manifestSearchResponse.Items.Count() switch
            {
                0 => new NoContentResult(),
                _ => new ApiObjectResult(new ApiResponse <List <ManifestSearchResponse> >(manifestSearchResponse.Items.ToList(), manifestSearchResponse.ContinuationToken)),
            });
        /// <inheritdoc />
        public async Task <ApiDataPage <T> > GetByDocumentQuery <T>(IDocumentQuery <T> documentQuery)
            where T : class
        {
            ApiDataPage <T> apiDataPage = new ApiDataPage <T>();

            try
            {
                FeedResponse <T> response = await documentQuery.ExecuteNextAsync <T>();

                apiDataPage.ContinuationToken = response.ResponseContinuation;
                apiDataPage.Items             = response.ToList <T>();
            }
            catch (DocumentClientException documentClientException)
            {
                throw new CosmosDatabaseException(documentClientException);
            }
            catch (Exception exception)
            {
                throw new DefaultException(exception);
            }

            // Return the model
            return(apiDataPage);
        }
Ejemplo n.º 6
0
        /// <inheritdoc />
        public async Task <ApiDataPage <ManifestSearchResponse> > SearchPackageManifests(ManifestSearchRequest manifestSearchRequest, Dictionary <string, string> headers, IQueryCollection queryParameters)
        {
            // Create Working Set and return
            ApiDataPage <ManifestSearchResponse> apiDataPage     = new ApiDataPage <ManifestSearchResponse>();
            List <PackageManifest>        manifests              = new List <PackageManifest>();
            List <ManifestSearchResponse> manifestSearchResponse = new List <ManifestSearchResponse>();

            // Create feed options for inclusion search: -1 so we can get all matches in inclusion, then filter down.
            FeedOptions feedOptions = new FeedOptions
            {
                ResponseContinuationTokenLimitInKb = CosmosConnectionConstants.ResponseContinuationTokenLimitInKb,
                EnableCrossPartitionQuery          = true,
                MaxItemCount        = AllElements,
                RequestContinuation = null,
            };

            if (manifestSearchRequest.FetchAllManifests || (manifestSearchRequest.Inclusions == null && manifestSearchRequest.Query == null))
            {
                IQueryable <CosmosPackageManifest>     query           = this.cosmosDatabase.GetIQueryable <CosmosPackageManifest>(feedOptions);
                IDocumentQuery <CosmosPackageManifest> documentQuery   = query.AsDocumentQuery();
                ApiDataPage <CosmosPackageManifest>    apiDataDocument = await this.cosmosDatabase.GetByDocumentQuery <CosmosPackageManifest>(documentQuery);

                manifests.AddRange(apiDataDocument.Items);
            }
            else
            {
                // Process Inclusions
                Models.Arrays.SearchRequestPackageMatchFilter inclusions = new Models.Arrays.SearchRequestPackageMatchFilter();
                if (manifestSearchRequest.Inclusions != null)
                {
                    inclusions.AddRange(manifestSearchRequest.Inclusions);
                }

                // Convert Query to inclusions to submit to cosmos
                if (manifestSearchRequest.Query != null)
                {
                    inclusions.AddRange(this.queryList.Select(q => new Models.Objects.SearchRequestPackageMatchFilter()
                    {
                        PackageMatchField = q,
                        RequestMatch      = manifestSearchRequest.Query,
                    }));
                }

                // Submit Inclusions to Cosmos
                // Due to join limitation on Cosmos - we are submitting each predicate separately.
                // TODO: Create a more efficient search - but this will suffice for now for a light weight reference.
                if (inclusions.Count > 0)
                {
                    List <Task <ApiDataPage <PackageManifest> > > taskSet = new List <Task <ApiDataPage <PackageManifest> > >();
                    foreach (string packageMatchField in inclusions.Select(inc => inc.PackageMatchField).Distinct())
                    {
                        // Create Predicate for search
                        ExpressionStarter <PackageManifest> inclusionPredicate = PredicateBuilder.New <PackageManifest>();
                        foreach (SearchRequestPackageMatchFilter matchFilter in inclusions.Where(inc => inc.PackageMatchField.Equals(packageMatchField)))
                        {
                            // Some package match fields or types might not be supported by current version of search.
                            // So we will check the supported list before adding any predicates.
                            if (this.IsPackageMatchFieldSupported(matchFilter.PackageMatchField) &&
                                this.IsMatchTypeSupported(matchFilter.RequestMatch.MatchType))
                            {
                                inclusionPredicate.Or(this.QueryPredicate(matchFilter.PackageMatchField, matchFilter.RequestMatch));
                            }
                        }

                        // Create Document Query
                        IQueryable <PackageManifest> query = this.cosmosDatabase.GetIQueryable <PackageManifest>(feedOptions);
                        query = query.Where(inclusionPredicate);
                        IDocumentQuery <PackageManifest> documentQuery = query.AsDocumentQuery();

                        // Submit Query to Cosmos
                        taskSet.Add(Task.Run(() => this.cosmosDatabase.GetByDocumentQuery(documentQuery)));
                    }

                    // Wait for Cosmos Queries to complete
                    await Task.WhenAll(taskSet.ToArray());

                    // Process Manifests from Cosmos
                    foreach (Task <ApiDataPage <PackageManifest> > task in taskSet)
                    {
                        manifests.AddRange(task.Result.Items);
                    }

                    manifests = manifests.Distinct().ToList();
                }
            }

            // Process Filters
            if (manifestSearchRequest.Filters != null)
            {
                ExpressionStarter <PackageManifest> filterPredicate = PredicateBuilder.New <PackageManifest>();
                foreach (SearchRequestPackageMatchFilter matchFilter in manifestSearchRequest.Filters)
                {
                    if (this.IsPackageMatchFieldSupported(matchFilter.PackageMatchField) &&
                        this.IsMatchTypeSupported(matchFilter.RequestMatch.MatchType))
                    {
                        filterPredicate.Or(this.QueryPredicate(matchFilter.PackageMatchField, matchFilter.RequestMatch));
                    }
                }

                manifests = manifests.Where(filterPredicate).ToList();
            }

            foreach (PackageManifest manifest in manifests)
            {
                foreach (ManifestSearchResponse response in ManifestSearchResponse.GetSearchVersions(manifest))
                {
                    manifestSearchResponse.Add(response);
                }
            }

            // Consolidate Results
            manifestSearchResponse = ManifestSearchResponse.Consolidate(manifestSearchResponse).OrderBy(manifest => manifest.PackageIdentifier).ToList();

            // Process results
            if (manifestSearchResponse.Count > manifestSearchRequest.MaximumResults && manifestSearchRequest.MaximumResults > 0)
            {
                manifestSearchResponse = manifestSearchResponse.GetRange(0, manifestSearchRequest.MaximumResults);
            }

            int maxPageCount = manifestSearchRequest.MaximumResults < FunctionSettingsConstants.MaxResultsPerPage && manifestSearchRequest.MaximumResults > 0
                ? manifestSearchRequest.MaximumResults
                : FunctionSettingsConstants.MaxResultsPerPage;

            int totalResults = manifestSearchResponse.Count;

            if (totalResults > maxPageCount)
            {
                // Process Continuation Token
                ApiContinuationToken token = null;
                if (headers.ContainsKey(HeaderConstants.ContinuationToken))
                {
                    token = Parser.StringParser <ApiContinuationToken>(StringEncoder.DecodeContinuationToken(headers[HeaderConstants.ContinuationToken]));
                }
                else
                {
                    token = new ApiContinuationToken()
                    {
                        Index       = 0,
                        MaxPageSize = maxPageCount,
                    };
                }

                // If index miss-match dump results and return no content.
                if (token.Index > manifestSearchResponse.Count - 1)
                {
                    manifestSearchResponse = new List <ManifestSearchResponse>();
                    token = null;
                }
                else
                {
                    int elementsRemaining = totalResults - token.Index;
                    int elements          = elementsRemaining < token.MaxPageSize ? elementsRemaining : token.MaxPageSize;
                    manifestSearchResponse = manifestSearchResponse.GetRange(token.Index, elements);

                    token.Index += elements;
                    if (token.Index == totalResults)
                    {
                        token = null;
                    }
                }

                apiDataPage.ContinuationToken = token != null?StringEncoder.EncodeContinuationToken(FormatJSON.None(token)) : null;
            }

            apiDataPage.Items = ManifestSearchResponse.Consolidate(manifestSearchResponse.ToList());

            return(apiDataPage);
        }
Ejemplo n.º 7
0
        /// <inheritdoc />
        public async Task <ApiDataPage <PackageManifest> > GetPackageManifests(string packageIdentifier, IQueryCollection queryParameters)
        {
            // Process Continuation token
            string continuationToken = null;

            if (queryParameters != null)
            {
                continuationToken = queryParameters[QueryConstants.ContinuationToken];
            }

            continuationToken = continuationToken != null?StringEncoder.DecodeContinuationToken(continuationToken) : null;

            // Create feed options
            FeedOptions feedOptions = new FeedOptions
            {
                ResponseContinuationTokenLimitInKb = CosmosConnectionConstants.ResponseContinuationTokenLimitInKb,
                EnableCrossPartitionQuery          = true,
                MaxItemCount        = FunctionSettingsConstants.MaxResultsPerPage,
                RequestContinuation = continuationToken,
            };

            // Get iQueryable
            IQueryable <PackageManifest> query = this.cosmosDatabase.GetIQueryable <PackageManifest>(feedOptions);

            if (!string.IsNullOrWhiteSpace(packageIdentifier))
            {
                query = query.Where(package => package.PackageIdentifier.Equals(packageIdentifier));
            }

            // Finalize Query
            IDocumentQuery <PackageManifest> documentQuery = query.AsDocumentQuery();

            // Fetch Current Package
            ApiDataPage <PackageManifest> apiDataDocument =
                await this.cosmosDatabase.GetByDocumentQuery <PackageManifest>(documentQuery);

            apiDataDocument.ContinuationToken = apiDataDocument.ContinuationToken != null?StringEncoder.EncodeContinuationToken(apiDataDocument.ContinuationToken) : null;

            // Apply Version Filter
            string versionFilter = queryParameters[QueryConstants.Version];

            if (!string.IsNullOrEmpty(versionFilter))
            {
                foreach (PackageManifest pm in apiDataDocument.Items)
                {
                    if (pm.Versions != null)
                    {
                        pm.Versions = new VersionsExtended(pm.Versions.Where(extended => extended.PackageVersion.Equals(versionFilter)));
                    }
                }
            }

            // Apply Channel Filter
            string channelFilter = queryParameters[QueryConstants.Channel];

            if (!string.IsNullOrEmpty(channelFilter))
            {
                foreach (PackageManifest pm in apiDataDocument.Items)
                {
                    if (pm.Versions != null)
                    {
                        pm.Versions = new VersionsExtended(pm.Versions.Where(extended => extended.Channel.Equals(channelFilter)));
                    }
                }
            }

            return(apiDataDocument);
        }