Skip to content

Commit 2fe8167

Browse files
committed
Create Owner Details URI Template resources
1 parent 252bbee commit 2fe8167

8 files changed

Lines changed: 140 additions & 1 deletion

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
#nullable enable
5+
6+
using System;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using NuGet.Protocol.Core.Types;
10+
using NuGet.Protocol.Resources;
11+
12+
namespace NuGet.Protocol.Providers
13+
{
14+
/// <summary>NuGet.Protocol resource provider for <see cref="OwnerDetailsUriTemplateResourceV3"/> in V3 HTTP feeds.</summary>
15+
/// <remarks>When successful, returns an instance of <see cref="OwnerDetailsUriTemplateResourceV3"/>.</remarks>
16+
public class OwnerDetailsUriResourceV3Provider : ResourceProvider
17+
{
18+
public OwnerDetailsUriResourceV3Provider()
19+
: base(typeof(OwnerDetailsUriTemplateResourceV3),
20+
nameof(OwnerDetailsUriTemplateResourceV3),
21+
NuGetResourceProviderPositions.Last)
22+
{
23+
}
24+
25+
/// <inheritdoc cref="ResourceProvider.TryCreate(SourceRepository, CancellationToken)"/>
26+
public override async Task<Tuple<bool, INuGetResource?>> TryCreate(SourceRepository source, CancellationToken token)
27+
{
28+
OwnerDetailsUriTemplateResourceV3? resource = null;
29+
ServiceIndexResourceV3? serviceIndex = await source.GetResourceAsync<ServiceIndexResourceV3>(token);
30+
if (serviceIndex != null)
31+
{
32+
Uri uriTemplate = serviceIndex.GetServiceEntryUri(ServiceTypes.OwnerDetailsUriTemplate);
33+
resource = OwnerDetailsUriTemplateResourceV3.CreateOrNull(uriTemplate);
34+
}
35+
36+
return new Tuple<bool, INuGetResource?>(resource != null, resource);
37+
}
38+
}
39+
}

src/NuGet.Core/NuGet.Protocol/PublicAPI/net472/PublicAPI.Unshipped.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
#nullable enable
2+
NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider
3+
NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider.OwnerDetailsUriResourceV3Provider() -> void
4+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3
5+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.GetUri(string! owner) -> System.Uri!
6+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.OwnerDetailsUriTemplateResourceV3(string! template) -> void
7+
override NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository! source, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task<System.Tuple<bool, NuGet.Protocol.Core.Types.INuGetResource?>!>!
8+
static NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.CreateOrNull(System.Uri? uriTemplate) -> NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3?
29
~NuGet.Protocol.Core.Types.IPackageSearchMetadata.OwnersList.get -> System.Collections.Generic.IReadOnlyList<string>
310
~NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.OwnersList.get -> System.Collections.Generic.IReadOnlyList<string>
411
~NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.OwnersList.set -> void

src/NuGet.Core/NuGet.Protocol/PublicAPI/netcoreapp5.0/PublicAPI.Unshipped.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
#nullable enable
2+
NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider
3+
NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider.OwnerDetailsUriResourceV3Provider() -> void
4+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3
5+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.GetUri(string! owner) -> System.Uri!
6+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.OwnerDetailsUriTemplateResourceV3(string! template) -> void
7+
override NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository! source, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task<System.Tuple<bool, NuGet.Protocol.Core.Types.INuGetResource?>!>!
8+
static NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.CreateOrNull(System.Uri? uriTemplate) -> NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3?
29
~NuGet.Protocol.Core.Types.IPackageSearchMetadata.OwnersList.get -> System.Collections.Generic.IReadOnlyList<string>
310
~NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.OwnersList.get -> System.Collections.Generic.IReadOnlyList<string>
411
~NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.OwnersList.set -> void

src/NuGet.Core/NuGet.Protocol/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
#nullable enable
2+
NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider
3+
NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider.OwnerDetailsUriResourceV3Provider() -> void
4+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3
5+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.GetUri(string! owner) -> System.Uri!
6+
NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.OwnerDetailsUriTemplateResourceV3(string! template) -> void
7+
override NuGet.Protocol.Providers.OwnerDetailsUriResourceV3Provider.TryCreate(NuGet.Protocol.Core.Types.SourceRepository! source, System.Threading.CancellationToken token) -> System.Threading.Tasks.Task<System.Tuple<bool, NuGet.Protocol.Core.Types.INuGetResource?>!>!
8+
static NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3.CreateOrNull(System.Uri? uriTemplate) -> NuGet.Protocol.Resources.OwnerDetailsUriTemplateResourceV3?
29
~NuGet.Protocol.Core.Types.IPackageSearchMetadata.OwnersList.get -> System.Collections.Generic.IReadOnlyList<string>
310
~NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.OwnersList.get -> System.Collections.Generic.IReadOnlyList<string>
411
~NuGet.Protocol.Core.Types.PackageSearchMetadataBuilder.ClonedPackageSearchMetadata.OwnersList.set -> void

src/NuGet.Core/NuGet.Protocol/Repository.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public virtual IEnumerable<Lazy<INuGetResourceProvider>> GetCoreV3()
8181
yield return new Lazy<INuGetResourceProvider>(() => new PluginResourceProvider());
8282
yield return new Lazy<INuGetResourceProvider>(() => new RepositorySignatureResourceProvider());
8383
yield return new Lazy<INuGetResourceProvider>(() => new VulnerabilityInfoResourceV3Provider());
84+
yield return new Lazy<INuGetResourceProvider>(() => new OwnerDetailsUriResourceV3Provider());
8485

8586
// Local repository providers
8687
yield return new Lazy<INuGetResourceProvider>(() => new FindLocalPackagesResourceUnzippedProvider());
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
#nullable enable
5+
6+
using System;
7+
using NuGet.Protocol.Core.Types;
8+
9+
namespace NuGet.Protocol.Resources
10+
{
11+
/// <summary>Owner Details Uri Template for NuGet V3 HTTP feeds.</summary>
12+
/// <remarks>Not intended to be created directly. Use <see cref="SourceRepository.GetResourceAsync{T}(CancellationToken)"/>
13+
/// with <see cref="OwnerDetailsUriTemplateResourceV3"/> for T, and typecast to this class.
14+
public class OwnerDetailsUriTemplateResourceV3 : INuGetResource
15+
{
16+
private readonly string _template;
17+
18+
public OwnerDetailsUriTemplateResourceV3(string template)
19+
{
20+
_template = template ?? throw new ArgumentNullException(nameof(template));
21+
}
22+
23+
/// <summary>
24+
/// Creates the specified Owner Details Uri template provided by the server if it exists and is valid.
25+
/// </summary>
26+
/// <param name="uriTemplate">The Absolute Uri template provided by the server.</param>
27+
/// <returns>A valid Owner Details Uri template, or null.</returns>
28+
public static OwnerDetailsUriTemplateResourceV3? CreateOrNull(Uri? uriTemplate)
29+
{
30+
if (uriTemplate == null || uriTemplate.OriginalString.Length == 0 || !uriTemplate.IsAbsoluteUri)
31+
{
32+
return null;
33+
}
34+
35+
string absoluteUri = uriTemplate.OriginalString;
36+
if (string.IsNullOrWhiteSpace(absoluteUri)
37+
|| !IsValidUriTemplate(absoluteUri))
38+
{
39+
return null;
40+
}
41+
42+
return new OwnerDetailsUriTemplateResourceV3(absoluteUri);
43+
}
44+
45+
private static bool IsValidUriTemplate(string absoluteUri)
46+
{
47+
Uri? uri;
48+
var isValidUri = Uri.TryCreate(absoluteUri, UriKind.Absolute, out uri);
49+
50+
// Only allow HTTPS owner details URLs.
51+
if (isValidUri && uri?.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase) != true)
52+
{
53+
return false;
54+
}
55+
56+
return isValidUri;
57+
}
58+
59+
/// <summary>
60+
/// Gets a URL for viewing package Owner URL outside of Visual Studio. The URL will not be verified to exist.
61+
/// </summary>
62+
/// <param name="owner">The owner username.</param>
63+
/// <returns>The first URL from the resource, with the URI template applied.</returns>
64+
public Uri GetUri(string owner)
65+
{
66+
var uriString = _template
67+
#if NETCOREAPP
68+
.Replace("{owner}", owner, StringComparison.OrdinalIgnoreCase);
69+
#else
70+
.Replace("{owner}", owner);
71+
#endif
72+
73+
return new Uri(uriString);
74+
}
75+
}
76+
}

src/NuGet.Core/NuGet.Protocol/ServiceTypes.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public static class ServiceTypes
1717
public static readonly string Version500 = "/5.0.0";
1818
public static readonly string Version510 = "/5.1.0";
1919
internal const string Version670 = "/6.7.0";
20+
internal const string Version6110 = "/6.11.0";
2021

2122
public static readonly string[] SearchQueryService = { "SearchQueryService" + Versioned, "SearchQueryService" + Version340, "SearchQueryService" + Version300beta };
2223
public static readonly string[] RegistrationsBaseUrl = { $"RegistrationsBaseUrl{Versioned}", $"RegistrationsBaseUrl{Version360}", $"RegistrationsBaseUrl{Version340}", $"RegistrationsBaseUrl{Version300rc}", $"RegistrationsBaseUrl{Version300beta}", "RegistrationsBaseUrl" };
@@ -29,5 +30,6 @@ public static class ServiceTypes
2930
public static readonly string[] RepositorySignatures = { "RepositorySignatures" + Version500, "RepositorySignatures" + Version490, "RepositorySignatures" + Version470 };
3031
public static readonly string[] SymbolPackagePublish = { "SymbolPackagePublish" + Version490 };
3132
internal static readonly string[] VulnerabilityInfo = { "VulnerabilityInfo" + Version670 };
33+
internal static readonly string[] OwnerDetailsUriTemplate = { "OwnerDetailsUriTemplate" + Version6110 };
3234
}
3335
}

test/NuGet.Core.Tests/NuGet.Protocol.Tests/RepositoryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void Provider_WithDefaultProvider_ReturnsDefaultResourceProviders()
6363

6464
int actualCount = resourceProviders.Count();
6565

66-
Assert.Equal(47, actualCount);
66+
Assert.Equal(48, actualCount);
6767
}
6868
}
6969
}

0 commit comments

Comments
 (0)