From 285b973a5c6520caf78a83738748a928df6cf2de Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Thu, 1 Jun 2017 16:34:41 -0700 Subject: [PATCH] Use IHostingEnvironment to determine application identifier Reverses changes made in #230 --- ...taProtectionServiceCollectionExtensions.cs | 2 + .../HostingApplicationDiscriminator.cs | 25 +++++++ ...Microsoft.AspNetCore.DataProtection.csproj | 1 + .../DataProtectionUtilityExtensionsTests.cs | 65 ++++++++++++++++--- 4 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 src/Microsoft.AspNetCore.DataProtection/Internal/HostingApplicationDiscriminator.cs diff --git a/src/Microsoft.AspNetCore.DataProtection/DataProtectionServiceCollectionExtensions.cs b/src/Microsoft.AspNetCore.DataProtection/DataProtectionServiceCollectionExtensions.cs index 95fef0d55c..04e68303d0 100644 --- a/src/Microsoft.AspNetCore.DataProtection/DataProtectionServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNetCore.DataProtection/DataProtectionServiceCollectionExtensions.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.Cryptography.Cng; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.DataProtection.Infrastructure; using Microsoft.AspNetCore.DataProtection.Internal; using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; @@ -75,6 +76,7 @@ namespace Microsoft.Extensions.DependencyInjection ServiceDescriptor.Transient, DataProtectionOptionsSetup>()); services.TryAddSingleton(); + services.TryAddSingleton(); // Internal services services.TryAddSingleton(); diff --git a/src/Microsoft.AspNetCore.DataProtection/Internal/HostingApplicationDiscriminator.cs b/src/Microsoft.AspNetCore.DataProtection/Internal/HostingApplicationDiscriminator.cs new file mode 100644 index 0000000000..400d372418 --- /dev/null +++ b/src/Microsoft.AspNetCore.DataProtection/Internal/HostingApplicationDiscriminator.cs @@ -0,0 +1,25 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.DataProtection.Infrastructure; +using Microsoft.AspNetCore.Hosting; + +namespace Microsoft.AspNetCore.DataProtection.Internal +{ + internal class HostingApplicationDiscriminator : IApplicationDiscriminator + { + private readonly IHostingEnvironment _hosting; + + // the optional constructor for when IHostingEnvironment is not available from DI + public HostingApplicationDiscriminator() + { + } + + public HostingApplicationDiscriminator(IHostingEnvironment hosting) + { + _hosting = hosting; + } + + public string Discriminator => _hosting?.ContentRootPath; + } +} diff --git a/src/Microsoft.AspNetCore.DataProtection/Microsoft.AspNetCore.DataProtection.csproj b/src/Microsoft.AspNetCore.DataProtection/Microsoft.AspNetCore.DataProtection.csproj index 4ecef314c9..6495b57699 100644 --- a/src/Microsoft.AspNetCore.DataProtection/Microsoft.AspNetCore.DataProtection.csproj +++ b/src/Microsoft.AspNetCore.DataProtection/Microsoft.AspNetCore.DataProtection.csproj @@ -21,6 +21,7 @@ + diff --git a/test/Microsoft.AspNetCore.DataProtection.Test/DataProtectionUtilityExtensionsTests.cs b/test/Microsoft.AspNetCore.DataProtection.Test/DataProtectionUtilityExtensionsTests.cs index f1b2f508da..5af33b1b25 100644 --- a/test/Microsoft.AspNetCore.DataProtection.Test/DataProtectionUtilityExtensionsTests.cs +++ b/test/Microsoft.AspNetCore.DataProtection.Test/DataProtectionUtilityExtensionsTests.cs @@ -3,6 +3,8 @@ using System; using Microsoft.AspNetCore.DataProtection.Infrastructure; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; @@ -11,28 +13,75 @@ namespace Microsoft.AspNetCore.DataProtection public class DataProtectionUtilityExtensionsTests { [Theory] - [InlineData(" discriminator", "discriminator")] // normalized trim - [InlineData("", null)] // app discriminator not null -> overrides app base path + [InlineData("app-path", "app-path")] + [InlineData("app-path ", "app-path")] // normalized trim + [InlineData(" ", null)] // normalized whitespace -> null [InlineData(null, null)] // nothing provided at all - public void GetApplicationUniqueIdentifier(string appDiscriminator, string expected) + public void GetApplicationUniqueIdentifierFromHosting(string contentRootPath, string expected) { // Arrange - var mockAppDiscriminator = new Mock(); - mockAppDiscriminator.Setup(o => o.Discriminator).Returns(appDiscriminator); - var mockServiceProvider = new Mock(); - mockServiceProvider.Setup(o => o.GetService(typeof(IApplicationDiscriminator))).Returns(mockAppDiscriminator.Object); + var mockEnvironment = new Mock(); + mockEnvironment.Setup(o => o.ContentRootPath).Returns(contentRootPath); + + var services = new ServiceCollection() + .AddSingleton(mockEnvironment.Object) + .AddDataProtection() + .Services + .BuildServiceProvider(); // Act - string actual = mockServiceProvider.Object.GetApplicationUniqueIdentifier(); + var actual = services.GetApplicationUniqueIdentifier(); // Assert Assert.Equal(expected, actual); } + [Theory] + [InlineData(" discriminator ", "discriminator")] + [InlineData(" discriminator", "discriminator")] // normalized trim + [InlineData(" ", null)] // normalized whitespace -> null + [InlineData(null, null)] // nothing provided at all + public void GetApplicationIdentifierFromApplicationDiscriminator(string discriminator, string expected) + { + // Arrange + var mockAppDiscriminator = new Mock(); + mockAppDiscriminator.Setup(o => o.Discriminator).Returns(discriminator); + + var mockEnvironment = new Mock(); + mockEnvironment.SetupGet(o => o.ContentRootPath).Throws(new InvalidOperationException("Hosting environment should not be checked")); + + var services = new ServiceCollection() + .AddSingleton(mockEnvironment.Object) + .AddSingleton(mockAppDiscriminator.Object) + .AddDataProtection() + .Services + .BuildServiceProvider(); + + // Act + var actual = services.GetApplicationUniqueIdentifier(); + + // Assert + Assert.Equal(expected, actual); + mockAppDiscriminator.VerifyAll(); + } + [Fact] public void GetApplicationUniqueIdentifier_NoServiceProvider_ReturnsNull() { Assert.Null(((IServiceProvider)null).GetApplicationUniqueIdentifier()); } + + [Fact] + public void GetApplicationUniqueIdentifier_NoHostingEnvironment_ReturnsNull() + { + // arrange + var services = new ServiceCollection() + .AddDataProtection() + .Services + .BuildServiceProvider(); + + // act & assert + Assert.Null(services.GetApplicationUniqueIdentifier()); + } } }