diff --git a/.editorconfig b/.editorconfig index 0d3f804..31d2459 100644 --- a/.editorconfig +++ b/.editorconfig @@ -216,10 +216,10 @@ csharp_style_var_when_type_is_apparent = true dotnet_diagnostic.IDE0007.severity = error dotnet_diagnostic.IDE0008.severity = error -csharp_style_expression_bodied_constructors = true : error +csharp_style_expression_bodied_constructors = false : error dotnet_diagnostic.IDE0021.severity = error -csharp_style_expression_bodied_methods = true : error +csharp_style_expression_bodied_methods = false : error dotnet_diagnostic.IDE0022.severity = error csharp_style_expression_bodied_operators = true : error diff --git a/Directory.Packages.props b/Directory.Packages.props index 69e7ca0..fec0edf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,16 +1,22 @@ - - - true - false - true - true - - - - - - - - - + + + true + false + true + true + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Kentico.Xperience.GoogleMaps.Tests/Extensions/StartupExtensionsTests.cs b/Kentico.Xperience.GoogleMaps.Tests/Extensions/StartupExtensionsTests.cs new file mode 100644 index 0000000..9619bf9 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps.Tests/Extensions/StartupExtensionsTests.cs @@ -0,0 +1,74 @@ +using System.Net.Http.Headers; +using CMS.Tests; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +using NUnit.Framework; + +namespace Kentico.Xperience.GoogleMaps.Tests +{ + /// + /// Tests for class. + /// + public class StartupExtensionsTests + { + [TestFixture] + public class AddGoogleMapsTests : UnitTests + { + private const string APIKEY = "APIKey"; + + private IServiceCollection services; + private IConfiguration configuration; + + + [SetUp] + public void Setup() + { + services = new ServiceCollection(); + } + + + [Test] + public void AddGoogleMaps_ValidOptions_SetupOptionsAddHttpClient() + { + configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { $"{GoogleMapsConstants.SECTION_KEY}:{nameof(GoogleMapsOptions.APIKey)}", APIKEY } + }) + .Build(); + + services.AddGoogleMaps(configuration); + + var serviceProvider = services.BuildServiceProvider(); + var googleMapsOptions = serviceProvider.GetRequiredService>(); + var httpClientFactory = serviceProvider.GetService(); + var httpClient = httpClientFactory.CreateClient(GoogleMapsConstants.CLIENT_NAME); + + Assert.Multiple(() => + { + Assert.That(googleMapsOptions, Is.Not.Null); + Assert.That(googleMapsOptions.Value.APIKey, Is.EqualTo(APIKEY)); + Assert.That(httpClient.DefaultRequestHeaders.Accept, Is.InstanceOf>()); + Assert.That(httpClient.DefaultRequestHeaders.Accept.Contains(new MediaTypeWithQualityHeaderValue("application/json"))); + }); + } + + + [TestCase(null, TestName = "AddGoogleMaps_APIKeyNull_ThrowsException")] + [TestCase("", TestName = "AddGoogleMaps_APIKeyEmpty_ThrowsException")] + public void AddGoogleMaps(string apiKey) + { + configuration = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { $"{GoogleMapsConstants.SECTION_KEY}:{nameof(GoogleMapsOptions.APIKey)}", apiKey }, + }) + .Build(); + + Assert.That(() => services.AddGoogleMaps(configuration), Throws.InvalidOperationException); + } + } + } +} diff --git a/Kentico.Xperience.GoogleMaps.Tests/Kentico.Xperience.GoogleMaps.Tests.csproj b/Kentico.Xperience.GoogleMaps.Tests/Kentico.Xperience.GoogleMaps.Tests.csproj new file mode 100644 index 0000000..e705eaa --- /dev/null +++ b/Kentico.Xperience.GoogleMaps.Tests/Kentico.Xperience.GoogleMaps.Tests.csproj @@ -0,0 +1,31 @@ + + + + net6.0 + enable + disable + + false + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/Kentico.Xperience.GoogleMaps.Tests/Services/AddressValidatorTests.cs b/Kentico.Xperience.GoogleMaps.Tests/Services/AddressValidatorTests.cs new file mode 100644 index 0000000..b679795 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps.Tests/Services/AddressValidatorTests.cs @@ -0,0 +1,229 @@ +using NSubstitute; +using NUnit.Framework; + +namespace Kentico.Xperience.GoogleMaps.Tests +{ + public class AddressValidatorTests + { + [TestFixture] + public class ValidateTests : AddressValidatorTestsBase + { + [Test] + public async Task Validate_ValidAddress_ReturnsExpectedResult() + { + const string VALID_ADDRESS = "1600 Amphitheatre Parkway, Mountain View, CA"; + + MockHttpClient(new List + { + GetMessage(new GeocodeResponse + { + Status = "OK", + Results = new List + { + new() + { + FormattedAddress = VALID_ADDRESS, + }, + }, + }), + GetMessage(new AddressValidationResponse + { + Result = new AddressValidationResult + { + Verdict = new AddressValidationVerdict + { + AddressComplete = true, + }, + Address = new AddressValidationAddress + { + FormattedAddress = VALID_ADDRESS, + }, + }, + }) + }); + + var result = await addressValidator.Validate(VALID_ADDRESS); + + Assert.Multiple(() => + { + Assert.That(result.IsValid, Is.True); + Assert.That(result.FormattedAddress, Is.EqualTo(VALID_ADDRESS)); + Assert.That(NumberOfRequests, Is.EqualTo(2)); + + httpClientFactory.Received(2).CreateClient(GoogleMapsConstants.CLIENT_NAME); + }); + } + + + [Test] + public async Task Validate_InvalidAddress_ReturnsExpectedResult() + { + const string INVALID_ADDRESS = "This is invalid address."; + + MockHttpClient(new List + { + GetMessage(new GeocodeResponse + { + Status = "ZERO_RESULTS", + Results = new List(), + }) + }); + + var result = await addressValidator.Validate(INVALID_ADDRESS); + + Assert.Multiple(() => + { + Assert.That(result.IsValid, Is.False); + Assert.That(NumberOfRequests, Is.EqualTo(1)); + + httpClientFactory.Received(1).CreateClient(GoogleMapsConstants.CLIENT_NAME); + }); + } + + + [Test] + public async Task Validate_CompanyNamesEnabled_ReturnsExpectedResult() + { + const string COMPANY_NAME = "Rockstar Games"; + const string COMPANY_ADDRESS = "622 Broadway, New York, NY 10012, USA"; + + MockHttpClient(new List + { + GetMessage(new GeocodeResponse + { + Status = "OK", + Results = new List + { + new() + { + FormattedAddress = COMPANY_ADDRESS, + }, + }, + }), + GetMessage(new AddressValidationResponse + { + Result = new AddressValidationResult + { + Verdict = new AddressValidationVerdict + { + AddressComplete = true, + }, + Address = new AddressValidationAddress + { + FormattedAddress = COMPANY_ADDRESS, + }, + }, + }) + }); + + var result = await addressValidator.Validate(COMPANY_NAME); + + Assert.Multiple(() => + { + Assert.That(result.IsValid, Is.True); + Assert.That(result.FormattedAddress, Is.EqualTo(COMPANY_ADDRESS)); + Assert.That(NumberOfRequests, Is.EqualTo(2)); + + httpClientFactory.Received(2).CreateClient(GoogleMapsConstants.CLIENT_NAME); + }); + } + + + [Test] + public async Task Validate_CompanyNamesDisabled_ReturnsExpectedResult() + { + const string COMPANY_NAME = "Rockstar Games"; + + MockHttpClient(new List + { + GetMessage(new AddressValidationResponse + { + Result = new AddressValidationResult + { + Verdict = new AddressValidationVerdict + { + AddressComplete = null, + }, + Address = new AddressValidationAddress + { + FormattedAddress = COMPANY_NAME, + }, + }, + }) + }); + + var result = await addressValidator.Validate(COMPANY_NAME, "US", false); + + Assert.Multiple(() => + { + Assert.That(result.IsValid, Is.False); + Assert.That(NumberOfRequests, Is.EqualTo(1)); + + httpClientFactory.Received(1).CreateClient(GoogleMapsConstants.CLIENT_NAME); + }); + } + + + [Test] + public async Task Validate_NotCompleteAddress_ReturnsExpectedResult() + { + const string NOT_COMPLETE_ADDRESS = "Baltimore, MD"; + + MockHttpClient(new List + { + GetMessage(new GeocodeResponse + { + Status = "OK", + Results = new List + { + new() + { + FormattedAddress = NOT_COMPLETE_ADDRESS, + }, + }, + }), + GetMessage(new AddressValidationResponse + { + Result = new AddressValidationResult + { + Verdict = new AddressValidationVerdict + { + AddressComplete = null, + }, + Address = new AddressValidationAddress + { + FormattedAddress = NOT_COMPLETE_ADDRESS, + }, + }, + }) + }); + + var result = await addressValidator.Validate(NOT_COMPLETE_ADDRESS); + + Assert.Multiple(() => + { + Assert.That(result.IsValid, Is.False); + Assert.That(NumberOfRequests, Is.EqualTo(2)); + + httpClientFactory.Received(2).CreateClient(GoogleMapsConstants.CLIENT_NAME); + }); + } + + + [TestCase(null, TestName = "Validate_NullValue_ThrowsException")] + [TestCase("", TestName = "Validate_EmptyValue_ThrowsException")] + public async Task Validate(string value) + { + var result = await addressValidator.Validate(value); + + Assert.Multiple(() => + { + Assert.That(result.IsValid, Is.False); + Assert.That(NumberOfRequests, Is.EqualTo(0)); + + httpClientFactory.Received(0).CreateClient(GoogleMapsConstants.CLIENT_NAME); + }); + } + } + } +} diff --git a/Kentico.Xperience.GoogleMaps.Tests/Services/AddressValidatorTestsBase.cs b/Kentico.Xperience.GoogleMaps.Tests/Services/AddressValidatorTestsBase.cs new file mode 100644 index 0000000..eb8fc43 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps.Tests/Services/AddressValidatorTestsBase.cs @@ -0,0 +1,116 @@ +using System.Net; +using System.Text.Json; +using CMS.Base.Internal; +using CMS.Core; +using CMS.Tests; +using Microsoft.Extensions.Options; +using NSubstitute; +using NUnit.Framework; + +namespace Kentico.Xperience.GoogleMaps.Tests +{ + /// + /// Base class for tests. + /// + public class AddressValidatorTestsBase : UnitTests + { + protected const string API_KEY = "API_KEY"; + protected const string DOMAIN = "http://test.com/"; + + private protected AddressValidator addressValidator; + private protected IHttpClientFactory httpClientFactory; + private protected GoogleMapsOptions options; + private protected IEventLogService eventLogService; + private IHttpContextRetriever httpContextRetriever; + + + public static int NumberOfRequests { get; private set; } + + + protected override void RegisterTestServices() + { + base.RegisterTestServices(); + + httpContextRetriever = Substitute.For(); + Service.Use(httpContextRetriever); + } + + + [SetUp] + public void SetUp() + { + var iOptions = Substitute.For>(); + options = new GoogleMapsOptions + { + APIKey = API_KEY, + }; + + iOptions.Value.Returns(options); + + eventLogService = Substitute.For(); + + httpClientFactory = Substitute.For(); + + MockHttpClient(new List()); + + + var httpContext = Substitute.For(); + var httpRequest = Substitute.For(); + httpRequest.Url.Returns(new Uri(DOMAIN)); + + httpContext.Request.Returns(httpRequest); + httpContextRetriever.GetContext().Returns(httpContext); + + NumberOfRequests = 0; + + addressValidator = new AddressValidator(httpClientFactory, eventLogService, iOptions); + } + + + protected static HttpResponseMessage GetMessage(T content = null, HttpStatusCode statusCode = HttpStatusCode.OK) + where T : class + { + return new HttpResponseMessage + { + StatusCode = statusCode, + Content = new StringContent(JsonSerializer.Serialize(content)) + }; + } + + + /// + /// Used for mocking responses of httpClient. Needed to allow mocking multiple requests in the same method. + /// + /// Responses to use for requests, returned by the given order. + protected void MockHttpClient(IList responseMessages) + { + var httpClient = new HttpClient(new MockHttpMessageHandler(responseMessages)); + httpClientFactory.CreateClient(GoogleMapsConstants.CLIENT_NAME).Returns(httpClient); + } + + + private class MockHttpMessageHandler : HttpMessageHandler + { + private readonly Queue responseMessages; + + + public MockHttpMessageHandler(IEnumerable responseMessages) + { + this.responseMessages = new Queue(responseMessages); + } + + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + return Task.FromResult(Send(request, cancellationToken)); + } + + + protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) + { + NumberOfRequests++; + return responseMessages.Dequeue(); + } + } + } +} diff --git a/Kentico.Xperience.GoogleMaps.Tests/packages.lock.json b/Kentico.Xperience.GoogleMaps.Tests/packages.lock.json new file mode 100644 index 0000000..36b92a6 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps.Tests/packages.lock.json @@ -0,0 +1,984 @@ +{ + "version": 2, + "dependencies": { + "net6.0": { + "Kentico.Xperience.Core.Tests": { + "type": "Direct", + "requested": "[28.4.3, )", + "resolved": "28.4.3", + "contentHash": "H4RunVRGXHi9z/BObfwPugGKLHwNQ/2wGuSXShUjic2aAPxbw3zmx+txIXu35EqPRahiiX7bGejgHLk85wG8sg==", + "dependencies": { + "Kentico.Xperience.Core": "[28.4.3]", + "NUnit": "3.14.0", + "Newtonsoft.Json": "13.0.3", + "System.Configuration.ConfigurationManager": "8.0.0" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.10.0-release-24177-07, )", + "resolved": "17.10.0-release-24177-07", + "contentHash": "OIvw7UlANS20ybCP7orcX4WSfyUc7SUzkAl/Fo51O9IqmSJA0Pa8LW96bQ3c8KFDiV7K5ckSS0QFmyw10C66IA==", + "dependencies": { + "Microsoft.CodeCoverage": "17.10.0-release-24177-07", + "Microsoft.TestPlatform.TestHost": "17.10.0-release-24177-07" + } + }, + "NSubstitute": { + "type": "Direct", + "requested": "[5.1.0, )", + "resolved": "5.1.0", + "contentHash": "ZCqOP3Kpp2ea7QcLyjMU4wzE+0wmrMN35PQMsdPOHYc2IrvjmusG9hICOiqiOTPKN0gJon6wyCn6ZuGHdNs9hQ==", + "dependencies": { + "Castle.Core": "5.1.1" + } + }, + "NUnit": { + "type": "Direct", + "requested": "[4.1.0, )", + "resolved": "4.1.0", + "contentHash": "MT/DpAhjtiytzhTgTqIhBuWx4y26PKfDepYUHUM+5uv4TsryHC2jwFo5e6NhWkApCm/G6kZ80dRjdJFuAxq3rg==" + }, + "NUnit.ConsoleRunner": { + "type": "Direct", + "requested": "[3.17.0, )", + "resolved": "3.17.0", + "contentHash": "XUctGgtqYdWzNiXFdDa1odKlrBWBStEEfv+TOhrtubpXGmNwKZ4GzzZJiq3eK5qpkj2QmPlP583Ffzf/Zr+w6g==" + }, + "NUnit3TestAdapter": { + "type": "Direct", + "requested": "[4.5.0, )", + "resolved": "4.5.0", + "contentHash": "s8JpqTe9bI2f49Pfr3dFRfoVSuFQyraTj68c3XXjIS/MRGvvkLnrg6RLqnTjdShX+AdFUCCU/4Xex58AdUfs6A==" + }, + "SonarAnalyzer.CSharp": { + "type": "Direct", + "requested": "[9.23.1.88495, )", + "resolved": "9.23.1.88495", + "contentHash": "aKrXq94OO1wiMtsBttRd7vRJKFWp/eVeMJrPFB6OIbjbpxEySbKrLmM8Kj1ZF5jqp5yaZGBLMpe6jxodJqPyMg==" + }, + "AngleSharp": { + "type": "Transitive", + "resolved": "0.17.1", + "contentHash": "5MPI4bbixlwxb0W/smOMeIR+QlxMy5/5jD+WnIAw4pBC+7AhLPe5bS3cLgQMJyvd6q0A48sG+uYOt/ep406GLA==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Text.Encoding.CodePages": "6.0.0" + } + }, + "AngleSharp.Css": { + "type": "Transitive", + "resolved": "0.17.0", + "contentHash": "bg0AcugmX6BFEi/DHG61QrwRU8iuiX4H8LZehdIzYdqOM/dgb3BsCTzNIcc1XADn4+xfQEdVwJYTSwUxroL4vg==", + "dependencies": { + "AngleSharp": "[0.17.0, 0.18.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.35.0", + "contentHash": "hENcx03Jyuqv05F4RBEPbxz29UrM3Nbhnr6Wl6NQpoU9BCIbL3XLentrxDCTrH54NLS11Exxi/o8MYgT/cnKFA==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "6.0.1", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.10.3", + "contentHash": "l1Xm2MWOF2Mzcwuarlw8kWQXLZk3UeB55aQXVyjj23aBfDwOZ3gu5GP2kJ6KlmZeZv2TCzw7x4L3V36iNr3gww==", + "dependencies": { + "Azure.Core": "1.35.0", + "Microsoft.Identity.Client": "4.56.0", + "Microsoft.Identity.Client.Extensions.Msal": "4.56.0", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "BananaCakePop.Middleware": { + "type": "Transitive", + "resolved": "13.0.0", + "contentHash": "6Zj/vfmnCXLjBG7WNdtOgZZ5ZDR3Sy1FQSshZUonIYs3OdzozmsFmqPXMd9XJ0QE9aAildgVGq/lDLpLrMI4Yw==", + "dependencies": { + "Yarp.ReverseProxy": "2.0.1" + } + }, + "BouncyCastle.Cryptography": { + "type": "Transitive", + "resolved": "2.3.0", + "contentHash": "IaVIiYxZLaBulveGDRUx/pBoW/Rc8QeXGF5u2E8xL8RWhVKCgfmtX9NUyGRbnSqnbFQU2zyP3MkXIdH+jUuQBw==" + }, + "Castle.Core": { + "type": "Transitive", + "resolved": "5.1.1", + "contentHash": "rpYtIczkzGpf+EkZgDr9CClTdemhsrwA/W5hMoPjLkRFnXzH44zDLoovXeKtmxb1ykXK9aJVODSpiJml8CTw2g==", + "dependencies": { + "System.Diagnostics.EventLog": "6.0.0" + } + }, + "CommandLineParser": { + "type": "Transitive", + "resolved": "2.9.1", + "contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA==" + }, + "GreenDonut": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "T8ZYTsm0S48hi89d2symCvUEJoBkg5F+rfU+HFtkEOc7WLZsIBDStnfF3c890Vxjmx/P1tFpY5StDNTM+C6fIw==", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.0" + } + }, + "HotChocolate": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "aGBAW6d9Oj1MfmKJF482yYdJ8G87yJ0rVFxU9l7lA1dg1xjc5XALLQO9jCPz4GCpQLetuAhHdkZ713imJ6WCPw==", + "dependencies": { + "HotChocolate.Authorization": "13.9.0", + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Fetching": "13.9.0", + "HotChocolate.Types": "13.9.0", + "HotChocolate.Types.CursorPagination": "13.9.0", + "HotChocolate.Types.Mutations": "13.9.0", + "HotChocolate.Types.OffsetPagination": "13.9.0", + "HotChocolate.Validation": "13.9.0" + } + }, + "HotChocolate.Abstractions": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "mb3IPL8V4NRL2FUefZP20fSwIMOnE7uCMLiM4d5Y5cjljYaMUVzUJnvdW9C1tUfbodP49Llk9WnBCR6S9fr8mQ==", + "dependencies": { + "HotChocolate.Language": "13.9.0", + "Microsoft.Bcl.AsyncInterfaces": "6.0.0", + "System.Collections.Immutable": "6.0.0" + } + }, + "HotChocolate.AspNetCore": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "RnxUdKEYOmsjzNPss473CYOug/9GIt8qlS9j8HxtZrW5TASM/9S7pDb7FthcDj4ag/D7wAwme3YxsqxH+iw5Bg==", + "dependencies": { + "BananaCakePop.Middleware": "13.0.0", + "HotChocolate": "13.9.0", + "HotChocolate.Subscriptions.InMemory": "13.9.0", + "HotChocolate.Transport.Sockets": "13.9.0", + "HotChocolate.Types.Scalars.Upload": "13.9.0", + "HotChocolate.Utilities.DependencyInjection": "13.9.0" + } + }, + "HotChocolate.Authorization": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "6CPA39zObNuMUmkmQ6J3zqmalukhjCiJS/klSEDPpwTtrn9HS/3edsh/7oiKzmUh6PNVKGed0lwkSdDP+DGZDQ==", + "dependencies": { + "HotChocolate.Execution": "13.9.0" + } + }, + "HotChocolate.Data": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "eZI9pIipsJsqdacj55krmxx24cUTCearQ/q9wT4aa6vQ/5GwuwWJ0ZIqdcp1qPjd+BsmJixrQBbi6/OgnFXIGw==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types.CursorPagination": "13.9.0" + } + }, + "HotChocolate.Execution": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "zO1aG5qx5lzbZu/iKR56g+zeOgCCCa5pICwxijd1qEap+7J5q0YsME9RByw8wYPH+tNsXCvDcKaeAEcashB4cg==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "HotChocolate.Execution.Abstractions": "13.9.0", + "HotChocolate.Fetching": "13.9.0", + "HotChocolate.Types": "13.9.0", + "HotChocolate.Utilities.DependencyInjection": "13.9.0", + "HotChocolate.Validation": "13.9.0", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "System.Threading.Channels": "6.0.0" + } + }, + "HotChocolate.Execution.Abstractions": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "flySLPDyTtM4051tI3mh5Ue0fGrKFDuW3w0ebWmW2qjfuF4jgQzd3pK3ZxfkxAfpxQXyPaVn/Q7fae+fYQxeCg==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0" + } + }, + "HotChocolate.Fetching": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "pIw7VlEABejQGLRnJGnO7iPdT40AHklf0psJp5zNXrq0IX+Vq7hRRqON73nubZv5Ofhh8fV3kugqYFKvzcptoA==", + "dependencies": { + "GreenDonut": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Language": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "M8q0XHQm8Gtab+wKgYXfVPxScjdDE+INify5yaj6g1ZDkV3sLIeX+muu1WebrNO3DgmuAi6o3aW770Ucw7k/dw==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0", + "HotChocolate.Language.Utf8": "13.9.0", + "HotChocolate.Language.Visitors": "13.9.0", + "HotChocolate.Language.Web": "13.9.0" + } + }, + "HotChocolate.Language.SyntaxTree": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "+vwrQ0qOiKn/yUBHn53030hQmqj45C1g0WI8sip50CPnkgs3bAPnDInUvrR3IiHbRn5spAonO4tFPtMDdJrEMA==", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "6.0.0" + } + }, + "HotChocolate.Language.Utf8": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "IEWNYGvtwejf7+j+Xci25FaYets2UD8wkfzQ5dUCW47c1rnTAyuRdTiO8T8x6LYuZ7+SLg7UTBYgjv4ybwAUgA==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0" + } + }, + "HotChocolate.Language.Visitors": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "j6mPBkfVo2fopWYLoczXCoog4PJ+KwbHItSgHfPfI1kDBcNcy9XY4oxth3Uau1uBbfHYIFjnuVc+FrGb1f9KAQ==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0" + } + }, + "HotChocolate.Language.Web": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "GI5ufbNVEoKygSC09owVnCvw1Ma2KzOtm1l6uen3wKshAdOKB4gmSVCjzf71pNL2Nt6cL4IHa70ClqjECmu9qg==", + "dependencies": { + "HotChocolate.Language.Utf8": "13.9.0" + } + }, + "HotChocolate.Subscriptions": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "P3ason65NwSzkB2W9myV/pRIm4IMIWXH3RPCtpHVKx22Xw3hRJRJhjLBQZ5LCk5v3+7kKhXNBTbFNpbMyvez3Q==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "HotChocolate.Execution.Abstractions": "13.9.0" + } + }, + "HotChocolate.Subscriptions.InMemory": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "rj5U1Cd2QsjNnSNNdlSopYLtXh0kTZ1NlA1B3v02YFtj4Zu9le6QkGsl3oUljUUq46vSkkrT9ISj+e5wTCcw/Q==", + "dependencies": { + "HotChocolate.Execution.Abstractions": "13.9.0", + "HotChocolate.Subscriptions": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0" + } + }, + "HotChocolate.Transport.Sockets": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "4hPlhS2bgqT/tYCZfPtbGtPAaedULKgTbFKkTsjigrDhJcVxBA36Gr3yGM6S3NEw2JdIgiwugYV1log9zXkEjA==", + "dependencies": { + "System.IO.Pipelines": "6.0.0" + } + }, + "HotChocolate.Types": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "VGPZePNC4sBlz/iY4x90zIRxW62MWzWNcl2yjLS3JcW+0W8KuKxh99dFLxL0WY/+Eoe8PUecmoob+FrVEvPzpg==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "HotChocolate.Types.Shared": "13.9.0", + "HotChocolate.Utilities": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.ObjectPool": "6.0.0", + "System.ComponentModel.Annotations": "5.0.0", + "System.Text.Json": "6.0.7" + } + }, + "HotChocolate.Types.CursorPagination": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "2+w6tLrdjo+d/aIKyoNW1L/OH/p+FACMwGWHk1P4MwAspqaF7zjy71qTeNks+8QbRwG8uMleey/0sbr8sWpC6w==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.Mutations": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "NX1zLkb7t19Om5RYubmkA6yRCtBbca454rqSGKSVBYjDrsiA6+4ZDvmS9Kjbw8F+cPm3VqShenrIIgfW8bzCXQ==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.OffsetPagination": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "LIAaSVRS6FJCssP+s4ooLajhQ1/QfES78twX4OgZFJ9/UZMxXlU3K/IWeB2aXcJNkehfIZLgoiROnouB7ATepw==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.Scalars.Upload": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "hisB6PGGgsekz3a8YJwKgvbZHED98eph9+TMPg5A500tyvrZS00fbdpjRcN+rcTKAxhJ5evzHB2Fo1m62Dyo4w==", + "dependencies": { + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.Shared": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "2lhdbXU/GltPQWO9r8qePZSzDo9ryFs8Wv0aF7aQgEq3dLvwer6OpvnZhIYmGua6bXXebA1PzBAEaaxPpLx3Wg==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0" + } + }, + "HotChocolate.Utilities": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "6zqwjROYxtuzAYjh31JnYKgM/MySRWEq4DHO64oSPFRJQ8NDgg7EvUU771yLt/6T7kUh+S6k25hVnmUipFtEnQ==" + }, + "HotChocolate.Utilities.DependencyInjection": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "o1ijY8Rk0IUAo8QZYhfQ8s4/3z78JS9tyXGHzA963gkzTSJPehD4960CAmWlyC19FdE1i2KiTnYLhNOwNoL6+A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0" + } + }, + "HotChocolate.Validation": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "gC7/YfOcOOmT+zV/V45CubYhK3lZI7+SmNYLGXQ1ko4cwjVRh3PzSJMAaKw3naWDcbjXbEyWwdYc0dLuoVBNEA==", + "dependencies": { + "HotChocolate.Types": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "HtmlSanitizer": { + "type": "Transitive", + "resolved": "8.0.843", + "contentHash": "XfmHK4rFz9PPN0gcv7J7pc+MRpcni1mrnO04mwA+9/1zIHLgdOvLJeDwWnX5a+up4tioPvGreB+p+KljLJ32wg==", + "dependencies": { + "AngleSharp": "[0.17.1]", + "AngleSharp.Css": "[0.17.0]", + "System.Collections.Immutable": "8.0.0" + } + }, + "Kentico.Aira.Client": { + "type": "Transitive", + "resolved": "1.0.25", + "contentHash": "Hu3xxl89ZWWU6iGkpnTCIXE/L3DNU+i/ZUZaRESYP6BJANlThPRFCIkrDwNx+daAsda5B/n5iApFzk5nH6qPOA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "7.3.1" + } + }, + "Kentico.Xperience.Core": { + "type": "Transitive", + "resolved": "28.4.3", + "contentHash": "yyQHoVfiABFk7iFrIH81kHqsytzN45/UsSvpNEu3cS7nW1B09nU8GKzwy8Ov4/vKcB8kWZjOSk4g6OG6OydJzA==", + "dependencies": { + "AngleSharp": "0.17.1", + "MailKit": "4.4.0", + "Microsoft.Data.SqlClient": "5.2.0", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.Configuration": "6.0.1", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Localization": "6.0.28", + "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0", + "Mono.Cecil": "0.11.5", + "Newtonsoft.Json": "13.0.3", + "System.CodeDom": "8.0.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "cv+oiAOn2+LhhGUVvxpJjEOIZOTZBFDIDO9ebOfxqqU1f/PllHpKr5VjWOBsqeLrb+zLisxWSQDzM5C64XrRNA==", + "dependencies": { + "MimeKit": "4.4.0" + } + }, + "Microsoft.AspNetCore.SpaServices.Extensions": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "IyI3A40jIxHWKT0BcjxGWHaU24zT3NUrexMwWxWdDxTYHteH97OVHf5dNc0eY4RKybCrAi9C+IWAZ2l7NEFEGg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.10.0-release-24177-07", + "contentHash": "mq5zBpsT40IHOm25aLP9dwWBjT3rH/PyiwiyQ+krHGfp57r9C3MtjTY6WPMtM8DK9osRCBqEGXAjjEkVXpOZAg==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "3alfyqRN3ELRtdvU1dGtLBRNQqprr3TJ0WrUJfMISPwg1nPUN2P3Lelah68IKWuV27Ceb7ig95hWNHFTSXfxMg==", + "dependencies": { + "Azure.Identity": "1.10.3", + "Microsoft.Data.SqlClient.SNI.runtime": "5.2.0", + "Microsoft.Identity.Client": "4.56.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.35.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.35.0", + "Microsoft.SqlServer.Server": "1.0.0", + "System.Configuration.ConfigurationManager": "6.0.1", + "System.Runtime.Caching": "6.0.0" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "po1jhvFd+8pbfvJR/puh+fkHi0GRanAdvayh/0e47yaM6CXWZ6opUjCMFuYlAnD2LcbyvQE7fPJKvogmaUcN+w==" + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "BUyFU9t+HzlSE7ri4B+AQN2BgTgHv/uM82s5ZkgU1BApyzWzIl48nDsG5wR1t0pniNuuyTBzG3qCW8152/NtSw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "b3ErKzND8LIC7o08QAVlKfaEIYEvLJbtmVbFZVBRXeu9YkKfSSzLZfR1SUfQPBIy9mKLhEtJgGYImkcMNaKE0A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Embedded": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "vlMC8FYEU4BB7W5NXIalaVf9i1qlKIGJSCvB7n1RQLKSwQMhCIKjKvzeyvRbWUdmZwOJRCZm5fidKqnRI71bQQ==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Localization": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "uuD1hdAFK+JqLOOQBMBEIA1aHPLZ1iomXDiAO7ffssDpRCK23tUuQKvl+IGPI3WM9CUsmnAxwXNJg7YKFtUiMA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Localization.Abstractions": "6.0.28", + "Microsoft.Extensions.Logging.Abstractions": "6.0.4", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Localization.Abstractions": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "LFbRKw+TOPiU3eFyuklwCoNCpVb3bYZjvgyCFjmL7GsWLjZg1quyKgUCunLS2Sq5m/4nhppM5VR91alKaRz1wQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "K14wYgwOfKVELrUh5eBqlC8Wvo9vvhS3ZhIvcswV2uS/ubkTRPSQsN557EZiYUSSoZNxizG+alN4wjtdyLdcyw==" + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7hR9FU0JJHOCLmn/Ary31pLLAhlzoMptBKs5CJmNUzD87dXjl+/NqVkyCTl6cT2JAfTK0G39HpvCOv1fhsX3BQ==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bXWINbTn0vC0FYc9GaQTISbxhQLAMrvtbuvD9N6JelEaIS/Pr62wUCinrq5bf1WRBGczt1v4wDhxFtVFNcMdUQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.56.0", + "contentHash": "rr4zbidvHy9r4NvOAs5hdd964Ao2A0pAeFBJKR95u1CJAVzbd1p6tPTXUZ+5ld0cfThiVSGvz6UHwY6JjraTpA==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.22.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "4.56.0", + "contentHash": "H12YAzEGK55vZ+QpxUzozhW8ZZtgPDuWvgA0JbdIR9UhMUplj29JhIgE2imuH8W2Nw9D8JKygR1uxRFtpSNcrg==", + "dependencies": { + "Microsoft.Identity.Client": "4.56.0", + "System.IO.FileSystem.AccessControl": "5.0.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "gIw8Sr5ZpuzKFBTfJonh2F54DivTzm5IIK15QB4Y6uE30uQdEO1NnCojTC/b6sWZoZzD0sdBa6SqwMXhucD+nA==" + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "mXA6AoaD5uZqtsKghgRiupBhyXNii8p9F2BjNLnDGud0tZLS5+4Fio2YAGjFXhnkc80CqgQ61X5U1gUNnDEoKQ==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "7.3.1" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "uPt2aiRUCbcOc0Wk+dDCSClFfPNs3S3Z7fmy50MoxJ1mGmtVUDMpyRJeYzZ/16x4rL19T+g2zrzjcWoitp5+gQ==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "7.3.1" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.35.0", + "contentHash": "BPQhlDzdFvv1PzaUxNSk+VEPwezlDEVADIKmyxubw7IiELK18uJ06RQ9QKKkds30XI+gDu9n8j24XQ8w7fjWcg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.35.0", + "Microsoft.IdentityModel.Tokens": "6.35.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.35.0", + "contentHash": "LMtVqnECCCdSmyFoCOxIE5tXQqkOLrvGrL7OxHg41DIm1bpWtaCdGyVcTAfOQpJXvzND9zUKIN/lhngPkYR8vg==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.35.0", + "System.IdentityModel.Tokens.Jwt": "6.35.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "/c/p8/3CAH706c0ii5uTgSb/8M/jwyuurtdMeKTBeKFU9aA+EZrLu1M8aaS3CSlGaxoxsoaxr4/+KXykgQ4VgQ==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "7.3.1" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.10.0-release-24177-07", + "contentHash": "Km1jsYkTtwZmN3EQ4kom76eZiN/WXWiMkk007NpL39lP6OtFD2NARw4bqs+NMokIFQZrMwqtt+IVtvDgbkiQbA==", + "dependencies": { + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.10.0-release-24177-07", + "contentHash": "yPFZE4cUyJLMsDCHY8EC8N945Cxy+sXB8Epa5aC3glcAMlm9vziUtKDvbY1lNmMB8Ri2E4OHfEQuor1/pLWqtg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.10.0-release-24177-07", + "Newtonsoft.Json": "13.0.1" + } + }, + "MimeKit": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "pKvznVpvK35cJb21LdjvhB3MW2FrlAqG3PH36uVKHhlgnfMS5tIRsKJEMgo0hiPyJJhN2f1llHptu2w8CvF9Vg==", + "dependencies": { + "BouncyCastle.Cryptography": "2.3.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Security.Cryptography.Pkcs": "8.0.0", + "System.Text.Encoding.CodePages": "8.0.0" + } + }, + "Mono.Cecil": { + "type": "Transitive", + "resolved": "0.11.5", + "contentHash": "fxfX+0JGTZ8YQeu1MYjbBiK2CYTSzDyEeIixt+yqKKTn7FW8rv7JMY70qevup4ZJfD7Kk/VG/jDzQQTpfch87g==" + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.CodeDom": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "WTlRjL6KWIMr/pAaq3rYqh0TJlzpouaQ/W1eelssHgtlwHAH25jXTkUphTYx9HaIIf7XA6qs/0+YhtLEQRkJ+Q==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg==" + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "JlYi9XVvIREURRUlGMr1F6vOFLk7YSY4p1vHo4kX3tQ0AGrjqlRWHDi66ImHhy6qwXBG3BJ6Y1QlYQ+Qz6Xgww==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "8.0.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "AJukBuLoe3QeAF+mfaRKQb2dgyrvt340iMBHYv+VdBzCUM06IxGlvl0o/uPOS7lHnXPN6u8fFRHSHudx5aTi8w==" + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "iE8biOWyAC1NnYcZGcgXErNACvIQ6Gcmg5s28gsjVbyyYdF9NdKsYzAPAsO3KGK86EQjpToI1AO82XbG8chkzA==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "7.3.1", + "Microsoft.IdentityModel.Tokens": "7.3.1" + } + }, + "System.IO.FileSystem.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "sDnWM0N3AMCa86LrKTWeF3BZLD2sgWyYUc7HL6z4+xyDZNQRwzmxbo4qP2rX2MqC+Sy1/gOSRDah5ltxY5jPxw==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mXX66shZ4xLlI3vNLaJ0lt8OIZdmXTvIqXRdQX5HLVGSkLhINLsVhyZuX2UdRFnOGkqnwmMUs40pIIQ7mna4+A==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "E0e03kUp5X2k+UAoVl6efmI7uU7JRBWi5EIdlQ7cr0NpBGjHG4fWII35PgsBY9T4fJQ8E4QPsL0rKksU9gcL5A==", + "dependencies": { + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ULmp3xoOwNYjOYp4JZ2NK/6NdTgiN1GQXzVVN1njQ7LOZ0d0B9vyMnhyqbIi9Qw4JXj1JgCsitkTShboHRx7Eg==", + "dependencies": { + "System.Formats.Asn1": "8.0.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "+TUFINV2q2ifyXauQXRwy4CiBhqvDEDZeVJU7qfxya4aRYOKzVBpN+4acx25VcPB9ywUN6C0n8drWl110PhZEg==" + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.7", + "contentHash": "/Tf/9XjprpHolbcDOrxsKVYy/mUG/FS7aGd9YUgBVEiHeQH4kAE0T1sMbde7q6B5xcrNUsJ5iW7D1RvHudQNqA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TY8/9+tI0mNaUMgntOxxaq2ndTkdXqLSxvPmas7XEqOlv9lQtB7wLjYGd756lOaO7Dvb5r/WXhluM+0Xe87v5Q==" + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "Yarp.ReverseProxy": { + "type": "Transitive", + "resolved": "2.0.1", + "contentHash": "op7vBwONPFeR1PYxeLw+RLqSodODDX8RWd0OinLGMVIq6yi1q9mv1j56ImuyZgiAToksiC0Dc7jbRUZ9I+jvFA==", + "dependencies": { + "System.IO.Hashing": "7.0.0" + } + }, + "kentico.xperience.googlemaps": { + "type": "Project", + "dependencies": { + "Kentico.Xperience.Admin": "[28.4.3, )", + "Microsoft.NET.Test.Sdk": "[17.10.0-release-24177-07, )", + "NSubstitute": "[5.1.0, )", + "NUnit": "[4.1.0, )", + "NUnit.ConsoleRunner": "[3.17.0, )", + "NUnit3TestAdapter": "[4.5.0, )" + } + }, + "Kentico.Xperience.Admin": { + "type": "CentralTransitive", + "requested": "[28.4.3, )", + "resolved": "28.4.3", + "contentHash": "TZnv+XpEtH8gWR+UFkJANBS1bZQ+ZP2ZQQgQXPJz9OlowPwVRkB+aAu9yOfqiXXjEudpmvpAP/SB6o3lxHG+3A==", + "dependencies": { + "Kentico.Aira.Client": "1.0.25", + "Kentico.Xperience.WebApp": "[28.4.3]", + "Microsoft.AspNetCore.SpaServices.Extensions": "6.0.28", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.28" + } + }, + "Kentico.Xperience.WebApp": { + "type": "CentralTransitive", + "requested": "[28.1.0, )", + "resolved": "28.4.3", + "contentHash": "tFsbmisfYQrLdKtH35z9LL/D9UeqIb9T3o8WqKuIWOaZlOZDlxpaohzlh0raUuTGtJ14OE7kYgln1vGg4lvonw==", + "dependencies": { + "CommandLineParser": "2.9.1", + "HotChocolate.AspNetCore": "13.9.0", + "HotChocolate.Data": "13.9.0", + "HtmlSanitizer": "8.0.843", + "Kentico.Xperience.Core": "[28.4.3]", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.28", + "Microsoft.Extensions.Localization": "6.0.28" + } + } + } + } +} \ No newline at end of file diff --git a/Kentico.Xperience.GoogleMaps.sln b/Kentico.Xperience.GoogleMaps.sln new file mode 100644 index 0000000..d93ef7d --- /dev/null +++ b/Kentico.Xperience.GoogleMaps.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33516.290 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kentico.Xperience.GoogleMaps", "Kentico.Xperience.GoogleMaps\Kentico.Xperience.GoogleMaps.csproj", "{10737D48-21DF-44CF-8E7C-026C6519F9B7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kentico.Xperience.GoogleMaps.Tests", "Kentico.Xperience.GoogleMaps.Tests\Kentico.Xperience.GoogleMaps.Tests.csproj", "{46419201-554C-4DF5-B491-0E1909853077}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {10737D48-21DF-44CF-8E7C-026C6519F9B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10737D48-21DF-44CF-8E7C-026C6519F9B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10737D48-21DF-44CF-8E7C-026C6519F9B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10737D48-21DF-44CF-8E7C-026C6519F9B7}.Release|Any CPU.Build.0 = Release|Any CPU + {46419201-554C-4DF5-B491-0E1909853077}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46419201-554C-4DF5-B491-0E1909853077}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46419201-554C-4DF5-B491-0E1909853077}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46419201-554C-4DF5-B491-0E1909853077}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1B2A20BC-F57B-4AAE-B1C2-E4DC52EFCAC5} + EndGlobalSection +EndGlobal diff --git a/Kentico.Xperience.GoogleMaps/AssemblyAttributes.cs b/Kentico.Xperience.GoogleMaps/AssemblyAttributes.cs new file mode 100644 index 0000000..42796c5 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/AssemblyAttributes.cs @@ -0,0 +1,5 @@ +using System.Runtime.CompilerServices; +using CMS; + +[assembly: AssemblyDiscoverable] +[assembly: InternalsVisibleTo("Kentico.Xperience.GoogleMaps.Tests")] diff --git a/Kentico.Xperience.GoogleMaps/Extensions/StartupExtensions.cs b/Kentico.Xperience.GoogleMaps/Extensions/StartupExtensions.cs new file mode 100644 index 0000000..ce356b1 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Extensions/StartupExtensions.cs @@ -0,0 +1,39 @@ +using System.Net.Http.Headers; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Startup extensions necessary for Google Maps. + /// + public static class StartupExtensions + { + /// + /// Initializes . + /// + /// Services. + /// Configuration. + public static IServiceCollection AddGoogleMaps(this IServiceCollection services, IConfiguration configuration) + { + var googleMapsSection = configuration.GetSection(GoogleMapsConstants.SECTION_KEY); + services.Configure(googleMapsSection); + + var googleMapsOptions = googleMapsSection.Get(); + + if (string.IsNullOrEmpty(googleMapsOptions.APIKey)) + { + throw new InvalidOperationException(nameof(googleMapsOptions.APIKey)); + } + + services.Configure(googleMapsSection); + + services.AddHttpClient(GoogleMapsConstants.CLIENT_NAME, client + => client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"))); + + services.AddSingleton(); + + return services; + } + } +} diff --git a/Kentico.Xperience.GoogleMaps/GoogleMapsConstants.cs b/Kentico.Xperience.GoogleMaps/GoogleMapsConstants.cs new file mode 100644 index 0000000..806e9f4 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/GoogleMapsConstants.cs @@ -0,0 +1,31 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Constants used by Google Maps integration. + /// + public static class GoogleMapsConstants + { + /// + /// The URL for the Google Maps Geocode API. + /// + public const string GEOCODE_API_URL = "https://maps.googleapis.com/maps/api/geocode/json?key={0}&address={1}&components={2}"; + + + /// + /// The URL for the Google Maps Address Validation API. + /// + public const string VALIDATION_API_URL = "https://addressvalidation.googleapis.com/v1:validateAddress?key={0}"; + + + /// + /// Name of the Google maps section in the 'appsettings.json' file. + /// + public const string SECTION_KEY = "xperience.googleMaps"; + + + /// + /// Name of the named HTTP client. + /// + public const string CLIENT_NAME = "GoogleMapsClient"; + } +} diff --git a/Kentico.Xperience.GoogleMaps/Kentico.Xperience.GoogleMaps.csproj b/Kentico.Xperience.GoogleMaps/Kentico.Xperience.GoogleMaps.csproj new file mode 100644 index 0000000..a4af198 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Kentico.Xperience.GoogleMaps.csproj @@ -0,0 +1,36 @@ + + + + net6.0 + enable + enable + true + + + + + true + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationAddress.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationAddress.cs new file mode 100644 index 0000000..27da735 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationAddress.cs @@ -0,0 +1,13 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents a address received by validation. + /// + internal class AddressValidationAddress + { + /// + /// Gets or sets the formatted address. + /// + public string? FormattedAddress { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationRequestData.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationRequestData.cs new file mode 100644 index 0000000..1d26433 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationRequestData.cs @@ -0,0 +1,13 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents the data for a validation request. + /// + internal class AddressValidationRequestData + { + /// + /// Gets or sets the address for validation. + /// + public AddressValidationRequestDataAddress? Address { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationRequestDataAddress.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationRequestDataAddress.cs new file mode 100644 index 0000000..60dbdfe --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationRequestDataAddress.cs @@ -0,0 +1,18 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents the address data for a validation request. + /// + internal class AddressValidationRequestDataAddress + { + /// + /// Gets or sets the region code of the address. + /// + public string? RegionCode { get; set; } + + /// + /// Gets or sets the address lines of the address. + /// + public IEnumerable? AddressLines { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationResponse.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationResponse.cs new file mode 100644 index 0000000..5e40168 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationResponse.cs @@ -0,0 +1,13 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents the validation response for an address. + /// + internal class AddressValidationResponse + { + /// + /// Gets or sets the validation result. + /// + public AddressValidationResult? Result { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationResult.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationResult.cs new file mode 100644 index 0000000..70b583e --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationResult.cs @@ -0,0 +1,18 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents the result of an address validation. + /// + internal class AddressValidationResult + { + /// + /// Gets or sets the verdict of the validation. + /// + public AddressValidationVerdict? Verdict { get; set; } + + /// + /// Gets or sets the validated address. + /// + public AddressValidationAddress? Address { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationVerdict.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationVerdict.cs new file mode 100644 index 0000000..1a9fa4a --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidationVerdict.cs @@ -0,0 +1,13 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents the validation verdict for an address. + /// + internal class AddressValidationVerdict + { + /// + /// Gets or sets a value indicating whether the address is complete. + /// + public bool? AddressComplete { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidatorResult.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidatorResult.cs new file mode 100644 index 0000000..67b1c91 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/AddressValidatorResult.cs @@ -0,0 +1,19 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents the result of an address validation. + /// + public class AddressValidatorResult + { + /// + /// Gets or sets a value indicating whether the address is valid. + /// + public bool IsValid { get; set; } + + + /// + /// Gets or sets the formatted address. + /// + public string? FormattedAddress { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/GeocodeResponse.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/GeocodeResponse.cs new file mode 100644 index 0000000..9e029c2 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/GeocodeResponse.cs @@ -0,0 +1,19 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents the response from the geocoding service. + /// + internal class GeocodeResponse + { + /// + /// Gets or sets the status of the geocode response. + /// + public string? Status { get; set; } + + + /// + /// Gets or sets the collection of geocode results. + /// + public IEnumerable? Results { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/AddressValidation/GeocodeResult.cs b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/GeocodeResult.cs new file mode 100644 index 0000000..7c1b799 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/AddressValidation/GeocodeResult.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents a geocode result. + /// + internal class GeocodeResult + { + /// + /// Gets or sets the formatted address. + /// + [JsonPropertyName("formatted_address")] + public string? FormattedAddress { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/FormComponents/AddressFormComponent.cs b/Kentico.Xperience.GoogleMaps/Models/FormComponents/AddressFormComponent.cs new file mode 100644 index 0000000..64dde7c --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/FormComponents/AddressFormComponent.cs @@ -0,0 +1,81 @@ +using System.ComponentModel.DataAnnotations; +using Kentico.Forms.Web.Mvc; +using Kentico.Xperience.GoogleMaps; + +[assembly: RegisterFormComponent(AddressFormComponent.IDENTIFIER, + typeof(AddressFormComponent), + "{$addressformcomponent.name$}", + IconClass = "icon-home")] + +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents a address input form component. + /// + public class AddressFormComponent : FormComponent + { + private readonly IAddressValidator addressValidator; + + + /// + /// Represents the identifier. + /// + public const string IDENTIFIER = "AddressFormComponent"; + + + /// + /// Initializes an instance of the class. + /// + /// Service validating addresses. + public AddressFormComponent(IAddressValidator addressValidator) + { + this.addressValidator = addressValidator; + } + + + /// + /// Represents the input value in the resulting HTML. + /// + [BindableProperty] + public string Value { get; set; } = string.Empty; + + + /// + public override string GetValue() + { + return Value; + } + + + /// + public override void SetValue(string value) + { + Value = value; + } + + + /// + public override IEnumerable Validate(ValidationContext validationContext) + { + var errors = new List(); + errors.AddRange(base.Validate(validationContext)); + + string value = GetValue(); + + var addressValidationResult = Properties.EnableValidation + ? addressValidator.Validate(value, Properties.SupportedCountries, Properties.EnableCompanyNames).GetAwaiter().GetResult() + : null; + + if (!string.IsNullOrWhiteSpace(value) && Properties.EnableValidation && !addressValidationResult?.IsValid == true) + { + errors.Add(new ValidationResult("Entered value is not a valid address.", new[] { nameof(Value) })); + } + else if (Properties.EnableValidation && addressValidationResult is not null) + { + Value = addressValidationResult.FormattedAddress ?? string.Empty; + } + + return errors; + } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Models/FormComponents/AddressFormComponentProperties.cs b/Kentico.Xperience.GoogleMaps/Models/FormComponents/AddressFormComponentProperties.cs new file mode 100644 index 0000000..11f2bfe --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Models/FormComponents/AddressFormComponentProperties.cs @@ -0,0 +1,43 @@ +using CMS.DataEngine; +using Kentico.Forms.Web.Mvc; +using Kentico.Xperience.Admin.Base.FormAnnotations; + +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents properties of a . + /// + public class AddressFormComponentProperties : FormComponentProperties + { + /// + [TextInputComponent(Label = "{$kentico.formbuilder.defaultvalue$}", Order = EditingComponentOrder.DEFAULT_VALUE)] + public override string DefaultValue { get; set; } = string.Empty; + + + [CheckBoxComponent(Label = "{$addressformcomponent.properties.enablevalidation.label$}", Order = EditingComponentOrder.DEFAULT_VALUE, + Tooltip = "{$addressformcomponent.properties.enablevalidation.tooltip$}")] + public bool EnableValidation { get; set; } = false; + + + [CheckBoxComponent(Label = "{$addressformcomponent.properties.enablecompanynames.label$}", Order = EditingComponentOrder.DEFAULT_VALUE, + Tooltip = "{$addressformcomponent.properties.enablecompanynames.tooltip$}")] + public bool EnableCompanyNames { get; set; } = false; + + + [TextInputComponent(Label = "{$addressformcomponent.properties.supportedcountries.label$}", Order = EditingComponentOrder.DEFAULT_VALUE, + ExplanationText = "{$addressformcomponent.properties.supportedcountries.explanationtext$}", ExplanationTextAsHtml = true)] + public string SupportedCountries { get; set; } = string.Empty; + + + /// + /// Initializes a new instance of the class. + /// + /// + /// The constructor initializes the base class to data type and size 500. + /// + public AddressFormComponentProperties() + : base(FieldDataType.Text, 500) + { + } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Options/GoogleMapsOptions.cs b/Kentico.Xperience.GoogleMaps/Options/GoogleMapsOptions.cs new file mode 100644 index 0000000..66325eb --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Options/GoogleMapsOptions.cs @@ -0,0 +1,13 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Represents Google Maps options. + /// + public sealed class GoogleMapsOptions + { + /// + /// API Key used to send requests. + /// + public string? APIKey { get; set; } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Resources/GoogleMapsResources.cs b/Kentico.Xperience.GoogleMaps/Resources/GoogleMapsResources.cs new file mode 100644 index 0000000..0f9123e --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Resources/GoogleMapsResources.cs @@ -0,0 +1,14 @@ +using CMS.Base; +using CMS.Localization; + +[assembly: RegisterLocalizationResource(typeof(Kentico.Xperience.GoogleMaps.GoogleMapsResources), SystemContext.SYSTEM_CULTURE_NAME)] + +namespace Kentico.Xperience.GoogleMaps +{ + internal class GoogleMapsResources + { + public GoogleMapsResources() + { + } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Resources/GoogleMapsResources.resx b/Kentico.Xperience.GoogleMaps/Resources/GoogleMapsResources.resx new file mode 100644 index 0000000..203fe5a --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Resources/GoogleMapsResources.resx @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Enable Validation + + + This option enables validation of addresses using Google Maps API. + + + Enable company names + + + This option enables suggestions and validation for company names. + + + Supported countries + + + Insert countries you want to support separated by colons. Use Alpha-2 code for countries: <a href="https://www.iban.com/country-codes">Country codes</a> + + + Address + + \ No newline at end of file diff --git a/Kentico.Xperience.GoogleMaps/Services/AddressValidator.cs b/Kentico.Xperience.GoogleMaps/Services/AddressValidator.cs new file mode 100644 index 0000000..8623ce9 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Services/AddressValidator.cs @@ -0,0 +1,119 @@ +using System.Net.Http.Json; +using CMS.Core; +using Microsoft.Extensions.Options; + +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Validates addresses using API endpoint. + /// + internal class AddressValidator : IAddressValidator + { + private readonly IHttpClientFactory httpClientFactory; + private readonly IEventLogService eventLogService; + private readonly IOptions options; + + + /// + /// Initializes an instance of the class. + /// + public AddressValidator(IHttpClientFactory httpClientFactory, IEventLogService eventLogService, IOptions options) + { + this.httpClientFactory = httpClientFactory; + this.eventLogService = eventLogService; + this.options = options; + } + + + /// + public async Task Validate(string value, string supportedCountries = "US", bool enableCompanyNames = true) + { + if (string.IsNullOrWhiteSpace(value)) + { + return GetValidationResult(false); + } + + string address = value; + if (enableCompanyNames) + { + var geocodeResponse = await SendGeocodeRequest(value, supportedCountries); + if (geocodeResponse is not null && geocodeResponse.Status != "OK") + { + return GetValidationResult(false); + } + address = geocodeResponse?.Results?.First().FormattedAddress ?? string.Empty; + } + + var validateAddressResponse = await SendValidateAddressRequest(address, supportedCountries); + if (validateAddressResponse?.Result?.Address is not null && validateAddressResponse.Result.Verdict?.AddressComplete == true) + { + return GetValidationResult(true, validateAddressResponse.Result.Address.FormattedAddress); + } + + return GetValidationResult(false); + } + + + private async Task SendGeocodeRequest(string value, string supportedCountries) + { + string url = string.Format(GoogleMapsConstants.GEOCODE_API_URL, options.Value.APIKey, value, $"country:{supportedCountries}"); + + var httpClient = GetHttpClient(); + + try + { + return await httpClient.GetFromJsonAsync(url); + } + catch (Exception ex) + { + eventLogService.LogException(nameof(AddressValidator), nameof(SendGeocodeRequest), ex, additionalMessage: $"{nameof(SendGeocodeRequest)} failed. Request path: {url}"); + } + + return null; + } + + + private async Task SendValidateAddressRequest(string value, string supportedCountries) + { + var validateAddressRequestData = new AddressValidationRequestData() + { + Address = new AddressValidationRequestDataAddress() + { + AddressLines = new List { value }, + RegionCode = supportedCountries + } + }; + string url = string.Format(GoogleMapsConstants.VALIDATION_API_URL, options.Value.APIKey); + + var httpClient = GetHttpClient(); + + try + { + var validationResponse = await httpClient.PostAsJsonAsync(url, validateAddressRequestData); + return await validationResponse.Content.ReadFromJsonAsync(); + } + catch (Exception ex) + { + eventLogService.LogException(nameof(AddressValidator), nameof(SendValidateAddressRequest), ex, additionalMessage: $"{nameof(SendValidateAddressRequest)} failed. Request path: {url}"); + } + + return null; + } + + + private HttpClient GetHttpClient() + { + return httpClientFactory.CreateClient(GoogleMapsConstants.CLIENT_NAME); + } + + + private AddressValidatorResult GetValidationResult(bool isValid, string? formattedAddress = null) + { + return new AddressValidatorResult() + { + IsValid = isValid, + FormattedAddress = formattedAddress + }; + } + } +} diff --git a/Kentico.Xperience.GoogleMaps/Services/IAddressValidator.cs b/Kentico.Xperience.GoogleMaps/Services/IAddressValidator.cs new file mode 100644 index 0000000..63ccb08 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Services/IAddressValidator.cs @@ -0,0 +1,17 @@ +namespace Kentico.Xperience.GoogleMaps +{ + /// + /// Validates addresses. + /// + public interface IAddressValidator + { + /// + /// Validates if the address is valid. + /// + /// The address to validate. + /// Supported countries separated by colons. Use Alpha-2 code for countries. + /// Enables validation for company names. + /// True if the address is valid, otherwise false. + Task Validate(string value, string supportedCountries = "US", bool enableCompanyNames = true); + } +} diff --git a/Kentico.Xperience.GoogleMaps/Views/Shared/FormComponents/_AddressFormComponent.cshtml b/Kentico.Xperience.GoogleMaps/Views/Shared/FormComponents/_AddressFormComponent.cshtml new file mode 100644 index 0000000..431e5c9 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/Views/Shared/FormComponents/_AddressFormComponent.cshtml @@ -0,0 +1,11 @@ +@using Kentico.Forms.Web.Mvc +@using Kentico.Web.Mvc +@using Kentico.Xperience.GoogleMaps + +@model AddressFormComponent + +@{ + var htmlAttributes = ViewData.Kentico().GetEditorHtmlAttributes(); +} + +@Html.TextBoxFor(m => m.Value, htmlAttributes) diff --git a/Kentico.Xperience.GoogleMaps/packages.lock.json b/Kentico.Xperience.GoogleMaps/packages.lock.json new file mode 100644 index 0000000..e38ddd4 --- /dev/null +++ b/Kentico.Xperience.GoogleMaps/packages.lock.json @@ -0,0 +1,983 @@ +{ + "version": 2, + "dependencies": { + "net6.0": { + "Kentico.Xperience.Admin": { + "type": "Direct", + "requested": "[28.4.3, )", + "resolved": "28.4.3", + "contentHash": "TZnv+XpEtH8gWR+UFkJANBS1bZQ+ZP2ZQQgQXPJz9OlowPwVRkB+aAu9yOfqiXXjEudpmvpAP/SB6o3lxHG+3A==", + "dependencies": { + "Kentico.Aira.Client": "1.0.25", + "Kentico.Xperience.WebApp": "[28.4.3]", + "Microsoft.AspNetCore.SpaServices.Extensions": "6.0.28", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.28" + } + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.10.0-release-24177-07, )", + "resolved": "17.10.0-release-24177-07", + "contentHash": "OIvw7UlANS20ybCP7orcX4WSfyUc7SUzkAl/Fo51O9IqmSJA0Pa8LW96bQ3c8KFDiV7K5ckSS0QFmyw10C66IA==", + "dependencies": { + "Microsoft.CodeCoverage": "17.10.0-release-24177-07", + "Microsoft.TestPlatform.TestHost": "17.10.0-release-24177-07" + } + }, + "NSubstitute": { + "type": "Direct", + "requested": "[5.1.0, )", + "resolved": "5.1.0", + "contentHash": "ZCqOP3Kpp2ea7QcLyjMU4wzE+0wmrMN35PQMsdPOHYc2IrvjmusG9hICOiqiOTPKN0gJon6wyCn6ZuGHdNs9hQ==", + "dependencies": { + "Castle.Core": "5.1.1" + } + }, + "NUnit": { + "type": "Direct", + "requested": "[4.1.0, )", + "resolved": "4.1.0", + "contentHash": "MT/DpAhjtiytzhTgTqIhBuWx4y26PKfDepYUHUM+5uv4TsryHC2jwFo5e6NhWkApCm/G6kZ80dRjdJFuAxq3rg==" + }, + "NUnit.ConsoleRunner": { + "type": "Direct", + "requested": "[3.17.0, )", + "resolved": "3.17.0", + "contentHash": "XUctGgtqYdWzNiXFdDa1odKlrBWBStEEfv+TOhrtubpXGmNwKZ4GzzZJiq3eK5qpkj2QmPlP583Ffzf/Zr+w6g==" + }, + "NUnit3TestAdapter": { + "type": "Direct", + "requested": "[4.5.0, )", + "resolved": "4.5.0", + "contentHash": "s8JpqTe9bI2f49Pfr3dFRfoVSuFQyraTj68c3XXjIS/MRGvvkLnrg6RLqnTjdShX+AdFUCCU/4Xex58AdUfs6A==" + }, + "SonarAnalyzer.CSharp": { + "type": "Direct", + "requested": "[9.23.1.88495, )", + "resolved": "9.23.1.88495", + "contentHash": "aKrXq94OO1wiMtsBttRd7vRJKFWp/eVeMJrPFB6OIbjbpxEySbKrLmM8Kj1ZF5jqp5yaZGBLMpe6jxodJqPyMg==" + }, + "AngleSharp": { + "type": "Transitive", + "resolved": "0.17.1", + "contentHash": "5MPI4bbixlwxb0W/smOMeIR+QlxMy5/5jD+WnIAw4pBC+7AhLPe5bS3cLgQMJyvd6q0A48sG+uYOt/ep406GLA==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Text.Encoding.CodePages": "6.0.0" + } + }, + "AngleSharp.Css": { + "type": "Transitive", + "resolved": "0.17.0", + "contentHash": "bg0AcugmX6BFEi/DHG61QrwRU8iuiX4H8LZehdIzYdqOM/dgb3BsCTzNIcc1XADn4+xfQEdVwJYTSwUxroL4vg==", + "dependencies": { + "AngleSharp": "[0.17.0, 0.18.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.35.0", + "contentHash": "hENcx03Jyuqv05F4RBEPbxz29UrM3Nbhnr6Wl6NQpoU9BCIbL3XLentrxDCTrH54NLS11Exxi/o8MYgT/cnKFA==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "6.0.1", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.10.3", + "contentHash": "l1Xm2MWOF2Mzcwuarlw8kWQXLZk3UeB55aQXVyjj23aBfDwOZ3gu5GP2kJ6KlmZeZv2TCzw7x4L3V36iNr3gww==", + "dependencies": { + "Azure.Core": "1.35.0", + "Microsoft.Identity.Client": "4.56.0", + "Microsoft.Identity.Client.Extensions.Msal": "4.56.0", + "System.Memory": "4.5.4", + "System.Security.Cryptography.ProtectedData": "4.7.0", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "BananaCakePop.Middleware": { + "type": "Transitive", + "resolved": "13.0.0", + "contentHash": "6Zj/vfmnCXLjBG7WNdtOgZZ5ZDR3Sy1FQSshZUonIYs3OdzozmsFmqPXMd9XJ0QE9aAildgVGq/lDLpLrMI4Yw==", + "dependencies": { + "Yarp.ReverseProxy": "2.0.1" + } + }, + "BouncyCastle.Cryptography": { + "type": "Transitive", + "resolved": "2.3.0", + "contentHash": "IaVIiYxZLaBulveGDRUx/pBoW/Rc8QeXGF5u2E8xL8RWhVKCgfmtX9NUyGRbnSqnbFQU2zyP3MkXIdH+jUuQBw==" + }, + "Castle.Core": { + "type": "Transitive", + "resolved": "5.1.1", + "contentHash": "rpYtIczkzGpf+EkZgDr9CClTdemhsrwA/W5hMoPjLkRFnXzH44zDLoovXeKtmxb1ykXK9aJVODSpiJml8CTw2g==", + "dependencies": { + "System.Diagnostics.EventLog": "6.0.0" + } + }, + "CommandLineParser": { + "type": "Transitive", + "resolved": "2.9.1", + "contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA==" + }, + "GreenDonut": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "T8ZYTsm0S48hi89d2symCvUEJoBkg5F+rfU+HFtkEOc7WLZsIBDStnfF3c890Vxjmx/P1tFpY5StDNTM+C6fIw==", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0", + "System.Threading.Tasks.Extensions": "4.5.0" + } + }, + "HotChocolate": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "aGBAW6d9Oj1MfmKJF482yYdJ8G87yJ0rVFxU9l7lA1dg1xjc5XALLQO9jCPz4GCpQLetuAhHdkZ713imJ6WCPw==", + "dependencies": { + "HotChocolate.Authorization": "13.9.0", + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Fetching": "13.9.0", + "HotChocolate.Types": "13.9.0", + "HotChocolate.Types.CursorPagination": "13.9.0", + "HotChocolate.Types.Mutations": "13.9.0", + "HotChocolate.Types.OffsetPagination": "13.9.0", + "HotChocolate.Validation": "13.9.0" + } + }, + "HotChocolate.Abstractions": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "mb3IPL8V4NRL2FUefZP20fSwIMOnE7uCMLiM4d5Y5cjljYaMUVzUJnvdW9C1tUfbodP49Llk9WnBCR6S9fr8mQ==", + "dependencies": { + "HotChocolate.Language": "13.9.0", + "Microsoft.Bcl.AsyncInterfaces": "6.0.0", + "System.Collections.Immutable": "6.0.0" + } + }, + "HotChocolate.AspNetCore": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "RnxUdKEYOmsjzNPss473CYOug/9GIt8qlS9j8HxtZrW5TASM/9S7pDb7FthcDj4ag/D7wAwme3YxsqxH+iw5Bg==", + "dependencies": { + "BananaCakePop.Middleware": "13.0.0", + "HotChocolate": "13.9.0", + "HotChocolate.Subscriptions.InMemory": "13.9.0", + "HotChocolate.Transport.Sockets": "13.9.0", + "HotChocolate.Types.Scalars.Upload": "13.9.0", + "HotChocolate.Utilities.DependencyInjection": "13.9.0" + } + }, + "HotChocolate.Authorization": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "6CPA39zObNuMUmkmQ6J3zqmalukhjCiJS/klSEDPpwTtrn9HS/3edsh/7oiKzmUh6PNVKGed0lwkSdDP+DGZDQ==", + "dependencies": { + "HotChocolate.Execution": "13.9.0" + } + }, + "HotChocolate.Data": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "eZI9pIipsJsqdacj55krmxx24cUTCearQ/q9wT4aa6vQ/5GwuwWJ0ZIqdcp1qPjd+BsmJixrQBbi6/OgnFXIGw==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types.CursorPagination": "13.9.0" + } + }, + "HotChocolate.Execution": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "zO1aG5qx5lzbZu/iKR56g+zeOgCCCa5pICwxijd1qEap+7J5q0YsME9RByw8wYPH+tNsXCvDcKaeAEcashB4cg==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "HotChocolate.Execution.Abstractions": "13.9.0", + "HotChocolate.Fetching": "13.9.0", + "HotChocolate.Types": "13.9.0", + "HotChocolate.Utilities.DependencyInjection": "13.9.0", + "HotChocolate.Validation": "13.9.0", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "System.Threading.Channels": "6.0.0" + } + }, + "HotChocolate.Execution.Abstractions": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "flySLPDyTtM4051tI3mh5Ue0fGrKFDuW3w0ebWmW2qjfuF4jgQzd3pK3ZxfkxAfpxQXyPaVn/Q7fae+fYQxeCg==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0" + } + }, + "HotChocolate.Fetching": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "pIw7VlEABejQGLRnJGnO7iPdT40AHklf0psJp5zNXrq0IX+Vq7hRRqON73nubZv5Ofhh8fV3kugqYFKvzcptoA==", + "dependencies": { + "GreenDonut": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Language": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "M8q0XHQm8Gtab+wKgYXfVPxScjdDE+INify5yaj6g1ZDkV3sLIeX+muu1WebrNO3DgmuAi6o3aW770Ucw7k/dw==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0", + "HotChocolate.Language.Utf8": "13.9.0", + "HotChocolate.Language.Visitors": "13.9.0", + "HotChocolate.Language.Web": "13.9.0" + } + }, + "HotChocolate.Language.SyntaxTree": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "+vwrQ0qOiKn/yUBHn53030hQmqj45C1g0WI8sip50CPnkgs3bAPnDInUvrR3IiHbRn5spAonO4tFPtMDdJrEMA==", + "dependencies": { + "Microsoft.Extensions.ObjectPool": "6.0.0" + } + }, + "HotChocolate.Language.Utf8": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "IEWNYGvtwejf7+j+Xci25FaYets2UD8wkfzQ5dUCW47c1rnTAyuRdTiO8T8x6LYuZ7+SLg7UTBYgjv4ybwAUgA==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0" + } + }, + "HotChocolate.Language.Visitors": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "j6mPBkfVo2fopWYLoczXCoog4PJ+KwbHItSgHfPfI1kDBcNcy9XY4oxth3Uau1uBbfHYIFjnuVc+FrGb1f9KAQ==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0" + } + }, + "HotChocolate.Language.Web": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "GI5ufbNVEoKygSC09owVnCvw1Ma2KzOtm1l6uen3wKshAdOKB4gmSVCjzf71pNL2Nt6cL4IHa70ClqjECmu9qg==", + "dependencies": { + "HotChocolate.Language.Utf8": "13.9.0" + } + }, + "HotChocolate.Subscriptions": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "P3ason65NwSzkB2W9myV/pRIm4IMIWXH3RPCtpHVKx22Xw3hRJRJhjLBQZ5LCk5v3+7kKhXNBTbFNpbMyvez3Q==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "HotChocolate.Execution.Abstractions": "13.9.0" + } + }, + "HotChocolate.Subscriptions.InMemory": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "rj5U1Cd2QsjNnSNNdlSopYLtXh0kTZ1NlA1B3v02YFtj4Zu9le6QkGsl3oUljUUq46vSkkrT9ISj+e5wTCcw/Q==", + "dependencies": { + "HotChocolate.Execution.Abstractions": "13.9.0", + "HotChocolate.Subscriptions": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0" + } + }, + "HotChocolate.Transport.Sockets": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "4hPlhS2bgqT/tYCZfPtbGtPAaedULKgTbFKkTsjigrDhJcVxBA36Gr3yGM6S3NEw2JdIgiwugYV1log9zXkEjA==", + "dependencies": { + "System.IO.Pipelines": "6.0.0" + } + }, + "HotChocolate.Types": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "VGPZePNC4sBlz/iY4x90zIRxW62MWzWNcl2yjLS3JcW+0W8KuKxh99dFLxL0WY/+Eoe8PUecmoob+FrVEvPzpg==", + "dependencies": { + "HotChocolate.Abstractions": "13.9.0", + "HotChocolate.Types.Shared": "13.9.0", + "HotChocolate.Utilities": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.ObjectPool": "6.0.0", + "System.ComponentModel.Annotations": "5.0.0", + "System.Text.Json": "6.0.7" + } + }, + "HotChocolate.Types.CursorPagination": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "2+w6tLrdjo+d/aIKyoNW1L/OH/p+FACMwGWHk1P4MwAspqaF7zjy71qTeNks+8QbRwG8uMleey/0sbr8sWpC6w==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.Mutations": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "NX1zLkb7t19Om5RYubmkA6yRCtBbca454rqSGKSVBYjDrsiA6+4ZDvmS9Kjbw8F+cPm3VqShenrIIgfW8bzCXQ==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.OffsetPagination": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "LIAaSVRS6FJCssP+s4ooLajhQ1/QfES78twX4OgZFJ9/UZMxXlU3K/IWeB2aXcJNkehfIZLgoiROnouB7ATepw==", + "dependencies": { + "HotChocolate.Execution": "13.9.0", + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.Scalars.Upload": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "hisB6PGGgsekz3a8YJwKgvbZHED98eph9+TMPg5A500tyvrZS00fbdpjRcN+rcTKAxhJ5evzHB2Fo1m62Dyo4w==", + "dependencies": { + "HotChocolate.Types": "13.9.0" + } + }, + "HotChocolate.Types.Shared": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "2lhdbXU/GltPQWO9r8qePZSzDo9ryFs8Wv0aF7aQgEq3dLvwer6OpvnZhIYmGua6bXXebA1PzBAEaaxPpLx3Wg==", + "dependencies": { + "HotChocolate.Language.SyntaxTree": "13.9.0" + } + }, + "HotChocolate.Utilities": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "6zqwjROYxtuzAYjh31JnYKgM/MySRWEq4DHO64oSPFRJQ8NDgg7EvUU771yLt/6T7kUh+S6k25hVnmUipFtEnQ==" + }, + "HotChocolate.Utilities.DependencyInjection": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "o1ijY8Rk0IUAo8QZYhfQ8s4/3z78JS9tyXGHzA963gkzTSJPehD4960CAmWlyC19FdE1i2KiTnYLhNOwNoL6+A==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0" + } + }, + "HotChocolate.Validation": { + "type": "Transitive", + "resolved": "13.9.0", + "contentHash": "gC7/YfOcOOmT+zV/V45CubYhK3lZI7+SmNYLGXQ1ko4cwjVRh3PzSJMAaKw3naWDcbjXbEyWwdYc0dLuoVBNEA==", + "dependencies": { + "HotChocolate.Types": "13.9.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "HtmlSanitizer": { + "type": "Transitive", + "resolved": "8.0.843", + "contentHash": "XfmHK4rFz9PPN0gcv7J7pc+MRpcni1mrnO04mwA+9/1zIHLgdOvLJeDwWnX5a+up4tioPvGreB+p+KljLJ32wg==", + "dependencies": { + "AngleSharp": "[0.17.1]", + "AngleSharp.Css": "[0.17.0]", + "System.Collections.Immutable": "8.0.0" + } + }, + "Kentico.Aira.Client": { + "type": "Transitive", + "resolved": "1.0.25", + "contentHash": "Hu3xxl89ZWWU6iGkpnTCIXE/L3DNU+i/ZUZaRESYP6BJANlThPRFCIkrDwNx+daAsda5B/n5iApFzk5nH6qPOA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Http": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0", + "System.IdentityModel.Tokens.Jwt": "7.3.1" + } + }, + "Kentico.Xperience.Core": { + "type": "Transitive", + "resolved": "28.4.3", + "contentHash": "yyQHoVfiABFk7iFrIH81kHqsytzN45/UsSvpNEu3cS7nW1B09nU8GKzwy8Ov4/vKcB8kWZjOSk4g6OG6OydJzA==", + "dependencies": { + "AngleSharp": "0.17.1", + "MailKit": "4.4.0", + "Microsoft.Data.SqlClient": "5.2.0", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.Configuration": "6.0.1", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Localization": "6.0.28", + "Microsoft.Extensions.Options.ConfigurationExtensions": "6.0.0", + "Mono.Cecil": "0.11.5", + "Newtonsoft.Json": "13.0.3", + "System.CodeDom": "8.0.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "cv+oiAOn2+LhhGUVvxpJjEOIZOTZBFDIDO9ebOfxqqU1f/PllHpKr5VjWOBsqeLrb+zLisxWSQDzM5C64XrRNA==", + "dependencies": { + "MimeKit": "4.4.0" + } + }, + "Microsoft.AspNetCore.SpaServices.Extensions": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "IyI3A40jIxHWKT0BcjxGWHaU24zT3NUrexMwWxWdDxTYHteH97OVHf5dNc0eY4RKybCrAi9C+IWAZ2l7NEFEGg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.10.0-release-24177-07", + "contentHash": "mq5zBpsT40IHOm25aLP9dwWBjT3rH/PyiwiyQ+krHGfp57r9C3MtjTY6WPMtM8DK9osRCBqEGXAjjEkVXpOZAg==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "3alfyqRN3ELRtdvU1dGtLBRNQqprr3TJ0WrUJfMISPwg1nPUN2P3Lelah68IKWuV27Ceb7ig95hWNHFTSXfxMg==", + "dependencies": { + "Azure.Identity": "1.10.3", + "Microsoft.Data.SqlClient.SNI.runtime": "5.2.0", + "Microsoft.Identity.Client": "4.56.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.35.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.35.0", + "Microsoft.SqlServer.Server": "1.0.0", + "System.Configuration.ConfigurationManager": "6.0.1", + "System.Runtime.Caching": "6.0.0" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "po1jhvFd+8pbfvJR/puh+fkHi0GRanAdvayh/0e47yaM6CXWZ6opUjCMFuYlAnD2LcbyvQE7fPJKvogmaUcN+w==" + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "BUyFU9t+HzlSE7ri4B+AQN2BgTgHv/uM82s5ZkgU1BApyzWzIl48nDsG5wR1t0pniNuuyTBzG3qCW8152/NtSw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "b3ErKzND8LIC7o08QAVlKfaEIYEvLJbtmVbFZVBRXeu9YkKfSSzLZfR1SUfQPBIy9mKLhEtJgGYImkcMNaKE0A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Embedded": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "vlMC8FYEU4BB7W5NXIalaVf9i1qlKIGJSCvB7n1RQLKSwQMhCIKjKvzeyvRbWUdmZwOJRCZm5fidKqnRI71bQQ==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "15+pa2G0bAMHbHewaQIdr/y6ag2H3yh4rd9hTXavtWDzQBkvpe2RMqFg8BxDpcQWssmjmBApGPcw93QRz6YcMg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Localization": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "uuD1hdAFK+JqLOOQBMBEIA1aHPLZ1iomXDiAO7ffssDpRCK23tUuQKvl+IGPI3WM9CUsmnAxwXNJg7YKFtUiMA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Localization.Abstractions": "6.0.28", + "Microsoft.Extensions.Logging.Abstractions": "6.0.4", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Localization.Abstractions": { + "type": "Transitive", + "resolved": "6.0.28", + "contentHash": "LFbRKw+TOPiU3eFyuklwCoNCpVb3bYZjvgyCFjmL7GsWLjZg1quyKgUCunLS2Sq5m/4nhppM5VR91alKaRz1wQ==" + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "K14wYgwOfKVELrUh5eBqlC8Wvo9vvhS3ZhIvcswV2uS/ubkTRPSQsN557EZiYUSSoZNxizG+alN4wjtdyLdcyw==" + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7hR9FU0JJHOCLmn/Ary31pLLAhlzoMptBKs5CJmNUzD87dXjl+/NqVkyCTl6cT2JAfTK0G39HpvCOv1fhsX3BQ==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bXWINbTn0vC0FYc9GaQTISbxhQLAMrvtbuvD9N6JelEaIS/Pr62wUCinrq5bf1WRBGczt1v4wDhxFtVFNcMdUQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Binder": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.56.0", + "contentHash": "rr4zbidvHy9r4NvOAs5hdd964Ao2A0pAeFBJKR95u1CJAVzbd1p6tPTXUZ+5ld0cfThiVSGvz6UHwY6JjraTpA==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "6.22.0" + } + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "4.56.0", + "contentHash": "H12YAzEGK55vZ+QpxUzozhW8ZZtgPDuWvgA0JbdIR9UhMUplj29JhIgE2imuH8W2Nw9D8JKygR1uxRFtpSNcrg==", + "dependencies": { + "Microsoft.Identity.Client": "4.56.0", + "System.IO.FileSystem.AccessControl": "5.0.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Abstractions": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "gIw8Sr5ZpuzKFBTfJonh2F54DivTzm5IIK15QB4Y6uE30uQdEO1NnCojTC/b6sWZoZzD0sdBa6SqwMXhucD+nA==" + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "mXA6AoaD5uZqtsKghgRiupBhyXNii8p9F2BjNLnDGud0tZLS5+4Fio2YAGjFXhnkc80CqgQ61X5U1gUNnDEoKQ==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "7.3.1" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "uPt2aiRUCbcOc0Wk+dDCSClFfPNs3S3Z7fmy50MoxJ1mGmtVUDMpyRJeYzZ/16x4rL19T+g2zrzjcWoitp5+gQ==", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "7.3.1" + } + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.35.0", + "contentHash": "BPQhlDzdFvv1PzaUxNSk+VEPwezlDEVADIKmyxubw7IiELK18uJ06RQ9QKKkds30XI+gDu9n8j24XQ8w7fjWcg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.35.0", + "Microsoft.IdentityModel.Tokens": "6.35.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.35.0", + "contentHash": "LMtVqnECCCdSmyFoCOxIE5tXQqkOLrvGrL7OxHg41DIm1bpWtaCdGyVcTAfOQpJXvzND9zUKIN/lhngPkYR8vg==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.35.0", + "System.IdentityModel.Tokens.Jwt": "6.35.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "/c/p8/3CAH706c0ii5uTgSb/8M/jwyuurtdMeKTBeKFU9aA+EZrLu1M8aaS3CSlGaxoxsoaxr4/+KXykgQ4VgQ==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "7.3.1" + } + }, + "Microsoft.SqlServer.Server": { + "type": "Transitive", + "resolved": "1.0.0", + "contentHash": "N4KeF3cpcm1PUHym1RmakkzfkEv3GRMyofVv40uXsQhCQeglr2OHNcUk2WOG51AKpGO8ynGpo9M/kFXSzghwug==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.10.0-release-24177-07", + "contentHash": "Km1jsYkTtwZmN3EQ4kom76eZiN/WXWiMkk007NpL39lP6OtFD2NARw4bqs+NMokIFQZrMwqtt+IVtvDgbkiQbA==", + "dependencies": { + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.10.0-release-24177-07", + "contentHash": "yPFZE4cUyJLMsDCHY8EC8N945Cxy+sXB8Epa5aC3glcAMlm9vziUtKDvbY1lNmMB8Ri2E4OHfEQuor1/pLWqtg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.10.0-release-24177-07", + "Newtonsoft.Json": "13.0.1" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "pKvznVpvK35cJb21LdjvhB3MW2FrlAqG3PH36uVKHhlgnfMS5tIRsKJEMgo0hiPyJJhN2f1llHptu2w8CvF9Vg==", + "dependencies": { + "BouncyCastle.Cryptography": "2.3.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Security.Cryptography.Pkcs": "8.0.0", + "System.Text.Encoding.CodePages": "8.0.0" + } + }, + "Mono.Cecil": { + "type": "Transitive", + "resolved": "0.11.5", + "contentHash": "fxfX+0JGTZ8YQeu1MYjbBiK2CYTSzDyEeIixt+yqKKTn7FW8rv7JMY70qevup4ZJfD7Kk/VG/jDzQQTpfch87g==" + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.CodeDom": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "WTlRjL6KWIMr/pAaq3rYqh0TJlzpouaQ/W1eelssHgtlwHAH25jXTkUphTYx9HaIIf7XA6qs/0+YhtLEQRkJ+Q==" + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg==" + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "jXw9MlUu/kRfEU0WyTptAVueupqIeE3/rl0EZDMlf8pcvJnitQ8HeVEp69rZdaStXwTV72boi/Bhw8lOeO+U2w==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "KiLYDu2k2J82Q9BJpWiuQqCkFjRBWVq4jDzKKWawVi9KWzyD0XG3cmfX0vqTQlL14Wi9EufJrbL0+KCLTbqWiQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "lcyUiXTsETK2ALsZrX+nWuHSIQeazhqPphLfaRxzdGaG93+0kELqpgEHtwWOlQe7+jSFnKwaCAgL4kjeZCQJnw==" + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "AJukBuLoe3QeAF+mfaRKQb2dgyrvt340iMBHYv+VdBzCUM06IxGlvl0o/uPOS7lHnXPN6u8fFRHSHudx5aTi8w==" + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "7.3.1", + "contentHash": "iE8biOWyAC1NnYcZGcgXErNACvIQ6Gcmg5s28gsjVbyyYdF9NdKsYzAPAsO3KGK86EQjpToI1AO82XbG8chkzA==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "7.3.1", + "Microsoft.IdentityModel.Tokens": "7.3.1" + } + }, + "System.IO.FileSystem.AccessControl": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "SxHB3nuNrpptVk+vZ/F+7OHEpoHUIKKMl02bUmYHQr1r+glbZQxs7pRtsf4ENO29TVm2TH3AEeep2fJcy92oYw==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "sDnWM0N3AMCa86LrKTWeF3BZLD2sgWyYUc7HL6z4+xyDZNQRwzmxbo4qP2rX2MqC+Sy1/gOSRDah5ltxY5jPxw==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "mXX66shZ4xLlI3vNLaJ0lt8OIZdmXTvIqXRdQX5HLVGSkLhINLsVhyZuX2UdRFnOGkqnwmMUs40pIIQ7mna4+A==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "E0e03kUp5X2k+UAoVl6efmI7uU7JRBWi5EIdlQ7cr0NpBGjHG4fWII35PgsBY9T4fJQ8E4QPsL0rKksU9gcL5A==", + "dependencies": { + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ULmp3xoOwNYjOYp4JZ2NK/6NdTgiN1GQXzVVN1njQ7LOZ0d0B9vyMnhyqbIi9Qw4JXj1JgCsitkTShboHRx7Eg==", + "dependencies": { + "System.Formats.Asn1": "8.0.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.7", + "contentHash": "/Tf/9XjprpHolbcDOrxsKVYy/mUG/FS7aGd9YUgBVEiHeQH4kAE0T1sMbde7q6B5xcrNUsJ5iW7D1RvHudQNqA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TY8/9+tI0mNaUMgntOxxaq2ndTkdXqLSxvPmas7XEqOlv9lQtB7wLjYGd756lOaO7Dvb5r/WXhluM+0Xe87v5Q==" + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "Yarp.ReverseProxy": { + "type": "Transitive", + "resolved": "2.0.1", + "contentHash": "op7vBwONPFeR1PYxeLw+RLqSodODDX8RWd0OinLGMVIq6yi1q9mv1j56ImuyZgiAToksiC0Dc7jbRUZ9I+jvFA==", + "dependencies": { + "System.IO.Hashing": "7.0.0" + } + }, + "Kentico.Xperience.WebApp": { + "type": "CentralTransitive", + "requested": "[28.1.0, )", + "resolved": "28.4.3", + "contentHash": "tFsbmisfYQrLdKtH35z9LL/D9UeqIb9T3o8WqKuIWOaZlOZDlxpaohzlh0raUuTGtJ14OE7kYgln1vGg4lvonw==", + "dependencies": { + "CommandLineParser": "2.9.1", + "HotChocolate.AspNetCore": "13.9.0", + "HotChocolate.Data": "13.9.0", + "HtmlSanitizer": "8.0.843", + "Kentico.Xperience.Core": "[28.4.3]", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.FileProviders.Embedded": "6.0.28", + "Microsoft.Extensions.Localization": "6.0.28" + } + } + } + } +} \ No newline at end of file diff --git a/Kentico.Xperience.RepoTemplate.sln b/Kentico.Xperience.RepoTemplate.sln deleted file mode 100644 index d7f6689..0000000 --- a/Kentico.Xperience.RepoTemplate.sln +++ /dev/null @@ -1,19 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.33516.290 -MinimumVisualStudioVersion = 10.0.40219.1 -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {1B2A20BC-F57B-4AAE-B1C2-E4DC52EFCAC5} - EndGlobalSection -EndGlobal diff --git a/src/.gitkeep b/src/.gitkeep deleted file mode 100644 index e69de29..0000000