Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V1.1 changes to Information endpoint #58

Merged
merged 8 commits into from
Sep 8, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions src/WinGet.RestSource.Functions/ManifestSearchFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace Microsoft.WinGet.RestSource.Functions
using Microsoft.WinGet.RestSource.Constants;
using Microsoft.WinGet.RestSource.Exceptions;
using Microsoft.WinGet.RestSource.Functions.Common;
using Microsoft.WinGet.RestSource.Models;
using Microsoft.WinGet.RestSource.Models;
using Microsoft.WinGet.RestSource.Models.Arrays;
using Microsoft.WinGet.RestSource.Models.Schemas;
using Microsoft.WinGet.RestSource.Validators;

Expand Down Expand Up @@ -55,7 +56,8 @@ public async Task<IActionResult> ManifestSearchPostAsync(
Dictionary<string, string> headers = null;
ManifestSearchRequest manifestSearch = null;
ApiDataPage<ManifestSearchResponse> manifestSearchResponse = new ApiDataPage<ManifestSearchResponse>();

PackageMatchFields unsupportedFields;
PackageMatchFields requiredFields;
try
{
// Parse Headers
Expand All @@ -65,7 +67,10 @@ public async Task<IActionResult> ManifestSearchPostAsync(
manifestSearch = await Parser.StreamParser<ManifestSearchRequest>(req.Body, log);
ApiDataValidator.Validate(manifestSearch);

manifestSearchResponse = await this.dataStore.SearchPackageManifests(manifestSearch, headers, req.Query);
manifestSearchResponse = await this.dataStore.SearchPackageManifests(manifestSearch, headers, req.Query);

unsupportedFields = UnsupportedAndRequiredFieldsHelper.GetUnsupportedPackageMatchFieldsFromSearchRequest(manifestSearch, ApiConstants.UnsupportedPackageMatchFields);
requiredFields = UnsupportedAndRequiredFieldsHelper.GetRequiredPackageMatchFieldsFromSearchRequest(manifestSearch, ApiConstants.RequiredPackageMatchFields);
}
catch (DefaultException e)
{
Expand All @@ -76,13 +81,13 @@ public async Task<IActionResult> ManifestSearchPostAsync(
{
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)),
};
}
return new ApiObjectResult(new SearchApiResponse<List<ManifestSearchResponse>>(manifestSearchResponse.Items?.ToList(), manifestSearchResponse.ContinuationToken)
{
UnsupportedPackageMatchFields = unsupportedFields,
RequiredPackageMatchFields = requiredFields,
});
}
}
}
17 changes: 15 additions & 2 deletions src/WinGet.RestSource.Functions/PackageManifestFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace Microsoft.WinGet.RestSource.Functions
using Microsoft.WinGet.RestSource.Exceptions;
using Microsoft.WinGet.RestSource.Functions.Common;
using Microsoft.WinGet.RestSource.Models;
using Microsoft.WinGet.RestSource.Models.Arrays;
using Microsoft.WinGet.RestSource.Models.Errors;
using Microsoft.WinGet.RestSource.Models.Schemas;
using Microsoft.WinGet.RestSource.Validators;
Expand Down Expand Up @@ -188,6 +189,8 @@ public async Task<IActionResult> ManifestGetAsync(
{
Dictionary<string, string> headers = null;
ApiDataPage<PackageManifest> manifests = new ApiDataPage<PackageManifest>();
QueryParameters unsupportedQueryParameters;
QueryParameters requiredQueryParameters;

try
{
Expand All @@ -196,6 +199,8 @@ public async Task<IActionResult> ManifestGetAsync(

// Schema supports query parameters only when PackageIdentifier is specified.
manifests = await this.dataStore.GetPackageManifests(packageIdentifier, string.IsNullOrWhiteSpace(packageIdentifier) ? null : req.Query);
unsupportedQueryParameters = UnsupportedAndRequiredFieldsHelper.GetUnsupportedQueryParametersFromRequest(req.Query, ApiConstants.UnsupportedQueryParameters);
requiredQueryParameters = UnsupportedAndRequiredFieldsHelper.GetRequiredQueryParametersFromRequest(req.Query, ApiConstants.RequiredQueryParameters);
}
catch (DefaultException e)
{
Expand All @@ -211,8 +216,16 @@ public async Task<IActionResult> ManifestGetAsync(
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)),
1 => new ApiObjectResult(new GetPackageManifestApiResponse<PackageManifest>(manifests.Items.First(), manifests.ContinuationToken)
{
UnsupportedQueryParameters = unsupportedQueryParameters,
RequiredQueryParameters = requiredQueryParameters,
}),
_ => new ApiObjectResult(new GetPackageManifestApiResponse<List<PackageManifest>>(manifests.Items.ToList(), manifests.ContinuationToken)
{
UnsupportedQueryParameters = unsupportedQueryParameters,
RequiredQueryParameters = requiredQueryParameters,
}),
};
}
}
Expand Down
123 changes: 123 additions & 0 deletions src/WinGet.RestSource/Common/UnsupportedAndRequiredFieldsHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// -----------------------------------------------------------------------
// <copyright file="UnsupportedAndRequiredFieldsHelper.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------

namespace Microsoft.WinGet.RestSource.Common
{
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.WinGet.RestSource.Constants;
using Microsoft.WinGet.RestSource.Models.Arrays;
using Microsoft.WinGet.RestSource.Models.Schemas;

/// <summary>
/// Unsupported and required fields helper.
/// </summary>
public static class UnsupportedAndRequiredFieldsHelper
{
/// <summary>
/// Helper method to get the list of unsupported package match fields from search request.
/// </summary>
/// <param name="manifestSearchRequest">Manifest search request.</param>
/// <param name="unsupportedPackageMatchFields">List of unsupported package match fields by server.</param>
/// <returns>List of unsupported package match fields.</returns>
public static PackageMatchFields GetUnsupportedPackageMatchFieldsFromSearchRequest(
ManifestSearchRequest manifestSearchRequest, PackageMatchFields unsupportedPackageMatchFields)
{
PackageMatchFields unsupportedList = new PackageMatchFields();
foreach (var field in unsupportedPackageMatchFields)
{
if ((manifestSearchRequest.Inclusions != null && manifestSearchRequest.Inclusions.Any(x => x.PackageMatchField.ToLower().Equals(field.ToLower())))
|| (manifestSearchRequest.Filters != null && manifestSearchRequest.Filters.Any(x => x.PackageMatchField.ToLower().Equals(field.ToLower()))))
{
unsupportedList.Add(field);
}
}

return unsupportedList;
}

/// <summary>
/// Helper method to get the list of required package match fields from search request.
/// </summary>
/// <param name="manifestSearchRequest">Manifest search request.</param>
/// <param name="requiredPackageMatchFields">List of required package match fields by server.</param>
/// <returns>List of required package match fields.</returns>
public static PackageMatchFields GetRequiredPackageMatchFieldsFromSearchRequest(
ManifestSearchRequest manifestSearchRequest, PackageMatchFields requiredPackageMatchFields)
{
PackageMatchFields requiredFields = new PackageMatchFields();
if ((manifestSearchRequest.Inclusions == null || manifestSearchRequest.Inclusions.Count == 0) &&
(manifestSearchRequest.Filters == null || manifestSearchRequest.Filters.Count == 0))
{
return requiredPackageMatchFields;
}

foreach (var field in requiredPackageMatchFields)
{
if (!((manifestSearchRequest.Inclusions != null && manifestSearchRequest.Inclusions.Any(x => x.PackageMatchField.ToLower().Equals(field.ToLower())))
|| (manifestSearchRequest.Filters != null && manifestSearchRequest.Filters.Any(x => x.PackageMatchField.ToLower().Equals(field.ToLower())))))
{
requiredFields.Add(field);
}
}

return requiredFields;
}

/// <summary>
/// Helper method to get the list of unsupported query parameters from the request.
/// </summary>
/// <param name="queryParameters">Query parameters input.</param>
/// <param name="unsupportedQueryParameters">List of unsupported query parameters by server.</param>
/// <returns>List of unsupported query parameters.</returns>
public static QueryParameters GetUnsupportedQueryParametersFromRequest(
IQueryCollection queryParameters, QueryParameters unsupportedQueryParameters)
{
QueryParameters unsupportedList = new QueryParameters();

if (queryParameters == null || queryParameters.Count == 0)
{
return unsupportedList;
}

foreach (var field in unsupportedQueryParameters)
{
if (queryParameters.ContainsKey(field))
{
unsupportedList.Add(field);
}
}

return unsupportedList;
}

/// <summary>
/// Helper method to get the list of required query parameters from the request.
/// </summary>
/// <param name="queryParameters">Query parameters input.</param>
/// <param name="requiredQueryParameters">List of required query parameters by server.</param>
/// <returns>List of required query parameters.</returns>
public static QueryParameters GetRequiredQueryParametersFromRequest(
IQueryCollection queryParameters, QueryParameters requiredQueryParameters)
{
QueryParameters requiredList = new QueryParameters();
if (queryParameters == null || queryParameters.Count == 0)
{
return requiredQueryParameters;
}

foreach (var field in requiredQueryParameters)
{
if (!queryParameters.ContainsKey(field))
{
requiredList.Add(field);
}
}

return requiredList;
}
}
}
25 changes: 25 additions & 0 deletions src/WinGet.RestSource/Constants/ApiConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,33 @@ public class ApiConstants
public static readonly ApiVersions ServerSupportedVersions = new ApiVersions()
{
"1.0.0",
"1.1.0",
};

/// <summary>
/// Unsupported package match fields.
/// Note: NormalizedPackageNameAndPublisher field support is currently not implemented. There is a GitHub issue for this.
ashpatil-msft marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
public static readonly PackageMatchFields UnsupportedPackageMatchFields = new PackageMatchFields()
{
Enumerations.PackageMatchFields.NormalizedPackageNameAndPublisher,
};

/// <summary>
/// Required package match fields.
/// </summary>
public static readonly PackageMatchFields RequiredPackageMatchFields = new PackageMatchFields();

/// <summary>
/// Unsupported query parameters.
/// </summary>
public static readonly QueryParameters UnsupportedQueryParameters = new QueryParameters();

/// <summary>
/// Required query paramters.
/// </summary>
public static readonly QueryParameters RequiredQueryParameters = new QueryParameters();

/// <summary>
/// Gets server Identifier.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/WinGet.RestSource/Cosmos/CosmosDataStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ public async Task<ApiDataPage<PackageManifest>> GetPackageManifests(string packa
{
if (pm.Versions != null)
{
pm.Versions = new VersionsExtended(pm.Versions.Where(extended => extended.Channel.Equals(channelFilter)));
pm.Versions = new VersionsExtended(pm.Versions.Where(extended => extended.Channel != null && extended.Channel.Equals(channelFilter)));
}
}
}
Expand Down
29 changes: 29 additions & 0 deletions src/WinGet.RestSource/Models/Arrays/PackageMatchFields.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// -----------------------------------------------------------------------
// <copyright file="PackageMatchFields.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------

namespace Microsoft.WinGet.RestSource.Models.Arrays
{
using Microsoft.WinGet.RestSource.Models.Core;

/// <summary>
/// PackageMatchFields.
/// </summary>
public class PackageMatchFields : ApiArray<string>
{
private const bool Nullable = true;
private const bool Unique = true;

/// <summary>
/// Initializes a new instance of the <see cref="PackageMatchFields"/> class.
/// </summary>
public PackageMatchFields()
{
this.APIArrayName = nameof(PackageMatchFields);
this.AllowNull = Nullable;
this.UniqueItems = Unique;
}
}
}
29 changes: 29 additions & 0 deletions src/WinGet.RestSource/Models/Arrays/QueryParameters.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// -----------------------------------------------------------------------
// <copyright file="QueryParameters.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------

namespace Microsoft.WinGet.RestSource.Models.Arrays
{
using Microsoft.WinGet.RestSource.Models.Core;

/// <summary>
/// QueryParameters.
/// </summary>
public class QueryParameters : ApiArray<string>
{
private const bool Nullable = true;
private const bool Unique = true;

/// <summary>
/// Initializes a new instance of the <see cref="QueryParameters"/> class.
/// </summary>
public QueryParameters()
{
this.APIArrayName = nameof(QueryParameters);
this.AllowNull = Nullable;
this.UniqueItems = Unique;
}
}
}
42 changes: 42 additions & 0 deletions src/WinGet.RestSource/Models/GetPackageManifestApiResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// -----------------------------------------------------------------------
// <copyright file="GetPackageManifestApiResponse.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------

namespace Microsoft.WinGet.RestSource.Common
{
using Microsoft.WinGet.RestSource.Models;
using Microsoft.WinGet.RestSource.Models.Arrays;
using Newtonsoft.Json;

/// <summary>
/// This will wrap API responses that need additional data.
/// </summary>
/// <typeparam name="T">Response Type.</typeparam>
public class GetPackageManifestApiResponse<T> : ApiResponse<T>
where T : class
{
/// <summary>
/// Initializes a new instance of the <see cref="GetPackageManifestApiResponse{T}"/> class.
/// </summary>
/// <param name="data">Data.</param>
/// <param name="continuationToken">Continuation Token.</param>
public GetPackageManifestApiResponse(T data, string continuationToken = null)
: base(data, continuationToken)
{
}

/// <summary>
/// Gets or sets UnsupportedQueryParameters.
/// </summary>
[JsonProperty(Order = 2)]
public QueryParameters UnsupportedQueryParameters { get; set; }

/// <summary>
/// Gets or sets RequiredQueryParameters.
/// </summary>
[JsonProperty(Order = 3)]
public QueryParameters RequiredQueryParameters { get; set; }
}
}
Loading