From 9d8f13a09d6011510151cd53960c65390a95fc2b Mon Sep 17 00:00:00 2001 From: James R Sconfitto Date: Thu, 30 May 2013 11:34:56 -0400 Subject: [PATCH 1/6] Switch off the default diagnostic provider Remove the default testing diagnostic provider if another implementation is found. --- src/Nancy/Diagnostics/DefaultDiagnostics.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Nancy/Diagnostics/DefaultDiagnostics.cs b/src/Nancy/Diagnostics/DefaultDiagnostics.cs index ee4404a47e..32368ec243 100644 --- a/src/Nancy/Diagnostics/DefaultDiagnostics.cs +++ b/src/Nancy/Diagnostics/DefaultDiagnostics.cs @@ -1,6 +1,7 @@ namespace Nancy.Diagnostics { using System.Collections.Generic; + using System.Linq; using ModelBinding; using Nancy.Bootstrapper; using Responses.Negotiation; @@ -24,7 +25,6 @@ public class DefaultDiagnostics : IDiagnostics public DefaultDiagnostics(DiagnosticsConfiguration diagnosticsConfiguration, IEnumerable diagnosticProviders, IRootPathProvider rootPathProvider, IEnumerable serializers, IRequestTracing requestTracing, NancyInternalConfiguration configuration, IModelBinderLocator modelBinderLocator, IEnumerable responseProcessors, ICultureService cultureService) { this.diagnosticsConfiguration = diagnosticsConfiguration; - this.diagnosticProviders = diagnosticProviders; this.rootPathProvider = rootPathProvider; this.serializers = serializers; this.requestTracing = requestTracing; @@ -32,6 +32,15 @@ public DefaultDiagnostics(DiagnosticsConfiguration diagnosticsConfiguration, IEn this.modelBinderLocator = modelBinderLocator; this.responseProcessors = responseProcessors; this.cultureService = cultureService; + + if (diagnosticProviders.Count() > 2) + { + this.diagnosticProviders = diagnosticProviders.Where(diagProv => diagProv.GetType() != typeof(Nancy.Diagnostics.TestingDiagnosticProvider)); + } + else + { + this.diagnosticProviders = diagnosticProviders; + } } /// From 0aacb6de4bcc1d044e95b1637b547ceb771f5291 Mon Sep 17 00:00:00 2001 From: James R Sconfitto Date: Mon, 3 Jun 2013 12:12:32 -0400 Subject: [PATCH 2/6] Exclude testing diagnostics provider This will exclude the testing diagnostics provider from Nancy if there's another interactive diagnostics provider available. --- src/Nancy/Diagnostics/InteractiveDiagnostics.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Nancy/Diagnostics/InteractiveDiagnostics.cs b/src/Nancy/Diagnostics/InteractiveDiagnostics.cs index fe5d70ebe6..7d7fc5a7df 100644 --- a/src/Nancy/Diagnostics/InteractiveDiagnostics.cs +++ b/src/Nancy/Diagnostics/InteractiveDiagnostics.cs @@ -15,7 +15,21 @@ public class InteractiveDiagnostics : IInteractiveDiagnostics public InteractiveDiagnostics(IEnumerable providers) { - this.providers = providers.ToArray(); + var onlyNancyProviders = providers.All(provider => + { + return provider.GetType() == typeof(Nancy.Diagnostics.TestingDiagnosticProvider) || + provider.GetType() == typeof(Nancy.Routing.DefaultRouteCacheProvider); + }); + + if (!onlyNancyProviders) + { + // Exclude the TestingDiagnosticProvider + this.providers = providers.Where(provider => provider.GetType() != typeof(Nancy.Diagnostics.TestingDiagnosticProvider)).ToArray(); + } + else + { + this.providers = providers.ToArray(); + } this.BuildAvailableDiagnostics(); } From 6c76473636b095487b7c05eda4d553bdc4e97e3d Mon Sep 17 00:00:00 2001 From: James R Sconfitto Date: Mon, 3 Jun 2013 12:13:50 -0400 Subject: [PATCH 3/6] Revert "Switch off the default diagnostic provider" This reverts commit 9d8f13a09d6011510151cd53960c65390a95fc2b. --- src/Nancy/Diagnostics/DefaultDiagnostics.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Nancy/Diagnostics/DefaultDiagnostics.cs b/src/Nancy/Diagnostics/DefaultDiagnostics.cs index 32368ec243..ee4404a47e 100644 --- a/src/Nancy/Diagnostics/DefaultDiagnostics.cs +++ b/src/Nancy/Diagnostics/DefaultDiagnostics.cs @@ -1,7 +1,6 @@ namespace Nancy.Diagnostics { using System.Collections.Generic; - using System.Linq; using ModelBinding; using Nancy.Bootstrapper; using Responses.Negotiation; @@ -25,6 +24,7 @@ public class DefaultDiagnostics : IDiagnostics public DefaultDiagnostics(DiagnosticsConfiguration diagnosticsConfiguration, IEnumerable diagnosticProviders, IRootPathProvider rootPathProvider, IEnumerable serializers, IRequestTracing requestTracing, NancyInternalConfiguration configuration, IModelBinderLocator modelBinderLocator, IEnumerable responseProcessors, ICultureService cultureService) { this.diagnosticsConfiguration = diagnosticsConfiguration; + this.diagnosticProviders = diagnosticProviders; this.rootPathProvider = rootPathProvider; this.serializers = serializers; this.requestTracing = requestTracing; @@ -32,15 +32,6 @@ public DefaultDiagnostics(DiagnosticsConfiguration diagnosticsConfiguration, IEn this.modelBinderLocator = modelBinderLocator; this.responseProcessors = responseProcessors; this.cultureService = cultureService; - - if (diagnosticProviders.Count() > 2) - { - this.diagnosticProviders = diagnosticProviders.Where(diagProv => diagProv.GetType() != typeof(Nancy.Diagnostics.TestingDiagnosticProvider)); - } - else - { - this.diagnosticProviders = diagnosticProviders; - } } /// From a9415f73cc3f416516f0484ba8b1c79cfc9496f6 Mon Sep 17 00:00:00 2001 From: James R Sconfitto Date: Mon, 3 Jun 2013 12:29:29 -0400 Subject: [PATCH 4/6] Try to make the logic more readable --- src/Nancy/Diagnostics/InteractiveDiagnostics.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Nancy/Diagnostics/InteractiveDiagnostics.cs b/src/Nancy/Diagnostics/InteractiveDiagnostics.cs index 7d7fc5a7df..29c1ad00a1 100644 --- a/src/Nancy/Diagnostics/InteractiveDiagnostics.cs +++ b/src/Nancy/Diagnostics/InteractiveDiagnostics.cs @@ -15,15 +15,17 @@ public class InteractiveDiagnostics : IInteractiveDiagnostics public InteractiveDiagnostics(IEnumerable providers) { - var onlyNancyProviders = providers.All(provider => + var customProvidersAvailable = providers.Any(provider => { - return provider.GetType() == typeof(Nancy.Diagnostics.TestingDiagnosticProvider) || - provider.GetType() == typeof(Nancy.Routing.DefaultRouteCacheProvider); + Type providerType = provider.GetType(); + + return providerType != typeof(Nancy.Diagnostics.TestingDiagnosticProvider) & + providerType != typeof(Nancy.Routing.DefaultRouteCacheProvider); }); - if (!onlyNancyProviders) + if (customProvidersAvailable) { - // Exclude the TestingDiagnosticProvider + // Exclude only the TestingDiagnosticProvider this.providers = providers.Where(provider => provider.GetType() != typeof(Nancy.Diagnostics.TestingDiagnosticProvider)).ToArray(); } else From f6847ab5c15e2dda47e3f7c593f11d8343aaccc3 Mon Sep 17 00:00:00 2001 From: James R Sconfitto Date: Mon, 3 Jun 2013 14:48:41 -0400 Subject: [PATCH 5/6] Add tests --- src/Nancy.Tests/Nancy.Tests.csproj | 1 + .../CustomInteractiveDiagnosticsFixture.cs | 138 ++++++++++++++++++ .../Diagnostics/DiagnosticsHookFixture.cs | 26 ++++ 3 files changed, 165 insertions(+) create mode 100644 src/Nancy.Tests/Unit/Diagnostics/CustomInteractiveDiagnosticsFixture.cs diff --git a/src/Nancy.Tests/Nancy.Tests.csproj b/src/Nancy.Tests/Nancy.Tests.csproj index 192368c89c..2c0858585d 100644 --- a/src/Nancy.Tests/Nancy.Tests.csproj +++ b/src/Nancy.Tests/Nancy.Tests.csproj @@ -140,6 +140,7 @@ + diff --git a/src/Nancy.Tests/Unit/Diagnostics/CustomInteractiveDiagnosticsFixture.cs b/src/Nancy.Tests/Unit/Diagnostics/CustomInteractiveDiagnosticsFixture.cs new file mode 100644 index 0000000000..224f5ee9d3 --- /dev/null +++ b/src/Nancy.Tests/Unit/Diagnostics/CustomInteractiveDiagnosticsFixture.cs @@ -0,0 +1,138 @@ +namespace Nancy.Tests.Unit.Diagnostics +{ + using System; + using System.Collections.Generic; + using System.Linq; + + using Fakes; + using FakeItEasy; + using Nancy.Bootstrapper; + using Nancy.Cookies; + using Nancy.Cryptography; + using Nancy.Culture; + using Nancy.Diagnostics; + using Nancy.ModelBinding; + using Nancy.Responses.Negotiation; + using Nancy.Testing; + using Xunit; + + public class CustomInteractiveDiagnosticsHookFixture + { + private const string DiagsCookieName = "__ncd"; + + private readonly CryptographyConfiguration cryptoConfig; + + private readonly IObjectSerializer objectSerializer; + + public CustomInteractiveDiagnosticsHookFixture() + { + this.cryptoConfig = CryptographyConfiguration.Default; + this.objectSerializer = new DefaultObjectSerializer(); + } + + private class FakeDiagnostics : IDiagnostics + { + private readonly DiagnosticsConfiguration diagnosticsConfiguration; + private readonly IEnumerable diagnosticProviders; + private readonly IRootPathProvider rootPathProvider; + private readonly IEnumerable serializers; + private readonly IRequestTracing requestTracing; + private readonly NancyInternalConfiguration configuration; + private readonly IModelBinderLocator modelBinderLocator; + private readonly IEnumerable responseProcessors; + private readonly ICultureService cultureService; + + public FakeDiagnostics(DiagnosticsConfiguration diagnosticsConfiguration, IEnumerable diagnosticProviders, IRootPathProvider rootPathProvider, IEnumerable serializers, IRequestTracing requestTracing, NancyInternalConfiguration configuration, IModelBinderLocator modelBinderLocator, IEnumerable responseProcessors, ICultureService cultureService) + { + this.diagnosticsConfiguration = diagnosticsConfiguration; + this.diagnosticProviders = (new IDiagnosticsProvider[] { new FakeDiagnosticsProvider() }).ToArray(); + this.rootPathProvider = rootPathProvider; + this.serializers = serializers; + this.requestTracing = requestTracing; + this.configuration = configuration; + this.modelBinderLocator = modelBinderLocator; + this.responseProcessors = responseProcessors; + this.cultureService = cultureService; + } + + public void Initialize(IPipelines pipelines) + { + DiagnosticsHook.Enable(this.diagnosticsConfiguration, pipelines, this.diagnosticProviders, this.rootPathProvider, this.serializers, this.requestTracing, this.configuration, this.modelBinderLocator, this.responseProcessors, this.cultureService); + } + } + + private class FakeDiagnosticsProvider : IDiagnosticsProvider + { + public string Name + { + get { return "Fake testing provider"; } + } + + public string Description + { + get { return "Fake testing provider"; } + } + + public object DiagnosticObject + { + get { return this; } + } + } + + [Fact] + public void Should_return_main_page_with_valid_auth_cookie() + { + // Given + var diagsConfig = new DiagnosticsConfiguration { Password = "password", CryptographyConfiguration = this.cryptoConfig }; + + var bootstrapper = new ConfigurableBootstrapper(with => + { + with.EnableAutoRegistration(); + with.DiagnosticsConfiguration(diagsConfig); + with.Diagnostics(); + }); + + var browser = new Browser(bootstrapper); + + // When + var result = browser.Get(diagsConfig.Path + "/interactive/providers/", with => + { + with.Cookie(DiagsCookieName, this.GetSessionCookieValue("password")); + }); + + // Then should see our fake provider and not the default testing provider + result.Body.AsString().ShouldContain("Fake testing provider"); + result.Body.AsString().ShouldNotContain("Testing Diagnostic Provider"); + } + + private string GetSessionCookieValue(string password, DateTime? expiry = null) + { + var salt = DiagnosticsSession.GenerateRandomSalt(); + var hash = DiagnosticsSession.GenerateSaltedHash(password, salt); + var session = new DiagnosticsSession + { + Hash = hash, + Salt = salt, + Expiry = expiry.HasValue ? expiry.Value : DateTime.Now.AddMinutes(15), + }; + + var serializedSession = this.objectSerializer.Serialize(session); + + var encryptedSession = this.cryptoConfig.EncryptionProvider.Encrypt(serializedSession); + var hmacBytes = this.cryptoConfig.HmacProvider.GenerateHmac(encryptedSession); + var hmacString = Convert.ToBase64String(hmacBytes); + + return String.Format("{1}{0}", encryptedSession, hmacString); + } + + private DiagnosticsSession DecodeCookie(INancyCookie nancyCookie) + { + var cookieValue = nancyCookie.Value; + var hmacStringLength = Base64Helpers.GetBase64Length(this.cryptoConfig.HmacProvider.HmacLength); + var encryptedSession = cookieValue.Substring(hmacStringLength); + var decrypted = this.cryptoConfig.EncryptionProvider.Decrypt(encryptedSession); + + return this.objectSerializer.Deserialize(decrypted) as DiagnosticsSession; + } + } +} diff --git a/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs b/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs index 8d0541cb63..95163f1207 100644 --- a/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs +++ b/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs @@ -244,6 +244,32 @@ public void Should_use_rolling_expiry_for_auth_cookie() .Expiry.ShouldNotEqual(expiryDate); } + [Fact] + public void Should_return_diagnostic_example() + { + // Given no custom interactive diagnostic providers + var diagsConfig = new DiagnosticsConfiguration { Password = "password", CryptographyConfiguration = this.cryptoConfig }; + + var bootstrapper = new ConfigurableBootstrapper(with => + { + with.EnableAutoRegistration(); + with.DiagnosticsConfiguration(diagsConfig); + with.Diagnostics(); + }); + + var browser = new Browser(bootstrapper); + + // When querying the list of interactive providers + var result = browser.Get(diagsConfig.Path + "/interactive/providers/", with => + { + with.Cookie(DiagsCookieName, this.GetSessionCookieValue("password")); + }); + + // Then we should see the fake testing provider and not the Nancy provided testing example + result.Body.AsString().ShouldNotContain("Fake testing provider"); + result.Body.AsString().Contains("Testing Diagnostic Provider"); + } + private string GetSessionCookieValue(string password, DateTime? expiry = null) { var salt = DiagnosticsSession.GenerateRandomSalt(); From 8488c08d6f5d104ec4aa6aa9322f4e790ff3a16d Mon Sep 17 00:00:00 2001 From: James R Sconfitto Date: Mon, 3 Jun 2013 14:50:08 -0400 Subject: [PATCH 6/6] Format DiagnosticsHookFixture --- src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs b/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs index 95163f1207..c94540d61e 100644 --- a/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs +++ b/src/Nancy.Tests/Unit/Diagnostics/DiagnosticsHookFixture.cs @@ -29,7 +29,8 @@ public void Should_return_info_page_if_password_null() // Given var diagsConfig = new DiagnosticsConfiguration { Password = null, CryptographyConfiguration = this.cryptoConfig }; - var bootstrapper = new ConfigurableBootstrapper(with =>{ + var bootstrapper = new ConfigurableBootstrapper(with => + { with.EnableAutoRegistration(); with.DiagnosticsConfiguration(diagsConfig); with.Diagnostics(); @@ -296,7 +297,7 @@ private DiagnosticsSession DecodeCookie(INancyCookie nancyCookie) var hmacStringLength = Base64Helpers.GetBase64Length(this.cryptoConfig.HmacProvider.HmacLength); var encryptedSession = cookieValue.Substring(hmacStringLength); var decrypted = this.cryptoConfig.EncryptionProvider.Decrypt(encryptedSession); - + return this.objectSerializer.Deserialize(decrypted) as DiagnosticsSession; } }