From 59b98dbd9b7751400f5db04a2bb393eab487f7ec Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 10:03:10 +0000 Subject: [PATCH 01/35] EHD-1411: Reduce code in Core project: Move Obfuscator --- GenderPayGap.Core/GenderPayGap.Core.csproj | 2 -- GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs | 2 +- GenderPayGap.WebUI/Controllers/CompareEmployersController.cs | 1 - GenderPayGap.WebUI/Controllers/RedirectController.cs | 1 - GenderPayGap.WebUI/GenderPayGap.WebUI.csproj | 2 ++ .../Helpers/Obfuscator.cs | 4 +++- 6 files changed, 6 insertions(+), 6 deletions(-) rename GenderPayGap.Core/Classes/Obfuscation.cs => GenderPayGap.WebUI/Helpers/Obfuscator.cs (77%) diff --git a/GenderPayGap.Core/GenderPayGap.Core.csproj b/GenderPayGap.Core/GenderPayGap.Core.csproj index 31c13a93a..43bf7bc96 100644 --- a/GenderPayGap.Core/GenderPayGap.Core.csproj +++ b/GenderPayGap.Core/GenderPayGap.Core.csproj @@ -21,8 +21,6 @@ - - diff --git a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs index 1f31431d6..115ff452c 100644 --- a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs +++ b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Web; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Extensions; +using GenderPayGap.WebUI.Helpers; using Microsoft.AspNetCore.Http; using HttpContext = Microsoft.AspNetCore.Http.HttpContext; diff --git a/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs b/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs index 14b4d0b84..5f1d84f96 100644 --- a/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs +++ b/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; diff --git a/GenderPayGap.WebUI/Controllers/RedirectController.cs b/GenderPayGap.WebUI/Controllers/RedirectController.cs index cd4a61728..6fe8fe465 100644 --- a/GenderPayGap.WebUI/Controllers/RedirectController.cs +++ b/GenderPayGap.WebUI/Controllers/RedirectController.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.WebUI.Classes; diff --git a/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj b/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj index a60fbeb5a..c7866f8fb 100644 --- a/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj +++ b/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj @@ -94,6 +94,8 @@ + + diff --git a/GenderPayGap.Core/Classes/Obfuscation.cs b/GenderPayGap.WebUI/Helpers/Obfuscator.cs similarity index 77% rename from GenderPayGap.Core/Classes/Obfuscation.cs rename to GenderPayGap.WebUI/Helpers/Obfuscator.cs index 60fd99174..65b65628d 100644 --- a/GenderPayGap.Core/Classes/Obfuscation.cs +++ b/GenderPayGap.WebUI/Helpers/Obfuscator.cs @@ -1,4 +1,6 @@ -namespace GenderPayGap.Core.Classes +using GenderPayGap.Core; + +namespace GenderPayGap.WebUI.Helpers { public static class Obfuscator { From c1117664fb15fca25024e9532e50115ea7fffa88 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 10:07:30 +0000 Subject: [PATCH 02/35] EHD-1411: Reduce code in Core project: Move Autofac ContainerIOC from Global to Startup --- GenderPayGap.Core/GenderPayGap.Core.csproj | 3 -- GenderPayGap.Core/Global.cs | 4 --- .../Builders/ControllerBuilder.cs | 4 +-- .../Search/SearchRepositoryTests.cs | 28 +++++++++---------- .../TestHelpers/UiTestHelpers.cs | 6 +--- .../Admin/AdminDataMigrationController.cs | 4 +-- GenderPayGap.WebUI/GenderPayGap.WebUI.csproj | 1 + .../Helpers/DataProtectionKeysHelper.cs | 5 ++-- GenderPayGap.WebUI/Search/SearchRepository.cs | 2 +- GenderPayGap.WebUI/Startup.cs | 9 +++--- 10 files changed, 26 insertions(+), 40 deletions(-) diff --git a/GenderPayGap.Core/GenderPayGap.Core.csproj b/GenderPayGap.Core/GenderPayGap.Core.csproj index 43bf7bc96..d5d58af79 100644 --- a/GenderPayGap.Core/GenderPayGap.Core.csproj +++ b/GenderPayGap.Core/GenderPayGap.Core.csproj @@ -16,9 +16,6 @@ - - - diff --git a/GenderPayGap.Core/Global.cs b/GenderPayGap.Core/Global.cs index 0d496f59f..1fdf3c3ef 100644 --- a/GenderPayGap.Core/Global.cs +++ b/GenderPayGap.Core/Global.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Autofac; using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; using Newtonsoft.Json; @@ -11,9 +10,6 @@ namespace GenderPayGap.Core public static class Global { - public static IContainer ContainerIoC; - - #region Secrets / connection strings / API keys public static string DatabaseConnectionString => diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs index 27fe33c49..40ebbb39d 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs @@ -3,7 +3,6 @@ using System.Reflection; using System.Security.Claims; using Autofac; -using GenderPayGap.Core; using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; @@ -21,7 +20,6 @@ using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.Extensions.Primitives; using Moq; using Newtonsoft.Json; using NUnit.Framework; @@ -70,7 +68,7 @@ public ControllerBuilder WithMockUriHelper() public T Build() { IContainer DIContainer = BuildContainerIocForControllerOfType(); - Global.ContainerIoC = DIContainer; + Startup.ContainerIoC = DIContainer; var httpContextMock = new Mock(); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Search/SearchRepositoryTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Search/SearchRepositoryTests.cs index 406bb9b3b..82ceea925 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Search/SearchRepositoryTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Search/SearchRepositoryTests.cs @@ -23,7 +23,7 @@ public void LoadSearchDataIntoCache_Includes_RetiredOrganisationsWithSubmittedRe Status = OrganisationStatuses.Retired, Returns = new List {new Return {Status = ReturnStatuses.Submitted}} }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationWithSubmittedReports); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationWithSubmittedReports); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -43,7 +43,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_RetiredOrganisationsWithNoRep SectorType = SectorTypes.Private, Status = OrganisationStatuses.Retired }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationWithNoSubmittedReports); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationWithNoSubmittedReports); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -64,7 +64,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_RetiredOrganisationsWithDraft Status = OrganisationStatuses.Retired, Returns = new List {new Return {Status = ReturnStatuses.Draft}} }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationWithDraftReports); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationWithDraftReports); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -88,7 +88,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_RetiredOrganisationsInScope() new OrganisationScope {Status = ScopeRowStatuses.Active, ScopeStatus = ScopeStatuses.InScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationInScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationInScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -112,7 +112,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_RetiredOrganisationsPresumedI new OrganisationScope {Status = ScopeRowStatuses.Active, ScopeStatus = ScopeStatuses.PresumedInScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationPresumedInScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationPresumedInScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -136,7 +136,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_RetiredOrganisationsPreviousl new OrganisationScope {Status = ScopeRowStatuses.Retired, ScopeStatus = ScopeStatuses.InScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationPreviouslyInScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationPreviouslyInScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -160,7 +160,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_RetiredOrganisationsOutOfScop new OrganisationScope {Status = ScopeRowStatuses.Active, ScopeStatus = ScopeStatuses.OutOfScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationOutOfScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(retiredOrganisationOutOfScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -181,7 +181,7 @@ public void LoadSearchDataIntoCache_Includes_ActiveOrganisationsWithSubmittedRep Status = OrganisationStatuses.Active, Returns = new List {new Return {Status = ReturnStatuses.Submitted}} }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationWithSubmittedReports); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationWithSubmittedReports); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -206,7 +206,7 @@ public void LoadSearchDataIntoCache_Includes_ActiveOrganisationsWithDraftReports new OrganisationScope {Status = ScopeRowStatuses.Active, ScopeStatus = ScopeStatuses.PresumedInScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationWithDraftReports); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationWithDraftReports); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -230,7 +230,7 @@ public void LoadSearchDataIntoCache_Includes_ActiveOrganisationsInScope() new OrganisationScope {Status = ScopeRowStatuses.Active, ScopeStatus = ScopeStatuses.InScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationInScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationInScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -254,7 +254,7 @@ public void LoadSearchDataIntoCache_Includes_ActiveOrganisationsPresumedInScope( new OrganisationScope {Status = ScopeRowStatuses.Active, ScopeStatus = ScopeStatuses.PresumedInScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationPresumedInScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationPresumedInScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -278,7 +278,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_ActiveOrganisationsOutOfScope new OrganisationScope {Status = ScopeRowStatuses.Active, ScopeStatus = ScopeStatuses.OutOfScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationOutOfScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationOutOfScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -302,7 +302,7 @@ public void LoadSearchDataIntoCache_DoesNotIncludes_ActiveOrganisationsPreviousl new OrganisationScope {Status = ScopeRowStatuses.Retired, ScopeStatus = ScopeStatuses.InScope} } }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationPreviouslyInScope); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(activeOrganisationPreviouslyInScope); // Act SearchRepository.LoadSearchDataIntoCache(); @@ -323,7 +323,7 @@ public void LoadSearchDataIntoCache_DoesNotInclude_DeletedOrganisations() Status = OrganisationStatuses.Deleted, Returns = new List {new Return {Status = ReturnStatuses.Submitted}} }; - Global.ContainerIoC = UiTestHelper.BuildContainerIoC(deletedOrganisation); + Startup.ContainerIoC = UiTestHelper.BuildContainerIoC(deletedOrganisation); // Act SearchRepository.LoadSearchDataIntoCache(); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs index af0db9ff3..ba507a38b 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs @@ -7,8 +7,6 @@ using System.Reflection; using System.Security.Claims; using Autofac; -using Autofac.Features.AttributeFilters; -using GenderPayGap.Core; using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; @@ -37,8 +35,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; -using Microsoft.AspNetCore.Mvc.ViewFeatures; -using Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure; using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -65,7 +61,7 @@ public static T GetController(long userId = 0, RouteData routeData = null, pa DIContainer = BuildContainerIoC(dbObjects); //Create Inversion of Control container - Global.ContainerIoC = DIContainer; + Startup.ContainerIoC = DIContainer; //Mock UserId as claim var claims = new List(); diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs index 66b64d86c..6eca7b9b4 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs @@ -266,7 +266,7 @@ private void ImportDataFromJsonString(string fileAsString) InsertData(allData.ReminderEmails); WriteParagraph($"Starting Organisations and OrganisationPublicSectorTypes"); - var newDataRepository = Global.ContainerIoC.Resolve(); + var newDataRepository = Startup.ContainerIoC.Resolve(); newDataRepository.Insert(allData.Organisations); newDataRepository.Insert(allData.OrganisationPublicSectorTypes); newDataRepository.SaveChanges(); @@ -313,7 +313,7 @@ private void ImportDataFromJsonString(string fileAsString) private void InsertData(List items) where T : class { - var newDataRepository = Global.ContainerIoC.Resolve(); + var newDataRepository = Startup.ContainerIoC.Resolve(); newDataRepository.Insert(items); diff --git a/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj b/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj index c7866f8fb..331da8cd6 100644 --- a/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj +++ b/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj @@ -83,6 +83,7 @@ + diff --git a/GenderPayGap.WebUI/Helpers/DataProtectionKeysHelper.cs b/GenderPayGap.WebUI/Helpers/DataProtectionKeysHelper.cs index 678965aa3..bd6cc4189 100644 --- a/GenderPayGap.WebUI/Helpers/DataProtectionKeysHelper.cs +++ b/GenderPayGap.WebUI/Helpers/DataProtectionKeysHelper.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Xml.Linq; using Autofac; -using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database.Models; using GenderPayGap.Extensions; @@ -28,7 +27,7 @@ internal class CustomDataProtectionKeyRepository : IXmlRepository public IReadOnlyCollection GetAllElements() { - IDataRepository dataRepository = Global.ContainerIoC.Resolve(); + IDataRepository dataRepository = Startup.ContainerIoC.Resolve(); List dataProtectionKeys = dataRepository.GetAll() .ToList(); @@ -57,7 +56,7 @@ public void StoreElement(XElement element, string friendlyName) Xml = encryptedKey }; - IDataRepository dataRepository = Global.ContainerIoC.Resolve(); + IDataRepository dataRepository = Startup.ContainerIoC.Resolve(); dataRepository.Insert(dataProtectionKey); dataRepository.SaveChanges(); } diff --git a/GenderPayGap.WebUI/Search/SearchRepository.cs b/GenderPayGap.WebUI/Search/SearchRepository.cs index 378758cee..e76d3617d 100644 --- a/GenderPayGap.WebUI/Search/SearchRepository.cs +++ b/GenderPayGap.WebUI/Search/SearchRepository.cs @@ -27,7 +27,7 @@ public static class SearchRepository public static void LoadSearchDataIntoCache() { - using (ILifetimeScope scope = Global.ContainerIoC.BeginLifetimeScope()) + using (ILifetimeScope scope = Startup.ContainerIoC.BeginLifetimeScope()) { var dataRepository = scope.Resolve(); diff --git a/GenderPayGap.WebUI/Startup.cs b/GenderPayGap.WebUI/Startup.cs index 16f3f380c..f4127c47e 100644 --- a/GenderPayGap.WebUI/Startup.cs +++ b/GenderPayGap.WebUI/Startup.cs @@ -1,6 +1,4 @@ using System; -using System.IO; -using System.Linq; using System.Net.Http; using System.Web; using Autofac; @@ -34,7 +32,6 @@ using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.FileProviders; namespace GenderPayGap.WebUI { @@ -43,6 +40,8 @@ public class Startup public static Action ConfigureTestServices; public static Action ConfigureTestContainer; + + public static IContainer ContainerIoC; // ConfigureServices is where you register dependencies. This gets // called by the runtime before the ConfigureContainer method, below. @@ -135,10 +134,10 @@ public IServiceProvider ConfigureServices(IServiceCollection services) ConfigureTestServices?.Invoke(services); //Create Inversion of Control container - Global.ContainerIoC = BuildContainerIoC(services); + ContainerIoC = BuildContainerIoC(services); // Create the IServiceProvider based on the container. - return new AutofacServiceProvider(Global.ContainerIoC); + return new AutofacServiceProvider(ContainerIoC); } // ConfigureContainer is where you can register things directly From d3883f6c11897d25381c3e250ae82979581ae344 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 10:18:48 +0000 Subject: [PATCH 03/35] EHD-1411: Reduce code in Core project: Move CsvWriter --- GenderPayGap.Core/GenderPayGap.Core.csproj | 2 -- .../CoreTests/Helpers/CsvWriterTests.cs | 2 +- .../ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs | 1 + GenderPayGap.WebUI/GenderPayGap.WebUI.csproj | 2 ++ {GenderPayGap.Core => GenderPayGap.WebUI}/Helpers/CsvWriter.cs | 2 +- GenderPayGap.WebUI/Helpers/DownloadHelper.cs | 1 - 6 files changed, 5 insertions(+), 5 deletions(-) rename {GenderPayGap.Core => GenderPayGap.WebUI}/Helpers/CsvWriter.cs (98%) diff --git a/GenderPayGap.Core/GenderPayGap.Core.csproj b/GenderPayGap.Core/GenderPayGap.Core.csproj index d5d58af79..be7aeca7e 100644 --- a/GenderPayGap.Core/GenderPayGap.Core.csproj +++ b/GenderPayGap.Core/GenderPayGap.Core.csproj @@ -16,8 +16,6 @@ - - diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/CsvWriterTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/CsvWriterTests.cs index 4c9f1126f..805031b85 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/CsvWriterTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/CsvWriterTests.cs @@ -1,6 +1,6 @@ using System; using System.IO; -using GenderPayGap.Core.Helpers; +using GenderPayGap.WebUI.Helpers; using NUnit.Framework; namespace GenderPayGap.Core.Tests.Helpers diff --git a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs index 4cb220914..d0e7cf4fd 100644 --- a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs +++ b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs @@ -12,6 +12,7 @@ using GenderPayGap.Core.Models; using GenderPayGap.Database; using GenderPayGap.WebUI.ExternalServices.FileRepositories; +using GenderPayGap.WebUI.Helpers; using Microsoft.EntityFrameworkCore; namespace GenderPayGap.WebUI.BackgroundJobs.ScheduledJobs diff --git a/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj b/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj index 331da8cd6..d61714684 100644 --- a/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj +++ b/GenderPayGap.WebUI/GenderPayGap.WebUI.csproj @@ -90,6 +90,8 @@ + + diff --git a/GenderPayGap.Core/Helpers/CsvWriter.cs b/GenderPayGap.WebUI/Helpers/CsvWriter.cs similarity index 98% rename from GenderPayGap.Core/Helpers/CsvWriter.cs rename to GenderPayGap.WebUI/Helpers/CsvWriter.cs index d098a5743..969776d74 100644 --- a/GenderPayGap.Core/Helpers/CsvWriter.cs +++ b/GenderPayGap.WebUI/Helpers/CsvWriter.cs @@ -5,7 +5,7 @@ using CsvHelper.Configuration; using CsvHelper.TypeConversion; -namespace GenderPayGap.Core.Helpers +namespace GenderPayGap.WebUI.Helpers { public static class CsvWriter { diff --git a/GenderPayGap.WebUI/Helpers/DownloadHelper.cs b/GenderPayGap.WebUI/Helpers/DownloadHelper.cs index 8679a7a1c..1996a45cf 100644 --- a/GenderPayGap.WebUI/Helpers/DownloadHelper.cs +++ b/GenderPayGap.WebUI/Helpers/DownloadHelper.cs @@ -3,7 +3,6 @@ using System.IO; using System.Text; using CsvHelper.TypeConversion; -using GenderPayGap.Core.Helpers; using Microsoft.AspNetCore.Mvc; namespace GenderPayGap.WebUI.Helpers From 1e762d0f92ad335ca6cf13ac227c0cd5b306d23d Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 10:27:38 +0000 Subject: [PATCH 04/35] EHD-1411: Reduce code in Core project: Simplify SecurityHeaderMiddleware --- .../AspNetCore/SecurityHeaderMiddleware.cs | 16 ++-------------- GenderPayGap.Core/Extensions/Text.cs | 11 ----------- GenderPayGap.Core/Global.cs | 2 +- 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs b/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs index aec25ef83..fc569977b 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs @@ -13,27 +13,15 @@ public class SecurityHeaderMiddleware public SecurityHeaderMiddleware(RequestDelegate next) { _next = next; - _securityHeaders = Global.SecurityHeaders; } - private Dictionary _securityHeaders { get; } - public async Task Invoke(HttpContext httpContext) { httpContext.Response.OnStarting( () => { - foreach (string key in _securityHeaders.Keys) + foreach (KeyValuePair securityHeader in Global.SecurityHeaders) { - string value = _securityHeaders[key]; - - //Lookup the same value from another header - string varName = value.GetVariableName(); - if (!string.IsNullOrWhiteSpace(varName) && _securityHeaders.ContainsKey(varName)) - { - value = _securityHeaders[varName]; - } - - httpContext.SetResponseHeader(key, value); + httpContext.SetResponseHeader(securityHeader.Key, securityHeader.Value); } return Task.CompletedTask; diff --git a/GenderPayGap.Core/Extensions/Text.cs b/GenderPayGap.Core/Extensions/Text.cs index f75ba0157..2f235b7a0 100644 --- a/GenderPayGap.Core/Extensions/Text.cs +++ b/GenderPayGap.Core/Extensions/Text.cs @@ -32,17 +32,6 @@ public static bool IsNullOrWhiteSpace(this string input, params string[] inputs) return false; } - /// - /// Returns the name of the variable between $( and ) - /// - /// The text to search - /// The pattern to use - /// - public static string GetVariableName(this string text, string matchPattern = @"^\$\((.*)\)$") - { - return new Regex(matchPattern).Matches(text)?.FirstOrDefault()?.Groups[1]?.Value; - } - public static string TrimI(this string source, string trimChars) { if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(trimChars)) diff --git a/GenderPayGap.Core/Global.cs b/GenderPayGap.Core/Global.cs index 1fdf3c3ef..50a66f989 100644 --- a/GenderPayGap.Core/Global.cs +++ b/GenderPayGap.Core/Global.cs @@ -118,7 +118,7 @@ public static bool EnableSubmitAlerts {"X-Permitted-Cross-Domain-Policies", "master-only"}, {"X-Xss-Protection", "1; mode=block;"}, {"Content-Security-Policy", "frame-ancestors 'none'"}, - {"X-Content-Security-Policy", "$(Content-Security-Policy)"}, + {"X-Content-Security-Policy", "frame-ancestors 'none'"}, {"Referrer-Policy", "origin-when-cross-origin"}, {"Strict-Transport-Security", "max-age=31536000; includeSubDomains"}, {"X-Powered-By", ""}, From 1637c6d61a6e50ff7759ecc61320fb3674f07d1a Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 13:10:10 +0000 Subject: [PATCH 05/35] EHD-1411: Reduce code in Core project: Replace use of custom HttpContext.GetUri --- .../AspNetCore/Extensions.Middleware.cs | 9 +--- .../Extensions/AspNetCore/HttpContext.cs | 45 +------------------ .../AspNetCore/MaintenancePageMiddleware.cs | 5 +-- .../Builders/ControllerBuilder.cs | 7 --- .../TestHelpers/UiTestHelpers.cs | 12 ----- .../Classes/GoogleAnalyticsTracker.cs | 5 +-- .../Helpers/BasicAuthMiddleware.cs | 2 +- GenderPayGap.WebUI/Startup.cs | 1 - .../AddRemoveEmployerNew.cshtml | 2 +- .../CompareEmployersForYear.cshtml | 2 +- .../ViewReports/ComparisonBasketNew.cshtml | 2 +- 11 files changed, 10 insertions(+), 82 deletions(-) diff --git a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs b/GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs index 3fb3a5711..9ef9c7e8e 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using HttpContext = System.Web.HttpContext; @@ -8,13 +8,6 @@ namespace GenderPayGap.Extensions.AspNetCore public static partial class Extensions { - public static IApplicationBuilder UseStaticHttpContext(this IApplicationBuilder app) - { - var httpContextAccessor = app.ApplicationServices.GetRequiredService(); - HttpContext.Configure(httpContextAccessor); - return app; - } - public static IApplicationBuilder UseSecurityHeaderMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware(); diff --git a/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs b/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs index bdb752a22..5c0093ec7 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs @@ -1,22 +1,10 @@ -using GenderPayGap.Extensions; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.Extensions.Primitives; +using Microsoft.AspNetCore.Http; namespace System.Web { public static class HttpContext { - private static IHttpContextAccessor _contextAccessor; - - public static Microsoft.AspNetCore.Http.HttpContext Current => _contextAccessor?.HttpContext; - - public static void Configure(IHttpContextAccessor contextAccessor) - { - _contextAccessor = contextAccessor; - } - public static void SetResponseCache(this Microsoft.AspNetCore.Http.HttpContext context, int maxSeconds) { if (maxSeconds > 0) @@ -29,35 +17,6 @@ public static void SetResponseCache(this Microsoft.AspNetCore.Http.HttpContext c } } - public static string GetBrowser(this Microsoft.AspNetCore.Http.HttpContext context) - { - return context.Request?.Headers["User-Agent"].ToStringOrNull(); - } - - public static Uri GetUri(this Microsoft.AspNetCore.Http.HttpContext context) - { - string host = context.Request.Scheme.EqualsI("https") && context.Request.Host.Port == 443 - || context.Request.Scheme.EqualsI("http") && context.Request.Host.Port == 80 - ? context.Request.Host.Host - : context.Request.Host.ToString(); - string uri = $"{context.Request.Scheme}://{host}"; - string path = context.Request.Path.ToString().TrimI("/\\ "); - if (!string.IsNullOrWhiteSpace(path)) - { - uri += $"/{path}"; - } - - string querystring = context.Request.QueryString.ToString().TrimI("? "); - if (!string.IsNullOrWhiteSpace(querystring)) - { - uri += $"?{querystring}"; - } - - return new Uri(uri); - } - - #region Cookies - public static string GetRequestCookieValue(this Microsoft.AspNetCore.Http.HttpContext context, string key) { return context.Request.Cookies.ContainsKey(key) ? context.Request.Cookies[key] : null; @@ -89,7 +48,5 @@ public static void SetResponseCookie(this Microsoft.AspNetCore.Http.HttpContext } } - #endregion - } } diff --git a/GenderPayGap.Core/Extensions/AspNetCore/MaintenancePageMiddleware.cs b/GenderPayGap.Core/Extensions/AspNetCore/MaintenancePageMiddleware.cs index cfc9b0829..befc53b4d 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/MaintenancePageMiddleware.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/MaintenancePageMiddleware.cs @@ -1,5 +1,4 @@ using System.Threading.Tasks; -using System.Web; using Microsoft.AspNetCore.Http; using HttpContext = Microsoft.AspNetCore.Http.HttpContext; @@ -20,14 +19,14 @@ public MaintenancePageMiddleware(RequestDelegate next, bool enabled) public async Task Invoke(HttpContext httpContext) { - if (System.Web.HttpContext.GetUri(httpContext).PathAndQuery.StartsWith("/health-check")) + if (httpContext.Request.Path.Value.StartsWith("/health-check")) { await _next.Invoke(httpContext); return; } // Redirect to holding page if in maintenance mode - if (_enabled && !httpContext.GetUri().PathAndQuery.StartsWithI(@"/error/service-unavailable")) + if (_enabled && !httpContext.Request.Path.Value.StartsWithI(@"/error/service-unavailable")) { httpContext.Response.Redirect(@"/error/service-unavailable", permanent: false); } diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs index 40ebbb39d..56f82cdc5 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs @@ -80,13 +80,6 @@ public T Build() var routeData = new RouteData(); var controllerContextMock = new ControllerContext { HttpContext = httpContextMock.Object, RouteData = routeData }; - //Mock IHttpContextAccessor - Mock mockHttpContextAccessor = DIContainer.Resolve().GetMockFromObject(); - mockHttpContextAccessor.SetupGet(a => a.HttpContext).Returns(httpContextMock.Object); - - //Configure the global HttpContext using the mock accessor - System.Web.HttpContext.Configure(mockHttpContextAccessor.Object); - //Create and return the controller var controller = DIContainer.Resolve(); controller.ControllerContext = controllerContextMock; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs index ba507a38b..ee342ec08 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs @@ -170,18 +170,6 @@ public static T GetController(long userId = 0, RouteData routeData = null, pa //var controllerContextMock = new Mock(); var controllerContextMock = new ControllerContext {HttpContext = httpContextMock.Object, RouteData = routeData}; - if (routeData == null) - { - routeData = new RouteData(); - } - - //Mock IHttpContextAccessor - Mock mockHttpContextAccessor = DIContainer.Resolve().GetMockFromObject(); - mockHttpContextAccessor.SetupGet(a => a.HttpContext).Returns(httpContextMock.Object); - - //Configure the global HttpContext using the mock accessor - System.Web.HttpContext.Configure(mockHttpContextAccessor.Object); - //Create and return the controller var controller = DIContainer.Resolve(); diff --git a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs index 0c58de742..80dfe6527 100644 --- a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs +++ b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Net; using System.Net.Http; -using System.Web; using GenderPayGap.Extensions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -63,11 +62,11 @@ public void TrackPageView(Controller controller, string pageTitle = null, string if (string.IsNullOrWhiteSpace(pageUrl)) { - pageUrl = controller.HttpContext.GetUri().ToString(); + pageUrl = $"{controller.HttpContext.Request.Path}{controller.HttpContext.Request.QueryString}"; } else if (!pageUrl.IsUrl()) { - pageUrl = Url.RelativeToAbsoluteUrl(pageUrl, controller.HttpContext.GetUri()); + pageUrl = Url.RelativeToAbsoluteUrl(pageUrl, new Uri($"{controller.HttpContext.Request.Path}{controller.HttpContext.Request.QueryString}")); } SendPageViewTracking(pageTitle, pageUrl); diff --git a/GenderPayGap.WebUI/Helpers/BasicAuthMiddleware.cs b/GenderPayGap.WebUI/Helpers/BasicAuthMiddleware.cs index 15fbd9c91..630bc67a5 100644 --- a/GenderPayGap.WebUI/Helpers/BasicAuthMiddleware.cs +++ b/GenderPayGap.WebUI/Helpers/BasicAuthMiddleware.cs @@ -19,7 +19,7 @@ public BasicAuthMiddleware(RequestDelegate next) public async Task Invoke(HttpContext httpContext) { - if (System.Web.HttpContext.GetUri(httpContext).PathAndQuery.StartsWith("/health-check")) + if (httpContext.Request.Path.Value.StartsWith("/health-check")) { await _next.Invoke(httpContext); return; diff --git a/GenderPayGap.WebUI/Startup.cs b/GenderPayGap.WebUI/Startup.cs index f4127c47e..625f025be 100644 --- a/GenderPayGap.WebUI/Startup.cs +++ b/GenderPayGap.WebUI/Startup.cs @@ -282,7 +282,6 @@ public void Configure(IApplicationBuilder app, IApplicationLifetime lifetime) app.UseRouting(); app.UseResponseCaching(); app.UseResponseBuffering(); //required otherwise JsonResult uses chunking and adds extra characters - app.UseStaticHttpContext(); //Temporary fix for old static HttpContext app.UseSession(); //Must be before UseMvC or any middleware which requires session app.UseAuthentication(); //Ensure the OIDC IDentity Server authentication services execute on each http request - Must be before UseMVC app.UseAuthorization(); diff --git a/GenderPayGap.WebUI/Views/CompareEmployers/AddRemoveEmployerNew.cshtml b/GenderPayGap.WebUI/Views/CompareEmployers/AddRemoveEmployerNew.cshtml index 6ddf0a20f..82b49cc33 100644 --- a/GenderPayGap.WebUI/Views/CompareEmployers/AddRemoveEmployerNew.cshtml +++ b/GenderPayGap.WebUI/Views/CompareEmployers/AddRemoveEmployerNew.cshtml @@ -2,7 +2,7 @@ @model GenderPayGap.Database.Organisation @{ - string returnUrl = Context.GetUri().PathAndQuery; + string returnUrl = $"{Context.Request.Path}{Context.Request.QueryString}"; } @if (CompareViewService.BasketContains(Model.OrganisationId)) diff --git a/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml b/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml index f57d94691..685b20fe1 100644 --- a/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml +++ b/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml @@ -14,7 +14,7 @@ string reportingYearFormatted = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); ViewBag.Title = $"Compare employers' gender pay gaps for {reportingYearFormatted} reporting year"; - string currentRelativeUrl = Context.GetUri().PathAndQuery; + string currentRelativeUrl = $"{Context.Request.Path}{Context.Request.QueryString}"; string commaSeparatedListOfOrganisationIds = string.Join("-", Model.Organisations.Select(org => org.OrganisationId)); } diff --git a/GenderPayGap.WebUI/Views/ViewReports/ComparisonBasketNew.cshtml b/GenderPayGap.WebUI/Views/ViewReports/ComparisonBasketNew.cshtml index 5d8d1c454..d90ee414d 100644 --- a/GenderPayGap.WebUI/Views/ViewReports/ComparisonBasketNew.cshtml +++ b/GenderPayGap.WebUI/Views/ViewReports/ComparisonBasketNew.cshtml @@ -30,7 +30,7 @@
  • - Clear list From 3c9c6041363756d7d98a7ee96b7cfd309abea633 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 13:13:23 +0000 Subject: [PATCH 06/35] EHD-1411: Reduce code in Core project: Inline Extensions.Middleware code --- .../AspNetCore/Extensions.Middleware.cs | 22 ------------------- GenderPayGap.WebUI/Startup.cs | 4 ++-- 2 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs diff --git a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs b/GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs deleted file mode 100644 index 9ef9c7e8e..000000000 --- a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.Middleware.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using HttpContext = System.Web.HttpContext; - -namespace GenderPayGap.Extensions.AspNetCore -{ - public static partial class Extensions - { - - public static IApplicationBuilder UseSecurityHeaderMiddleware(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } - - public static IApplicationBuilder UseMaintenancePageMiddleware(this IApplicationBuilder builder, bool enable) - { - return builder.UseMiddleware(enable); - } - - } -} diff --git a/GenderPayGap.WebUI/Startup.cs b/GenderPayGap.WebUI/Startup.cs index 625f025be..b077be025 100644 --- a/GenderPayGap.WebUI/Startup.cs +++ b/GenderPayGap.WebUI/Startup.cs @@ -291,8 +291,8 @@ public void Configure(IApplicationBuilder app, IApplicationLifetime lifetime) MinimumSameSitePolicy = SameSiteMode.Lax, }; app.UseCookiePolicy(cookiePolicyOptions); - app.UseMaintenancePageMiddleware(Global.MaintenanceMode); //Redirect to maintenance page when Maintenance mode settings = true - app.UseSecurityHeaderMiddleware(); //Add/remove security headers from all responses + app.UseMiddleware(Global.MaintenanceMode); //Redirect to maintenance page when Maintenance mode settings = true + app.UseMiddleware(); //Add/remove security headers from all responses if (!string.IsNullOrWhiteSpace(Global.BasicAuthUsername) && !string.IsNullOrWhiteSpace(Global.BasicAuthPassword)) From 5ddf820d90b0b4d971ef7de2107e48ae173ac09a Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 13:28:06 +0000 Subject: [PATCH 07/35] EHD-1411: Reduce code in Core project: Inline GetRequestCookie code --- GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs | 5 ----- .../Classes/Presentation/CompareViewService.cs | 8 +++----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs b/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs index 5c0093ec7..6267ee9bd 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs @@ -17,11 +17,6 @@ public static void SetResponseCache(this Microsoft.AspNetCore.Http.HttpContext c } } - public static string GetRequestCookieValue(this Microsoft.AspNetCore.Http.HttpContext context, string key) - { - return context.Request.Cookies.ContainsKey(key) ? context.Request.Cookies[key] : null; - } - public static void SetResponseCookie(this Microsoft.AspNetCore.Http.HttpContext context, string key, string value, diff --git a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs index 115ff452c..7c5130f0d 100644 --- a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs +++ b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs @@ -50,14 +50,12 @@ public CompareViewService(IHttpContextAccessor httpContext) public void LoadComparedEmployersFromCookie() { - string value = httpContext.GetRequestCookieValue(CookieNames.LastCompareQuery); - - if (string.IsNullOrWhiteSpace(value)) + if (!httpContext.Request.Cookies.TryGetValue(CookieNames.LastCompareQuery, out string cookieValue)) { - return; + cookieValue = ""; } - string[] employerIds = value.SplitI(","); + string[] employerIds = cookieValue.SplitI(","); ComparedEmployers.Clear(); foreach (string employerId in employerIds) From d26093ce4e312c405329906d7305a5ddb710d5ec Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 13:28:13 +0000 Subject: [PATCH 08/35] EHD-1411: Reduce code in Core project: Move, rename HttpContextHelper and stop using extension methods --- .../Presentation/CompareViewService.cs | 3 +- .../Helpers/HttpContextHelper.cs | 95 +-- GenderPayGap.WebUI/Startup.cs | 667 +++++++++--------- 3 files changed, 383 insertions(+), 382 deletions(-) rename GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs => GenderPayGap.WebUI/Helpers/HttpContextHelper.cs (75%) diff --git a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs index 7c5130f0d..c05feeb9c 100644 --- a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs +++ b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs @@ -83,7 +83,8 @@ public void SaveComparedEmployersToCookieIfAnyAreObfuscated() public void SaveComparedEmployersToCookie() { //Save into the cookie - httpContext.SetResponseCookie( + HttpContextHelper.SetResponseCookie( + httpContext, CookieNames.LastCompareQuery, string.Join(',', ComparedEmployers), VirtualDateTime.Now.AddMonths(1), diff --git a/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs b/GenderPayGap.WebUI/Helpers/HttpContextHelper.cs similarity index 75% rename from GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs rename to GenderPayGap.WebUI/Helpers/HttpContextHelper.cs index 6267ee9bd..6d3fc3d77 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/HttpContext.cs +++ b/GenderPayGap.WebUI/Helpers/HttpContextHelper.cs @@ -1,47 +1,48 @@ -using Microsoft.AspNetCore.Http; - -namespace System.Web -{ - public static class HttpContext - { - - public static void SetResponseCache(this Microsoft.AspNetCore.Http.HttpContext context, int maxSeconds) - { - if (maxSeconds > 0) - { - context.Response.Headers["Cache-Control"] = $"public,max-age={maxSeconds}"; - } - else - { - context.Response.Headers["Cache-Control"] = $"no-cache,no-store,max-age=0,must-revalidate"; - } - } - - public static void SetResponseCookie(this Microsoft.AspNetCore.Http.HttpContext context, - string key, - string value, - DateTime expires, - string subdomain = null, - string path = "/", - bool httpOnly = false, - bool secure = false) - { - var cookieOptions = new CookieOptions { - Expires = expires, - Domain = subdomain, - Path = path, - Secure = secure, - HttpOnly = httpOnly - }; - if (string.IsNullOrWhiteSpace(value)) - { - context.Response.Cookies.Delete(key); - } - else - { - context.Response.Cookies.Append(key, value, cookieOptions); - } - } - - } -} +using System; +using Microsoft.AspNetCore.Http; + +namespace GenderPayGap.WebUI.Helpers +{ + public static class HttpContextHelper + { + + public static void SetResponseCache(HttpContext context, int maxSeconds) + { + if (maxSeconds > 0) + { + context.Response.Headers["Cache-Control"] = $"public,max-age={maxSeconds}"; + } + else + { + context.Response.Headers["Cache-Control"] = $"no-cache,no-store,max-age=0,must-revalidate"; + } + } + + public static void SetResponseCookie(HttpContext context, + string key, + string value, + DateTime expires, + string subdomain = null, + string path = "/", + bool httpOnly = false, + bool secure = false) + { + var cookieOptions = new CookieOptions { + Expires = expires, + Domain = subdomain, + Path = path, + Secure = secure, + HttpOnly = httpOnly + }; + if (string.IsNullOrWhiteSpace(value)) + { + context.Response.Cookies.Delete(key); + } + else + { + context.Response.Cookies.Append(key, value, cookieOptions); + } + } + + } +} diff --git a/GenderPayGap.WebUI/Startup.cs b/GenderPayGap.WebUI/Startup.cs index b077be025..f8a7cd8c3 100644 --- a/GenderPayGap.WebUI/Startup.cs +++ b/GenderPayGap.WebUI/Startup.cs @@ -1,334 +1,333 @@ -using System; -using System.Net.Http; -using System.Web; -using Autofac; -using Autofac.Extensions.DependencyInjection; -using GenderPayGap.Core; -using GenderPayGap.Core.Classes; -using GenderPayGap.Core.Classes.Logger; -using GenderPayGap.Core.Interfaces; -using GenderPayGap.Database; -using GenderPayGap.Extensions.AspNetCore; -using GenderPayGap.WebUI.BackgroundJobs; -using GenderPayGap.WebUI.BackgroundJobs.HangfireConfiguration; -using GenderPayGap.WebUI.BusinessLogic.Abstractions; -using GenderPayGap.WebUI.BusinessLogic.Services; -using GenderPayGap.WebUI.Classes; -using GenderPayGap.WebUI.Classes.Presentation; -using GenderPayGap.WebUI.ErrorHandling; -using GenderPayGap.WebUI.ExternalServices; -using GenderPayGap.WebUI.ExternalServices.CompaniesHouse; -using GenderPayGap.WebUI.ExternalServices.FileRepositories; -using GenderPayGap.WebUI.Helpers; -using GenderPayGap.WebUI.Repositories; -using GenderPayGap.WebUI.Search; -using GenderPayGap.WebUI.Services; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.AspNetCore.Mvc.Routing; -using Microsoft.Extensions.DependencyInjection; - -namespace GenderPayGap.WebUI -{ - public class Startup - { - - public static Action ConfigureTestServices; - public static Action ConfigureTestContainer; - - public static IContainer ContainerIoC; - - // ConfigureServices is where you register dependencies. This gets - // called by the runtime before the ConfigureContainer method, below. - public IServiceProvider ConfigureServices(IServiceCollection services) - { - // Add services to the collection. Don't build or return - // any IServiceProvider or the ConfigureContainer method - // won't get called. - - //Allow handler for caching of http responses - services.AddResponseCaching(); - - //Make sure the application uses the X-Forwarded-Proto header - services.Configure( - options => - { - options.ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor; - }); - - //Add a dedicated httpclient for Google Analytics tracking with exponential retry policy - services.AddHttpClient(nameof(IWebTracker), GoogleAnalyticsTracker.SetupHttpClient) - .SetHandlerLifetime(TimeSpan.FromMinutes(10)) - .AddPolicyHandler(GoogleAnalyticsTracker.GetRetryPolicy()); - - //Add a dedicated httpclient for Companies house API with exponential retry policy - services.AddHttpClient(nameof(ICompaniesHouseAPI), CompaniesHouseAPI.SetupHttpClient) - .SetHandlerLifetime(TimeSpan.FromMinutes(10)) - .AddPolicyHandler(CompaniesHouseAPI.GetRetryPolicy()); - - //Allow creation of a static http context anywhere - services.AddHttpContextAccessor(); - - services.AddControllersWithViews( - options => - { - options.AddStringTrimmingProvider(); //Add modelstate binder to trim input - options.ModelMetadataDetailsProviders.Add( - new TrimModelBinder()); //Set DisplayMetadata to input empty strings as null - options.Filters.Add(); - }) - .AddControllersAsServices() // Add controllers as services so attribute filters be resolved in contructors. - .AddJsonOptions(options => - { - // By default, ASP.Net's JSON serialiser converts property names to camelCase (because javascript typically uses camelCase) - // But, some of our javascript code uses PascalCase (e.g. the homepage auto-complete) - // These options tell ASP.Net to use the original C# property names, without changing the case - options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; - options.JsonSerializerOptions.PropertyNamingPolicy = null; - }); - - IMvcBuilder mvcBuilder = services.AddRazorPages(); - - if (Config.IsLocal()) - { - mvcBuilder.AddRazorRuntimeCompilation(); - } - - //Add antiforgery token by default to forms making sure the Secure flag is always set - services.AddAntiforgery( - options => - { - options.Cookie.SecurePolicy = CookieSecurePolicy.Always; - }); - - //Add services needed for sessions - services.AddSession( - o => - { - o.Cookie.IsEssential = true; //This is required otherwise session will not load - o.Cookie.SecurePolicy = CookieSecurePolicy.Always; //Equivalent to from Web.Config - o.Cookie.HttpOnly = true; //Session cookie should not be accessible by client-side scripts - o.IdleTimeout = TimeSpan.FromDays(30); // This is how long the session DATA is kept, not how long the cookie lasts - }); - - DataProtectionKeysHelper.AddDataProtectionKeyStorage(services); - services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) - .AddCookie(options => - { - options.LoginPath = new PathString("/login"); - options.LogoutPath = new PathString("/logout"); - options.AccessDeniedPath = new PathString("/error/403"); - // ... - }); - - services.AddHostedService(); - - HangfireConfigurationHelper.ConfigureServices(services); - - //Override any test services - ConfigureTestServices?.Invoke(services); - - //Create Inversion of Control container - ContainerIoC = BuildContainerIoC(services); - - // Create the IServiceProvider based on the container. - return new AutofacServiceProvider(ContainerIoC); - } - - // ConfigureContainer is where you can register things directly - // with Autofac. This runs after ConfigureServices so the things - // here will override registrations made in ConfigureServices. - // Don't build the container; that gets done for you. If you - // need a reference to the container, you need to use the - // "Without ConfigureContainer" mechanism shown later. - public IContainer BuildContainerIoC(IServiceCollection services) - { - var builder = new ContainerBuilder(); - - // Note that Populate is basically a foreach to add things - // into Autofac that are in the collection. If you register - // things in Autofac BEFORE Populate then the stuff in the - // ServiceCollection can override those things; if you register - // AFTER Populate those registrations can override things - // in the ServiceCollection. Mix and match as needed. - builder.Populate(services); - - //Register the configuration - builder.RegisterInstance(Config.Configuration).SingleInstance(); - - builder.Register(c => new SqlRepository(new GpgDatabaseContext(Global.DatabaseConnectionString, true))) - .As() - .InstancePerLifetimeScope(); - - builder.RegisterType() - .As() - .SingleInstance() - .WithParameter( - (p, ctx) => p.ParameterType == typeof(HttpClient), - (p, ctx) => ctx.Resolve().CreateClient(nameof(ICompaniesHouseAPI))); - - if (!Config.IsLocal()) - { - builder.Register(c => new AwsFileRepository( - bucketName: Global.S3BucketName, - awsAccessKeyId: Global.S3BucketAwsAccessKeyId, - awsSecretAccessKey: Global.S3BucketAwsSecretAccessKey, - awsRegion: Global.S3BucketAwsRegion - )) - .As() - .SingleInstance(); - } - else - { - string localStorageRoot = @"..\..\..\..\Temp\"; - builder.Register(c => new SystemFileRepository(localStorageRoot)).As().SingleInstance(); - } - - // BL Services - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - - builder.RegisterType().As().InstancePerLifetimeScope(); - - builder.RegisterType().As().InstancePerLifetimeScope(); - - // register web ui services - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - - //Register some singletons - builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - builder.RegisterType().As().InstancePerLifetimeScope(); - - - // Register Action helpers - builder.RegisterType().As().SingleInstance(); - builder.Register( - x => - { - ActionContext actionContext = x.Resolve().ActionContext; - var factory = x.Resolve(); - return factory.GetUrlHelper(actionContext); - }); - - //Register WebTracker - builder.RegisterType() - .As() - .SingleInstance() - .WithParameter( - (p, ctx) => p.ParameterType == typeof(HttpClient), - (p, ctx) => ctx.Resolve().CreateClient(nameof(IWebTracker))) - .WithParameter("trackingId", Global.GoogleAnalyticsAccountId); - - //TOD: Implement AutoFac modules - //builder.RegisterModule(new AutofacModule()); - - //Override any test services - ConfigureTestContainer?.Invoke(builder); - - IContainer container = builder.Build(); - - HangfireConfigurationHelper.ConfigureIOC(container); - - return container; - } - - // Configure is where you add middleware. This is called after - // ConfigureContainer. You can use IApplicationBuilder.ApplicationServices - // here if you need to resolve things from the container. - public void Configure(IApplicationBuilder app, IApplicationLifetime lifetime) - { - app.UseForwardedHeaders(); - if (Config.IsLocal()) - { - app.UseBrowserLink(); - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/error/500"); - app.UseStatusCodePagesWithReExecute("/error/{0}"); - } - - //app.UseHttpsRedirection(); - //app.UseResponseCompression(); //Disabled to use IIS compression which has better performance (see https://docs.microsoft.com/en-us/aspnet/core/performance/response-compression?view=aspnetcore-2.1) - app.UseStaticFiles( - new StaticFileOptions - { - OnPrepareResponse = ctx => - { - //Caching static files is required to reduce connections since the default behavior of checking if a static file has changed and returning a 304 still requires a connection. - if (Global.StaticCacheSeconds > 0) - { - ctx.Context.SetResponseCache(Global.StaticCacheSeconds); - } - } - }); //For the wwwroot folder - - app.UseRouting(); - app.UseResponseCaching(); - app.UseResponseBuffering(); //required otherwise JsonResult uses chunking and adds extra characters - app.UseSession(); //Must be before UseMvC or any middleware which requires session - app.UseAuthentication(); //Ensure the OIDC IDentity Server authentication services execute on each http request - Must be before UseMVC - app.UseAuthorization(); - - var cookiePolicyOptions = new CookiePolicyOptions - { - MinimumSameSitePolicy = SameSiteMode.Lax, - }; - app.UseCookiePolicy(cookiePolicyOptions); - app.UseMiddleware(Global.MaintenanceMode); //Redirect to maintenance page when Maintenance mode settings = true - app.UseMiddleware(); //Add/remove security headers from all responses - - if (!string.IsNullOrWhiteSpace(Global.BasicAuthUsername) - && !string.IsNullOrWhiteSpace(Global.BasicAuthPassword)) - { - // Add HTTP Basic Authentication in our non-production environments to make sure people don't accidentally stumble across the site - // The site will still also be secured by the usual login/cookie auth - this is just an extra layer to make the site not publicly accessible - app.UseMiddleware(); - } - - // Prevent caching of html responses as they may contain secure info - GPG-581 - app.UseMiddleware(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - - HangfireConfigurationHelper.ConfigureApp(app); - - lifetime.ApplicationStarted.Register( - () => - { - // Summary: - // Triggered when the application host has fully started and is about to wait for - // a graceful shutdown. - CustomLogger.Information("Application Started"); - }); - lifetime.ApplicationStopping.Register( - () => - { - // Summary: - // Triggered when the application host is performing a graceful shutdown. Requests - // may still be in flight. Shutdown will block until this event completes. - CustomLogger.Information("Application Stopping"); - }); - } - - } -} +using System; +using System.Net.Http; +using Autofac; +using Autofac.Extensions.DependencyInjection; +using GenderPayGap.Core; +using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Classes.Logger; +using GenderPayGap.Core.Interfaces; +using GenderPayGap.Database; +using GenderPayGap.Extensions.AspNetCore; +using GenderPayGap.WebUI.BackgroundJobs; +using GenderPayGap.WebUI.BackgroundJobs.HangfireConfiguration; +using GenderPayGap.WebUI.BusinessLogic.Abstractions; +using GenderPayGap.WebUI.BusinessLogic.Services; +using GenderPayGap.WebUI.Classes; +using GenderPayGap.WebUI.Classes.Presentation; +using GenderPayGap.WebUI.ErrorHandling; +using GenderPayGap.WebUI.ExternalServices; +using GenderPayGap.WebUI.ExternalServices.CompaniesHouse; +using GenderPayGap.WebUI.ExternalServices.FileRepositories; +using GenderPayGap.WebUI.Helpers; +using GenderPayGap.WebUI.Repositories; +using GenderPayGap.WebUI.Search; +using GenderPayGap.WebUI.Services; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.HttpOverrides; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace GenderPayGap.WebUI +{ + public class Startup + { + + public static Action ConfigureTestServices; + public static Action ConfigureTestContainer; + + public static IContainer ContainerIoC; + + // ConfigureServices is where you register dependencies. This gets + // called by the runtime before the ConfigureContainer method, below. + public IServiceProvider ConfigureServices(IServiceCollection services) + { + // Add services to the collection. Don't build or return + // any IServiceProvider or the ConfigureContainer method + // won't get called. + + //Allow handler for caching of http responses + services.AddResponseCaching(); + + //Make sure the application uses the X-Forwarded-Proto header + services.Configure( + options => + { + options.ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor; + }); + + //Add a dedicated httpclient for Google Analytics tracking with exponential retry policy + services.AddHttpClient(nameof(IWebTracker), GoogleAnalyticsTracker.SetupHttpClient) + .SetHandlerLifetime(TimeSpan.FromMinutes(10)) + .AddPolicyHandler(GoogleAnalyticsTracker.GetRetryPolicy()); + + //Add a dedicated httpclient for Companies house API with exponential retry policy + services.AddHttpClient(nameof(ICompaniesHouseAPI), CompaniesHouseAPI.SetupHttpClient) + .SetHandlerLifetime(TimeSpan.FromMinutes(10)) + .AddPolicyHandler(CompaniesHouseAPI.GetRetryPolicy()); + + //Allow creation of a static http context anywhere + services.AddHttpContextAccessor(); + + services.AddControllersWithViews( + options => + { + options.AddStringTrimmingProvider(); //Add modelstate binder to trim input + options.ModelMetadataDetailsProviders.Add( + new TrimModelBinder()); //Set DisplayMetadata to input empty strings as null + options.Filters.Add(); + }) + .AddControllersAsServices() // Add controllers as services so attribute filters be resolved in contructors. + .AddJsonOptions(options => + { + // By default, ASP.Net's JSON serialiser converts property names to camelCase (because javascript typically uses camelCase) + // But, some of our javascript code uses PascalCase (e.g. the homepage auto-complete) + // These options tell ASP.Net to use the original C# property names, without changing the case + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + options.JsonSerializerOptions.PropertyNamingPolicy = null; + }); + + IMvcBuilder mvcBuilder = services.AddRazorPages(); + + if (Config.IsLocal()) + { + mvcBuilder.AddRazorRuntimeCompilation(); + } + + //Add antiforgery token by default to forms making sure the Secure flag is always set + services.AddAntiforgery( + options => + { + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; + }); + + //Add services needed for sessions + services.AddSession( + o => + { + o.Cookie.IsEssential = true; //This is required otherwise session will not load + o.Cookie.SecurePolicy = CookieSecurePolicy.Always; //Equivalent to from Web.Config + o.Cookie.HttpOnly = true; //Session cookie should not be accessible by client-side scripts + o.IdleTimeout = TimeSpan.FromDays(30); // This is how long the session DATA is kept, not how long the cookie lasts + }); + + DataProtectionKeysHelper.AddDataProtectionKeyStorage(services); + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => + { + options.LoginPath = new PathString("/login"); + options.LogoutPath = new PathString("/logout"); + options.AccessDeniedPath = new PathString("/error/403"); + // ... + }); + + services.AddHostedService(); + + HangfireConfigurationHelper.ConfigureServices(services); + + //Override any test services + ConfigureTestServices?.Invoke(services); + + //Create Inversion of Control container + ContainerIoC = BuildContainerIoC(services); + + // Create the IServiceProvider based on the container. + return new AutofacServiceProvider(ContainerIoC); + } + + // ConfigureContainer is where you can register things directly + // with Autofac. This runs after ConfigureServices so the things + // here will override registrations made in ConfigureServices. + // Don't build the container; that gets done for you. If you + // need a reference to the container, you need to use the + // "Without ConfigureContainer" mechanism shown later. + public IContainer BuildContainerIoC(IServiceCollection services) + { + var builder = new ContainerBuilder(); + + // Note that Populate is basically a foreach to add things + // into Autofac that are in the collection. If you register + // things in Autofac BEFORE Populate then the stuff in the + // ServiceCollection can override those things; if you register + // AFTER Populate those registrations can override things + // in the ServiceCollection. Mix and match as needed. + builder.Populate(services); + + //Register the configuration + builder.RegisterInstance(Config.Configuration).SingleInstance(); + + builder.Register(c => new SqlRepository(new GpgDatabaseContext(Global.DatabaseConnectionString, true))) + .As() + .InstancePerLifetimeScope(); + + builder.RegisterType() + .As() + .SingleInstance() + .WithParameter( + (p, ctx) => p.ParameterType == typeof(HttpClient), + (p, ctx) => ctx.Resolve().CreateClient(nameof(ICompaniesHouseAPI))); + + if (!Config.IsLocal()) + { + builder.Register(c => new AwsFileRepository( + bucketName: Global.S3BucketName, + awsAccessKeyId: Global.S3BucketAwsAccessKeyId, + awsSecretAccessKey: Global.S3BucketAwsSecretAccessKey, + awsRegion: Global.S3BucketAwsRegion + )) + .As() + .SingleInstance(); + } + else + { + string localStorageRoot = @"..\..\..\..\Temp\"; + builder.Register(c => new SystemFileRepository(localStorageRoot)).As().SingleInstance(); + } + + // BL Services + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As().InstancePerLifetimeScope(); + + builder.RegisterType().As().InstancePerLifetimeScope(); + + // register web ui services + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + + //Register some singletons + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + builder.RegisterType().As().InstancePerLifetimeScope(); + + + // Register Action helpers + builder.RegisterType().As().SingleInstance(); + builder.Register( + x => + { + ActionContext actionContext = x.Resolve().ActionContext; + var factory = x.Resolve(); + return factory.GetUrlHelper(actionContext); + }); + + //Register WebTracker + builder.RegisterType() + .As() + .SingleInstance() + .WithParameter( + (p, ctx) => p.ParameterType == typeof(HttpClient), + (p, ctx) => ctx.Resolve().CreateClient(nameof(IWebTracker))) + .WithParameter("trackingId", Global.GoogleAnalyticsAccountId); + + //TOD: Implement AutoFac modules + //builder.RegisterModule(new AutofacModule()); + + //Override any test services + ConfigureTestContainer?.Invoke(builder); + + IContainer container = builder.Build(); + + HangfireConfigurationHelper.ConfigureIOC(container); + + return container; + } + + // Configure is where you add middleware. This is called after + // ConfigureContainer. You can use IApplicationBuilder.ApplicationServices + // here if you need to resolve things from the container. + public void Configure(IApplicationBuilder app, IApplicationLifetime lifetime) + { + app.UseForwardedHeaders(); + if (Config.IsLocal()) + { + app.UseBrowserLink(); + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/error/500"); + app.UseStatusCodePagesWithReExecute("/error/{0}"); + } + + //app.UseHttpsRedirection(); + //app.UseResponseCompression(); //Disabled to use IIS compression which has better performance (see https://docs.microsoft.com/en-us/aspnet/core/performance/response-compression?view=aspnetcore-2.1) + app.UseStaticFiles( + new StaticFileOptions + { + OnPrepareResponse = ctx => + { + //Caching static files is required to reduce connections since the default behavior of checking if a static file has changed and returning a 304 still requires a connection. + if (Global.StaticCacheSeconds > 0) + { + HttpContextHelper.SetResponseCache(ctx.Context, Global.StaticCacheSeconds); + } + } + }); //For the wwwroot folder + + app.UseRouting(); + app.UseResponseCaching(); + app.UseResponseBuffering(); //required otherwise JsonResult uses chunking and adds extra characters + app.UseSession(); //Must be before UseMvC or any middleware which requires session + app.UseAuthentication(); //Ensure the OIDC IDentity Server authentication services execute on each http request - Must be before UseMVC + app.UseAuthorization(); + + var cookiePolicyOptions = new CookiePolicyOptions + { + MinimumSameSitePolicy = SameSiteMode.Lax, + }; + app.UseCookiePolicy(cookiePolicyOptions); + app.UseMiddleware(Global.MaintenanceMode); //Redirect to maintenance page when Maintenance mode settings = true + app.UseMiddleware(); //Add/remove security headers from all responses + + if (!string.IsNullOrWhiteSpace(Global.BasicAuthUsername) + && !string.IsNullOrWhiteSpace(Global.BasicAuthPassword)) + { + // Add HTTP Basic Authentication in our non-production environments to make sure people don't accidentally stumble across the site + // The site will still also be secured by the usual login/cookie auth - this is just an extra layer to make the site not publicly accessible + app.UseMiddleware(); + } + + // Prevent caching of html responses as they may contain secure info - GPG-581 + app.UseMiddleware(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + + HangfireConfigurationHelper.ConfigureApp(app); + + lifetime.ApplicationStarted.Register( + () => + { + // Summary: + // Triggered when the application host has fully started and is about to wait for + // a graceful shutdown. + CustomLogger.Information("Application Started"); + }); + lifetime.ApplicationStopping.Register( + () => + { + // Summary: + // Triggered when the application host is performing a graceful shutdown. Requests + // may still be in flight. Shutdown will block until this event completes. + CustomLogger.Information("Application Stopping"); + }); + } + + } +} From bf99599ce9eda9d6fc774017864c257056270ae1 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 13:45:18 +0000 Subject: [PATCH 09/35] EHD-1411: Reduce code in Core project: Inline Extensions.SetResponseHeader code --- .../Extensions/AspNetCore/Extensions.cs | 43 +------------------ .../AspNetCore/SecurityHeaderMiddleware.cs | 17 +++++++- GenderPayGap.Core/Global.cs | 15 ++++--- 3 files changed, 26 insertions(+), 49 deletions(-) diff --git a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs b/GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs index 5c6e8b3c8..8ee570ea7 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs @@ -1,52 +1,11 @@ -using System; using System.Threading; using GenderPayGap.Core; -using Microsoft.AspNetCore.Http; namespace GenderPayGap.Extensions.AspNetCore { - public static partial class Extensions + public static class Extensions { - /// - /// Removes null header or ensures header is set to correct value - /// /// - /// - /// The HttpContext to remove the header from - /// The key of the header name - /// The value which the header should be - if empty removed the header - public static void SetResponseHeader(this HttpContext context, string key, string value = null) - { - try - { - if (string.IsNullOrWhiteSpace(value)) - { - if (context.Response.Headers.ContainsKey(key)) - { - context.Response.Headers.Remove(key); - } - } - else if (!context.Response.Headers.ContainsKey(key)) - { - context.Response.Headers.Add(key, value); - } - else if (context.Response.Headers[key] != value) - { - context.Response.Headers.Remove(key); //This is required as cannot change a key once added - context.Response.Headers[key] = value; - } - } - catch (Exception ex) - { - if (context.Response.Headers.ContainsKey(key)) - { - throw new Exception($"Could not set header '{key}' from value '{context.Response.Headers[key]}' to '{value}' ", ex); - } - - throw new Exception($"Could not add header '{key}' to value '{value}' ", ex); - } - } - public static string GetThreadCount() { ThreadPool.GetMinThreads(out int workerMin, out int ioMin); diff --git a/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs b/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs index fc569977b..e18cb4f29 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs @@ -19,9 +19,22 @@ public async Task Invoke(HttpContext httpContext) { httpContext.Response.OnStarting( () => { - foreach (KeyValuePair securityHeader in Global.SecurityHeaders) + foreach (KeyValuePair securityHeader in Global.SecurityHeadersToAdd) { - httpContext.SetResponseHeader(securityHeader.Key, securityHeader.Value); + if (!httpContext.Response.Headers.ContainsKey(securityHeader.Key)) + { + httpContext.Response.Headers.Add(securityHeader.Key, securityHeader.Value); + } + else if (httpContext.Response.Headers[securityHeader.Key] != securityHeader.Value) + { + httpContext.Response.Headers.Remove(securityHeader.Key); // This is required as we cannot change a key once it is added + httpContext.Response.Headers[securityHeader.Key] = securityHeader.Value; + } + } + + foreach (string securityHeaderName in Global.SecurityHeadersToRemove) + { + httpContext.Response.Headers.Remove(securityHeaderName); } return Task.CompletedTask; diff --git a/GenderPayGap.Core/Global.cs b/GenderPayGap.Core/Global.cs index 50a66f989..889279b77 100644 --- a/GenderPayGap.Core/Global.cs +++ b/GenderPayGap.Core/Global.cs @@ -110,7 +110,7 @@ public static bool EnableSubmitAlerts public static int MaxCompareBasketCount => 500; // Maximum number of employers you can add to the compare basket public static int EditableReportCount => 4; // Specifies how many reports an employer can edit public static int EditableScopeCount => 2; // Specifies how many scopes an employer can edit - public static Dictionary SecurityHeaders => + public static Dictionary SecurityHeadersToAdd => new Dictionary { {"X-Content-Type-Options", "nosniff"}, @@ -121,11 +121,16 @@ public static bool EnableSubmitAlerts {"X-Content-Security-Policy", "frame-ancestors 'none'"}, {"Referrer-Policy", "origin-when-cross-origin"}, {"Strict-Transport-Security", "max-age=31536000; includeSubDomains"}, - {"X-Powered-By", ""}, - {"X-AspNet-Version", ""}, - {"X-AspNetMvc-Version", ""}, - {"Server", ""} }; + public static List SecurityHeadersToRemove => + new List + { + "X-Powered-By", + "X-AspNet-Version", + "X-AspNetMvc-Version", + "Server" + }; + public static int ObfuscationSeed => 1045659205; #endregion From 8d4206e5e97b47e9082e70951c4bda472778e797 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 13:57:19 +0000 Subject: [PATCH 10/35] EHD-1411: Reduce code in Core project: Move middlewares --- .../Helpers}/MaintenancePageMiddleware.cs | 77 +++++++-------- .../Helpers}/SecurityHeaderMiddleware.cs | 94 +++++++++---------- 2 files changed, 86 insertions(+), 85 deletions(-) rename {GenderPayGap.Core/Extensions/AspNetCore => GenderPayGap.WebUI/Helpers}/MaintenancePageMiddleware.cs (92%) rename {GenderPayGap.Core/Extensions/AspNetCore => GenderPayGap.WebUI/Helpers}/SecurityHeaderMiddleware.cs (94%) diff --git a/GenderPayGap.Core/Extensions/AspNetCore/MaintenancePageMiddleware.cs b/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs similarity index 92% rename from GenderPayGap.Core/Extensions/AspNetCore/MaintenancePageMiddleware.cs rename to GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs index befc53b4d..42292d022 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/MaintenancePageMiddleware.cs +++ b/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs @@ -1,38 +1,39 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using HttpContext = Microsoft.AspNetCore.Http.HttpContext; - -namespace GenderPayGap.Extensions.AspNetCore -{ - public class MaintenancePageMiddleware - { - - private readonly bool _enabled; - private readonly RequestDelegate _next; - - public MaintenancePageMiddleware(RequestDelegate next, bool enabled) - { - _next = next; - _enabled = enabled; - } - - - public async Task Invoke(HttpContext httpContext) - { - if (httpContext.Request.Path.Value.StartsWith("/health-check")) - { - await _next.Invoke(httpContext); - return; - } - - // Redirect to holding page if in maintenance mode - if (_enabled && !httpContext.Request.Path.Value.StartsWithI(@"/error/service-unavailable")) - { - httpContext.Response.Redirect(@"/error/service-unavailable", permanent: false); - } - - await _next.Invoke(httpContext); - } - - } -} +using System.Threading.Tasks; +using GenderPayGap.Extensions; +using Microsoft.AspNetCore.Http; +using HttpContext = Microsoft.AspNetCore.Http.HttpContext; + +namespace GenderPayGap.WebUI.Helpers +{ + public class MaintenancePageMiddleware + { + + private readonly bool _enabled; + private readonly RequestDelegate _next; + + public MaintenancePageMiddleware(RequestDelegate next, bool enabled) + { + _next = next; + _enabled = enabled; + } + + + public async Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.Value.StartsWith("/health-check")) + { + await _next.Invoke(httpContext); + return; + } + + // Redirect to holding page if in maintenance mode + if (_enabled && !httpContext.Request.Path.Value.StartsWithI(@"/error/service-unavailable")) + { + httpContext.Response.Redirect(@"/error/service-unavailable", permanent: false); + } + + await _next.Invoke(httpContext); + } + + } +} diff --git a/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs b/GenderPayGap.WebUI/Helpers/SecurityHeaderMiddleware.cs similarity index 94% rename from GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs rename to GenderPayGap.WebUI/Helpers/SecurityHeaderMiddleware.cs index e18cb4f29..efb84a868 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/SecurityHeaderMiddleware.cs +++ b/GenderPayGap.WebUI/Helpers/SecurityHeaderMiddleware.cs @@ -1,47 +1,47 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using GenderPayGap.Core; -using Microsoft.AspNetCore.Http; - -namespace GenderPayGap.Extensions.AspNetCore -{ - public class SecurityHeaderMiddleware - { - - private readonly RequestDelegate _next; - - public SecurityHeaderMiddleware(RequestDelegate next) - { - _next = next; - } - - public async Task Invoke(HttpContext httpContext) - { - httpContext.Response.OnStarting( - () => { - foreach (KeyValuePair securityHeader in Global.SecurityHeadersToAdd) - { - if (!httpContext.Response.Headers.ContainsKey(securityHeader.Key)) - { - httpContext.Response.Headers.Add(securityHeader.Key, securityHeader.Value); - } - else if (httpContext.Response.Headers[securityHeader.Key] != securityHeader.Value) - { - httpContext.Response.Headers.Remove(securityHeader.Key); // This is required as we cannot change a key once it is added - httpContext.Response.Headers[securityHeader.Key] = securityHeader.Value; - } - } - - foreach (string securityHeaderName in Global.SecurityHeadersToRemove) - { - httpContext.Response.Headers.Remove(securityHeaderName); - } - - return Task.CompletedTask; - }); - - await _next.Invoke(httpContext); - } - - } -} +using System.Collections.Generic; +using System.Threading.Tasks; +using GenderPayGap.Core; +using Microsoft.AspNetCore.Http; + +namespace GenderPayGap.WebUI.Helpers +{ + public class SecurityHeaderMiddleware + { + + private readonly RequestDelegate _next; + + public SecurityHeaderMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task Invoke(HttpContext httpContext) + { + httpContext.Response.OnStarting( + () => { + foreach (KeyValuePair securityHeader in Global.SecurityHeadersToAdd) + { + if (!httpContext.Response.Headers.ContainsKey(securityHeader.Key)) + { + httpContext.Response.Headers.Add(securityHeader.Key, securityHeader.Value); + } + else if (httpContext.Response.Headers[securityHeader.Key] != securityHeader.Value) + { + httpContext.Response.Headers.Remove(securityHeader.Key); // This is required as we cannot change a key once it is added + httpContext.Response.Headers[securityHeader.Key] = securityHeader.Value; + } + } + + foreach (string securityHeaderName in Global.SecurityHeadersToRemove) + { + httpContext.Response.Headers.Remove(securityHeaderName); + } + + return Task.CompletedTask; + }); + + await _next.Invoke(httpContext); + } + + } +} From 4abb9d6e77d6cf98943a1db843b1a9f393a48d07 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:08:19 +0000 Subject: [PATCH 11/35] EHD-1411: Reduce code in Core project: Move Basic Auth helper --- .../BasicAuthenticationHeaderValue.cs | 15 -------------- .../Admin/AdminDataMigrationController.cs | 2 +- .../CompaniesHouse/CompaniesHouseAPI.cs | 3 ++- .../Helpers/AuthenticationHeaderHelper.cs | 20 +++++++++++++++++++ 4 files changed, 23 insertions(+), 17 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/AspNetCore/BasicAuthenticationHeaderValue.cs create mode 100644 GenderPayGap.WebUI/Helpers/AuthenticationHeaderHelper.cs diff --git a/GenderPayGap.Core/Extensions/AspNetCore/BasicAuthenticationHeaderValue.cs b/GenderPayGap.Core/Extensions/AspNetCore/BasicAuthenticationHeaderValue.cs deleted file mode 100644 index 240ee0eba..000000000 --- a/GenderPayGap.Core/Extensions/AspNetCore/BasicAuthenticationHeaderValue.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Net.Http.Headers; -using System.Text; - -namespace GenderPayGap.Extensions.AspNetCore -{ - public class BasicAuthenticationHeaderValue : AuthenticationHeaderValue - { - - public BasicAuthenticationHeaderValue(string username, string password) : base( - "Basic", - Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"))) { } - - } -} diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs index 6eca7b9b4..de7725fcd 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs @@ -153,7 +153,7 @@ public IActionResult ImportAllDataFromRemoteServer(AdminDataMigrationViewModel v var httpClient = new HttpClient(); if (!string.IsNullOrWhiteSpace(viewModel.BasicAuthUsername) && !string.IsNullOrWhiteSpace(viewModel.BasicAuthPassword)) { - httpClient.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(viewModel.BasicAuthUsername, viewModel.BasicAuthPassword); + httpClient.DefaultRequestHeaders.Authorization = AuthenticationHeaderHelper.GetBasicAuthenticationHeaderValue(viewModel.BasicAuthUsername, viewModel.BasicAuthPassword); } string requestUrl = $"https://{viewModel.Hostname}/admin/data-migration/export-all?password={viewModel.Password}"; string responseString = httpClient.GetStringAsync(requestUrl).Result; diff --git a/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs b/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs index b5b1529b6..edf9fd5cb 100644 --- a/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs +++ b/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs @@ -5,6 +5,7 @@ using GenderPayGap.Core; using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; +using GenderPayGap.WebUI.Helpers; using Newtonsoft.Json; using Polly; using Polly.Extensions.Http; @@ -92,7 +93,7 @@ public static void SetupHttpClient(HttpClient httpClient) httpClient.BaseAddress = BaseUri; httpClient.DefaultRequestHeaders.Clear(); - httpClient.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(ApiKey, ""); + httpClient.DefaultRequestHeaders.Authorization = AuthenticationHeaderHelper.GetBasicAuthenticationHeaderValue(ApiKey, ""); httpClient.DefaultRequestHeaders.ConnectionClose = false; ServicePointManager.FindServicePoint(httpClient.BaseAddress).ConnectionLeaseTimeout = 60 * 1000; } diff --git a/GenderPayGap.WebUI/Helpers/AuthenticationHeaderHelper.cs b/GenderPayGap.WebUI/Helpers/AuthenticationHeaderHelper.cs new file mode 100644 index 000000000..6e32f53c4 --- /dev/null +++ b/GenderPayGap.WebUI/Helpers/AuthenticationHeaderHelper.cs @@ -0,0 +1,20 @@ +using System; +using System.Net.Http.Headers; +using System.Text; + +namespace GenderPayGap.WebUI.Helpers +{ + public static class AuthenticationHeaderHelper + { + + public static AuthenticationHeaderValue GetBasicAuthenticationHeaderValue(string username, string password) + { + string base64UsernameAndPassword = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}")); + + return new AuthenticationHeaderValue( + "Basic", + base64UsernameAndPassword); + } + + } +} From c73ac0bc3d0c925b5d1e9691805ee8604c21414c Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:11:07 +0000 Subject: [PATCH 12/35] EHD-1411: Reduce code in Core project: Move ThreadCountHelper --- .../Helpers/ThreadCountHelper.cs | 4 ++-- GenderPayGap.WebUI/Program.cs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) rename GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs => GenderPayGap.WebUI/Helpers/ThreadCountHelper.cs (88%) diff --git a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs b/GenderPayGap.WebUI/Helpers/ThreadCountHelper.cs similarity index 88% rename from GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs rename to GenderPayGap.WebUI/Helpers/ThreadCountHelper.cs index 8ee570ea7..1d5258c8f 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/Extensions.cs +++ b/GenderPayGap.WebUI/Helpers/ThreadCountHelper.cs @@ -1,9 +1,9 @@ using System.Threading; using GenderPayGap.Core; -namespace GenderPayGap.Extensions.AspNetCore +namespace GenderPayGap.WebUI.Helpers { - public static class Extensions + public static class ThreadCountHelper { public static string GetThreadCount() diff --git a/GenderPayGap.WebUI/Program.cs b/GenderPayGap.WebUI/Program.cs index 3f73d0e54..fff9174fd 100644 --- a/GenderPayGap.WebUI/Program.cs +++ b/GenderPayGap.WebUI/Program.cs @@ -6,6 +6,7 @@ using GenderPayGap.Core; using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; +using GenderPayGap.WebUI.Helpers; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -31,10 +32,10 @@ public static void Main(string[] args) IWebHost host = BuildWebHost(args); // Set the minumum threads - Console.WriteLine(Extensions.AspNetCore.Extensions.SetThreadCount()); + Console.WriteLine(ThreadCountHelper.SetThreadCount()); // Show thread availability - Console.WriteLine(Extensions.AspNetCore.Extensions.GetThreadCount()); + Console.WriteLine(ThreadCountHelper.GetThreadCount()); // Run the webhost host.Run(); @@ -48,7 +49,7 @@ private static void CurrentDomain_UnhandledException(object sender, UnhandledExc Debug.WriteLine($"UNHANDLED EXCEPTION ({Console.Title}): {ex.Message}{Environment.NewLine}{ex.GetDetailsText()}"); //Show thread availability - Console.WriteLine(Extensions.AspNetCore.Extensions.GetThreadCount()); + Console.WriteLine(ThreadCountHelper.GetThreadCount()); throw ex; } From 7b98d636c0633cd45a067fafc61d5350c70e04c8 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:19:12 +0000 Subject: [PATCH 13/35] EHD-1411: Reduce code in Core project: Move FeatureFlagHelper --- GenderPayGap.WebUI/Helpers/ControllerHelper.cs | 1 - .../Helpers/FeatureFlagHelper.cs | 2 +- GenderPayGap.WebUI/Repositories/RegistrationRepository.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) rename {GenderPayGap.Core => GenderPayGap.WebUI}/Helpers/FeatureFlagHelper.cs (95%) diff --git a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs index 43d732bc2..d06047145 100644 --- a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs +++ b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Security.Claims; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; diff --git a/GenderPayGap.Core/Helpers/FeatureFlagHelper.cs b/GenderPayGap.WebUI/Helpers/FeatureFlagHelper.cs similarity index 95% rename from GenderPayGap.Core/Helpers/FeatureFlagHelper.cs rename to GenderPayGap.WebUI/Helpers/FeatureFlagHelper.cs index da4adf71f..b628884ce 100644 --- a/GenderPayGap.Core/Helpers/FeatureFlagHelper.cs +++ b/GenderPayGap.WebUI/Helpers/FeatureFlagHelper.cs @@ -1,7 +1,7 @@ using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; -namespace GenderPayGap.Core.Helpers +namespace GenderPayGap.WebUI.Helpers { public static class FeatureFlagHelper { diff --git a/GenderPayGap.WebUI/Repositories/RegistrationRepository.cs b/GenderPayGap.WebUI/Repositories/RegistrationRepository.cs index 79b3e404a..fd51dacac 100644 --- a/GenderPayGap.WebUI/Repositories/RegistrationRepository.cs +++ b/GenderPayGap.WebUI/Repositories/RegistrationRepository.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Services; using Microsoft.AspNetCore.Mvc; From ce9ba898fef9ebdf377194ced7dbe5f27067a1a0 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:22:28 +0000 Subject: [PATCH 14/35] EHD-1411: Reduce code in Core project: Move ChangeEmailVerificationToken --- .../Controllers/Account/ChangeEmailTests.cs | 3 --- .../Controllers/Account/ChangeEmailController.cs | 2 -- .../Models/Account}/ChangeEmailVerificationToken.cs | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) rename {GenderPayGap.Core/Models/AccountModels => GenderPayGap.WebUI/Models/Account}/ChangeEmailVerificationToken.cs (79%) diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs index 60ec215d7..7f06ac8fa 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Models; using GenderPayGap.Database; using GenderPayGap.Database.Models; using GenderPayGap.Extensions; @@ -10,7 +8,6 @@ using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; -using Microsoft.Extensions.Primitives; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.Account diff --git a/GenderPayGap.WebUI/Controllers/Account/ChangeEmailController.cs b/GenderPayGap.WebUI/Controllers/Account/ChangeEmailController.cs index 84ff96403..995bf00d1 100644 --- a/GenderPayGap.WebUI/Controllers/Account/ChangeEmailController.cs +++ b/GenderPayGap.WebUI/Controllers/Account/ChangeEmailController.cs @@ -1,14 +1,12 @@ using System; using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; -using GenderPayGap.Core.Models; using GenderPayGap.Database; using GenderPayGap.Extensions; using GenderPayGap.WebUI.BusinessLogic.Abstractions; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; -using GovUkDesignSystem; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/GenderPayGap.Core/Models/AccountModels/ChangeEmailVerificationToken.cs b/GenderPayGap.WebUI/Models/Account/ChangeEmailVerificationToken.cs similarity index 79% rename from GenderPayGap.Core/Models/AccountModels/ChangeEmailVerificationToken.cs rename to GenderPayGap.WebUI/Models/Account/ChangeEmailVerificationToken.cs index 7b3d82e50..86a753bb6 100644 --- a/GenderPayGap.Core/Models/AccountModels/ChangeEmailVerificationToken.cs +++ b/GenderPayGap.WebUI/Models/Account/ChangeEmailVerificationToken.cs @@ -1,6 +1,6 @@ using System; -namespace GenderPayGap.Core.Models +namespace GenderPayGap.WebUI.Models.Account { public class ChangeEmailVerificationToken From 6aa19f1da58fa0ad567ab3d63843b17ee495f88d Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:30:54 +0000 Subject: [PATCH 15/35] EHD-1411: Reduce code in Core project: Move DownloadResult --- .../Models/Extensions/Return.cs | 36 +-------- .../UpdatePublicFacingDownloadFilesJob.cs | 39 +++++++++- .../Models/Download}/DownloadResult.cs | 74 +++++++++---------- 3 files changed, 75 insertions(+), 74 deletions(-) rename {GenderPayGap.Core/Models => GenderPayGap.WebUI/Models/Download}/DownloadResult.cs (94%) diff --git a/GenderPayGap.Database/Models/Extensions/Return.cs b/GenderPayGap.Database/Models/Extensions/Return.cs index a583b412e..3ed567747 100644 --- a/GenderPayGap.Database/Models/Extensions/Return.cs +++ b/GenderPayGap.Database/Models/Extensions/Return.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations.Schema; using GenderPayGap.Core; using GenderPayGap.Core.Helpers; -using GenderPayGap.Core.Models; using GenderPayGap.Extensions; namespace GenderPayGap.Database @@ -243,39 +242,6 @@ public bool Equals(Return model) return true; } - public DownloadResult ToDownloadResult() - { - return new DownloadResult { - EmployerName = Organisation?.GetName(StatusDate)?.Name ?? Organisation.OrganisationName, - EmployerId = OrganisationId, - Address = Organisation.GetLatestAddress()?.GetAddressString(), - PostCode = Organisation.GetLatestAddress()?.GetPostCodeInAllCaps(), - CompanyNumber = Organisation?.CompanyNumber, - SicCodes = Organisation?.GetSicCodeIdsString(StatusDate, "," + Environment.NewLine), - DiffMeanHourlyPercent = DiffMeanHourlyPayPercent, - DiffMedianHourlyPercent = DiffMedianHourlyPercent, - DiffMeanBonusPercent = DiffMeanBonusPercent, - DiffMedianBonusPercent = DiffMedianBonusPercent, - MaleBonusPercent = MaleMedianBonusPayPercent, - FemaleBonusPercent = FemaleMedianBonusPayPercent, - MaleLowerQuartile = MaleLowerPayBand, - FemaleLowerQuartile = FemaleLowerPayBand, - MaleLowerMiddleQuartile = MaleMiddlePayBand, - FemaleLowerMiddleQuartile = FemaleMiddlePayBand, - MaleUpperMiddleQuartile = MaleUpperPayBand, - FemaleUpperMiddleQuartile = FemaleUpperPayBand, - MaleTopQuartile = MaleUpperQuartilePayBand, - FemaleTopQuartile = FemaleUpperQuartilePayBand, - CompanyLinkToGPGInfo = CompanyLinkToGPGInfo, - ResponsiblePerson = ResponsiblePerson, - EmployerSize = OrganisationSize.GetAttribute().Name, - CurrentName = Organisation?.OrganisationName, - SubmittedAfterTheDeadline = IsLateSubmission, - DueDate = GetDueDate(), - DateSubmitted = Modified - }; - } - public string GetReportingPeriod() { return ReportingYearsHelper.FormatYearAsReportingPeriod(AccountingDate.Year, "/"); @@ -284,7 +250,7 @@ public string GetReportingPeriod() // The deadline date is the final day that a return can be submitted without being considered late // The due date is a day later, the point at which a return is considered late // i.e. if the deadline date is 2021/04/01, submissions on that day are not late, any after 2021/04/02 00:00:00 are - private DateTime GetDueDate() + public DateTime GetDueDate() { return ReportingYearsHelper.GetDeadlineForAccountingDate(AccountingDate).AddDays(1); } diff --git a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs index d0e7cf4fd..4788beafd 100644 --- a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs +++ b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; using CsvHelper.Configuration; @@ -9,10 +10,11 @@ using GenderPayGap.Core.Classes.Logger; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; -using GenderPayGap.Core.Models; using GenderPayGap.Database; +using GenderPayGap.Extensions; using GenderPayGap.WebUI.ExternalServices.FileRepositories; using GenderPayGap.WebUI.Helpers; +using GenderPayGap.WebUI.Models.Download; using Microsoft.EntityFrameworkCore; namespace GenderPayGap.WebUI.BackgroundJobs.ScheduledJobs @@ -67,7 +69,7 @@ private void UpdateDownloadFilesAction() CustomLogger.Information($"UpdateDownloadFiles: - Converting Returns into results"); List downloadData = returns.ToList() - .Select(r => r.ToDownloadResult()) + .Select(r => ToDownloadResult(r)) .OrderBy(d => d.EmployerName) .ToList(); @@ -121,5 +123,38 @@ private void SaveCsvFile(IEnumerable records, string relativeFilePath) }); } + private static DownloadResult ToDownloadResult(Return ret) + { + return new DownloadResult { + EmployerName = ret.Organisation.GetName(ret.StatusDate)?.Name ?? ret.Organisation.OrganisationName, + EmployerId = ret.OrganisationId, + Address = ret.Organisation.GetLatestAddress()?.GetAddressString(), + PostCode = ret.Organisation.GetLatestAddress()?.GetPostCodeInAllCaps(), + CompanyNumber = ret.Organisation?.CompanyNumber, + SicCodes = ret.Organisation?.GetSicCodeIdsString(ret.StatusDate, "," + Environment.NewLine), + DiffMeanHourlyPercent = ret.DiffMeanHourlyPayPercent, + DiffMedianHourlyPercent = ret.DiffMedianHourlyPercent, + DiffMeanBonusPercent = ret.DiffMeanBonusPercent, + DiffMedianBonusPercent = ret.DiffMedianBonusPercent, + MaleBonusPercent = ret.MaleMedianBonusPayPercent, + FemaleBonusPercent = ret.FemaleMedianBonusPayPercent, + MaleLowerQuartile = ret.MaleLowerPayBand, + FemaleLowerQuartile = ret.FemaleLowerPayBand, + MaleLowerMiddleQuartile = ret.MaleMiddlePayBand, + FemaleLowerMiddleQuartile = ret.FemaleMiddlePayBand, + MaleUpperMiddleQuartile = ret.MaleUpperPayBand, + FemaleUpperMiddleQuartile = ret.FemaleUpperPayBand, + MaleTopQuartile = ret.MaleUpperQuartilePayBand, + FemaleTopQuartile = ret.FemaleUpperQuartilePayBand, + CompanyLinkToGPGInfo = ret.CompanyLinkToGPGInfo, + ResponsiblePerson = ret.ResponsiblePerson, + EmployerSize = ret.OrganisationSize.GetAttribute().Name, + CurrentName = ret.Organisation?.OrganisationName, + SubmittedAfterTheDeadline = ret.IsLateSubmission, + DueDate = ret.GetDueDate(), + DateSubmitted = ret.Modified + }; + } + } } diff --git a/GenderPayGap.Core/Models/DownloadResult.cs b/GenderPayGap.WebUI/Models/Download/DownloadResult.cs similarity index 94% rename from GenderPayGap.Core/Models/DownloadResult.cs rename to GenderPayGap.WebUI/Models/Download/DownloadResult.cs index 0e015ec8e..89f3ef5c5 100644 --- a/GenderPayGap.Core/Models/DownloadResult.cs +++ b/GenderPayGap.WebUI/Models/Download/DownloadResult.cs @@ -1,37 +1,37 @@ -using System; - -namespace GenderPayGap.Core.Models -{ - public class DownloadResult - { - - public string EmployerName { get; set; } - public long EmployerId { get; set; } - public string Address { get; set; } - public string PostCode { get; set; } - public string CompanyNumber { get; set; } - public string SicCodes { get; set; } - public decimal DiffMeanHourlyPercent { get; set; } - public decimal DiffMedianHourlyPercent { get; set; } - public decimal? DiffMeanBonusPercent { get; set; } - public decimal? DiffMedianBonusPercent { get; set; } - public decimal MaleBonusPercent { get; set; } - public decimal FemaleBonusPercent { get; set; } - public decimal? MaleLowerQuartile { get; set; } - public decimal? FemaleLowerQuartile { get; set; } - public decimal? MaleLowerMiddleQuartile { get; set; } - public decimal? FemaleLowerMiddleQuartile { get; set; } - public decimal? MaleUpperMiddleQuartile { get; set; } - public decimal? FemaleUpperMiddleQuartile { get; set; } - public decimal? MaleTopQuartile { get; set; } - public decimal? FemaleTopQuartile { get; set; } - public string CompanyLinkToGPGInfo { get; set; } - public string ResponsiblePerson { get; set; } - public string EmployerSize { get; set; } - public string CurrentName { get; set; } - public bool SubmittedAfterTheDeadline { get; set; } - public DateTime DueDate { get; set; } - public DateTime DateSubmitted { get; set; } - - } -} +using System; + +namespace GenderPayGap.WebUI.Models.Download +{ + public class DownloadResult + { + + public string EmployerName { get; set; } + public long EmployerId { get; set; } + public string Address { get; set; } + public string PostCode { get; set; } + public string CompanyNumber { get; set; } + public string SicCodes { get; set; } + public decimal DiffMeanHourlyPercent { get; set; } + public decimal DiffMedianHourlyPercent { get; set; } + public decimal? DiffMeanBonusPercent { get; set; } + public decimal? DiffMedianBonusPercent { get; set; } + public decimal MaleBonusPercent { get; set; } + public decimal FemaleBonusPercent { get; set; } + public decimal? MaleLowerQuartile { get; set; } + public decimal? FemaleLowerQuartile { get; set; } + public decimal? MaleLowerMiddleQuartile { get; set; } + public decimal? FemaleLowerMiddleQuartile { get; set; } + public decimal? MaleUpperMiddleQuartile { get; set; } + public decimal? FemaleUpperMiddleQuartile { get; set; } + public decimal? MaleTopQuartile { get; set; } + public decimal? FemaleTopQuartile { get; set; } + public string CompanyLinkToGPGInfo { get; set; } + public string ResponsiblePerson { get; set; } + public string EmployerSize { get; set; } + public string CurrentName { get; set; } + public bool SubmittedAfterTheDeadline { get; set; } + public DateTime DueDate { get; set; } + public DateTime DateSubmitted { get; set; } + + } +} From 54bc9aa3ba853b96464e5ec71d78bcdfa424db40 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:37:58 +0000 Subject: [PATCH 16/35] EHD-1411: Reduce code in Core project: Move GetAccountingStartDate --- GenderPayGap.Core/Classes/Extensions.cs | 49 ------------------- .../Helpers/ReportingYearsHelper.cs | 41 +++++++++++++++- .../Models/Extensions/Organisation.cs | 2 +- .../Builders/OrganisationBuilder.cs | 7 +-- .../Builders/OrganisationScopeBuilder.cs | 5 +- .../FillMissingScopesTests.cs | 2 +- .../FindOrgsWhereScopeNotSetTests.cs | 2 +- .../Helpers/ReportingYearsHelperTests.cs | 6 +-- .../Return/ReturnTests.IsLateSubmission.cs | 2 - .../ReturnTests.IsVoluntarySubmission.cs | 2 +- .../TestHelpers/OrganisationScopeHelper.cs | 2 +- .../TestsCommon/TestHelpers/ReturnHelper.cs | 2 +- .../ScheduledJobs/SendReminderEmailsJob.cs | 1 - .../Services/ScopeBusinessLogic.cs | 2 +- .../AdminDatabaseIntegrityChecksController.cs | 2 +- .../Admin/AdminDownloadsController.cs | 1 - .../AdminOrganisationSectorController.cs | 2 +- .../AdminOrganisationStatusController.cs | 1 - .../Admin/AdminViewOrganisationController.cs | 1 - .../Controllers/DownloadController.cs | 1 - .../ManageOrganisationsController.cs | 2 +- .../Report/LateSubmissionController.cs | 1 - .../Report/ReportFiguresController.cs | 2 +- .../Report/ReportOverviewController.cs | 2 +- .../Report/ReportStartingController.cs | 2 +- .../Controllers/ScopeController.cs | 2 +- .../Services/DraftReturnService.cs | 1 - .../Services/OrganisationService.cs | 2 +- GenderPayGap.WebUI/Services/ReturnService.cs | 2 +- 29 files changed, 61 insertions(+), 88 deletions(-) delete mode 100644 GenderPayGap.Core/Classes/Extensions.cs diff --git a/GenderPayGap.Core/Classes/Extensions.cs b/GenderPayGap.Core/Classes/Extensions.cs deleted file mode 100644 index 990dc4aad..000000000 --- a/GenderPayGap.Core/Classes/Extensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using GenderPayGap.Extensions; - -namespace GenderPayGap.Core.Classes -{ - public static class Extensions - { - - /// - /// Returns the accounting start date for the specified sector and year - /// - /// The sector type of the organisation - /// The starting year of the accounting period. If 0 then uses current accounting period - public static DateTime GetAccountingStartDate(this SectorTypes sectorType, int year = 0) - { - var tempDay = 0; - var tempMonth = 0; - - DateTime now = VirtualDateTime.Now; - - switch (sectorType) - { - case SectorTypes.Private: - tempDay = Global.PrivateAccountingDate.Day; - tempMonth = Global.PrivateAccountingDate.Month; - break; - case SectorTypes.Public: - tempDay = Global.PublicAccountingDate.Day; - tempMonth = Global.PublicAccountingDate.Month; - break; - default: - throw new ArgumentOutOfRangeException( - nameof(sectorType), - sectorType, - "Cannot calculate accounting date for this sector type"); - } - - if (year == 0) - { - year = now.Year; - } - - var tempDate = new DateTime(year, tempMonth, tempDay); - - return now > tempDate ? tempDate : tempDate.AddYears(-1); - } - - } -} diff --git a/GenderPayGap.Core/Helpers/ReportingYearsHelper.cs b/GenderPayGap.Core/Helpers/ReportingYearsHelper.cs index ceefaf5d4..1dfa360eb 100644 --- a/GenderPayGap.Core/Helpers/ReportingYearsHelper.cs +++ b/GenderPayGap.Core/Helpers/ReportingYearsHelper.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using GenderPayGap.Core.Classes; using GenderPayGap.Extensions; namespace GenderPayGap.Core.Helpers @@ -124,5 +123,45 @@ public static bool CanChangeScope(SectorTypes sectorType, int reportingYear) int earliestAllowedReportingYear = currentReportingYear - (Global.EditableScopeCount - 1); return reportingYear >= earliestAllowedReportingYear; } + + /// + /// Returns the accounting start date for the specified sector and year + /// + /// The sector type of the organisation + /// The starting year of the accounting period. If 0 then uses current accounting period + public static DateTime GetAccountingStartDate(this SectorTypes sectorType, int year = 0) + { + var tempDay = 0; + var tempMonth = 0; + + DateTime now = VirtualDateTime.Now; + + switch (sectorType) + { + case SectorTypes.Private: + tempDay = Global.PrivateAccountingDate.Day; + tempMonth = Global.PrivateAccountingDate.Month; + break; + case SectorTypes.Public: + tempDay = Global.PublicAccountingDate.Day; + tempMonth = Global.PublicAccountingDate.Month; + break; + default: + throw new ArgumentOutOfRangeException( + nameof(sectorType), + sectorType, + "Cannot calculate accounting date for this sector type"); + } + + if (year == 0) + { + year = now.Year; + } + + var tempDate = new DateTime(year, tempMonth, tempDay); + + return now > tempDate ? tempDate : tempDate.AddYears(-1); + } + } } diff --git a/GenderPayGap.Database/Models/Extensions/Organisation.cs b/GenderPayGap.Database/Models/Extensions/Organisation.cs index 69debec0a..4295c175b 100644 --- a/GenderPayGap.Database/Models/Extensions/Organisation.cs +++ b/GenderPayGap.Database/Models/Extensions/Organisation.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Extensions; namespace GenderPayGap.Database diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationBuilder.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationBuilder.cs index 86ae3903b..3161e9148 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationBuilder.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationBuilder.cs @@ -1,10 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Generic; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Database; -using GenderPayGap.Database.Models; using GenderPayGap.Extensions; using GenderPayGap.WebUI.Tests.TestHelpers; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationScopeBuilder.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationScopeBuilder.cs index 91c283063..587ffe78d 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationScopeBuilder.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/OrganisationScopeBuilder.cs @@ -1,6 +1,5 @@ -using System; -using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core; +using GenderPayGap.Core.Helpers; using GenderPayGap.Database; namespace GenderPayGap.WebUI.Tests.Builders diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FillMissingScopesTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FillMissingScopesTests.cs index 660482a36..775ea8b2f 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FillMissingScopesTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FillMissingScopesTests.cs @@ -1,7 +1,7 @@ using System; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FindOrgsWhereScopeNotSetTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FindOrgsWhereScopeNotSetTests.cs index 6f89852cb..0c395ab90 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FindOrgsWhereScopeNotSetTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Services/ScopeBusinessLogic/FindOrgsWhereScopeNotSetTests.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Tests.Common.Classes; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/ReportingYearsHelperTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/ReportingYearsHelperTests.cs index 26c69dcc5..829269839 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/ReportingYearsHelperTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/CoreTests/Helpers/ReportingYearsHelperTests.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.IO; +using System.Collections.Generic; using System.Linq; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using NUnit.Framework; -using GenderPayGap.Extensions; namespace GenderPayGap.Core.Tests.Helpers { diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsLateSubmission.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsLateSubmission.cs index ba3e19659..b12e8ff70 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsLateSubmission.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsLateSubmission.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; -using GenderPayGap.Extensions; using GenderPayGap.Tests.Common.TestHelpers; using NUnit.Framework; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsVoluntarySubmission.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsVoluntarySubmission.cs index 6dfb68ace..a42cf9f05 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsVoluntarySubmission.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/DatabaseTests/Return/ReturnTests.IsVoluntarySubmission.cs @@ -1,6 +1,6 @@ using System; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Extensions; using GenderPayGap.Tests.Common.TestHelpers; using NUnit.Framework; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/OrganisationScopeHelper.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/OrganisationScopeHelper.cs index 8e42ac955..93738a775 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/OrganisationScopeHelper.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/OrganisationScopeHelper.cs @@ -1,5 +1,5 @@ using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Database; namespace GenderPayGap.Tests.Common.TestHelpers diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/ReturnHelper.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/ReturnHelper.cs index ac101af64..0aa8ffc67 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/ReturnHelper.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/ReturnHelper.cs @@ -1,6 +1,6 @@ using System; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Database; using Moq; diff --git a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/SendReminderEmailsJob.cs b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/SendReminderEmailsJob.cs index 3d1070194..ccdfc98f5 100644 --- a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/SendReminderEmailsJob.cs +++ b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/SendReminderEmailsJob.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Linq.Expressions; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Classes.Logger; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; diff --git a/GenderPayGap.WebUI/BusinessLogic/Services/ScopeBusinessLogic.cs b/GenderPayGap.WebUI/BusinessLogic/Services/ScopeBusinessLogic.cs index b698dee50..2908fd15b 100644 --- a/GenderPayGap.WebUI/BusinessLogic/Services/ScopeBusinessLogic.cs +++ b/GenderPayGap.WebUI/BusinessLogic/Services/ScopeBusinessLogic.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.WebUI.BusinessLogic.Models.Scope; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminDatabaseIntegrityChecksController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminDatabaseIntegrityChecksController.cs index 1827e88ea..c39167ba9 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminDatabaseIntegrityChecksController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminDatabaseIntegrityChecksController.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Linq.Expressions; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.WebUI.Helpers; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs index 832b55a52..44318f634 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs @@ -4,7 +4,6 @@ using System.Dynamic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs index 2f2f7a028..833eef595 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs @@ -1,7 +1,7 @@ using System; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationStatusController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationStatusController.cs index 3f714115c..5a82f2f89 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationStatusController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationStatusController.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminViewOrganisationController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminViewOrganisationController.cs index e2592eb24..df66cb6fc 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminViewOrganisationController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminViewOrganisationController.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; diff --git a/GenderPayGap.WebUI/Controllers/DownloadController.cs b/GenderPayGap.WebUI/Controllers/DownloadController.cs index 5c22c5757..fde0ed690 100644 --- a/GenderPayGap.WebUI/Controllers/DownloadController.cs +++ b/GenderPayGap.WebUI/Controllers/DownloadController.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.WebUI.BackgroundJobs.ScheduledJobs; using GenderPayGap.WebUI.Classes; diff --git a/GenderPayGap.WebUI/Controllers/ManageOrganisations/ManageOrganisationsController.cs b/GenderPayGap.WebUI/Controllers/ManageOrganisations/ManageOrganisationsController.cs index 08ad35157..85831e0d8 100644 --- a/GenderPayGap.WebUI/Controllers/ManageOrganisations/ManageOrganisationsController.cs +++ b/GenderPayGap.WebUI/Controllers/ManageOrganisations/ManageOrganisationsController.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; diff --git a/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs b/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs index 86844d749..60a7338c1 100644 --- a/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs +++ b/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs @@ -1,5 +1,4 @@ using System; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; diff --git a/GenderPayGap.WebUI/Controllers/Report/ReportFiguresController.cs b/GenderPayGap.WebUI/Controllers/Report/ReportFiguresController.cs index 466f0b8aa..3f41195ac 100644 --- a/GenderPayGap.WebUI/Controllers/Report/ReportFiguresController.cs +++ b/GenderPayGap.WebUI/Controllers/Report/ReportFiguresController.cs @@ -1,5 +1,5 @@ using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; diff --git a/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs b/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs index 235b9a9cd..4861ca626 100644 --- a/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs +++ b/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs @@ -1,4 +1,4 @@ -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; diff --git a/GenderPayGap.WebUI/Controllers/Report/ReportStartingController.cs b/GenderPayGap.WebUI/Controllers/Report/ReportStartingController.cs index 48831bc05..a6ba81eba 100644 --- a/GenderPayGap.WebUI/Controllers/Report/ReportStartingController.cs +++ b/GenderPayGap.WebUI/Controllers/Report/ReportStartingController.cs @@ -1,5 +1,5 @@ using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.WebUI.Helpers; diff --git a/GenderPayGap.WebUI/Controllers/ScopeController.cs b/GenderPayGap.WebUI/Controllers/ScopeController.cs index 22a36a269..cc21dac8f 100644 --- a/GenderPayGap.WebUI/Controllers/ScopeController.cs +++ b/GenderPayGap.WebUI/Controllers/ScopeController.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; diff --git a/GenderPayGap.WebUI/Services/DraftReturnService.cs b/GenderPayGap.WebUI/Services/DraftReturnService.cs index 2de00ea4b..84958f8ca 100644 --- a/GenderPayGap.WebUI/Services/DraftReturnService.cs +++ b/GenderPayGap.WebUI/Services/DraftReturnService.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; diff --git a/GenderPayGap.WebUI/Services/OrganisationService.cs b/GenderPayGap.WebUI/Services/OrganisationService.cs index 6589c4d82..f9ad20e86 100644 --- a/GenderPayGap.WebUI/Services/OrganisationService.cs +++ b/GenderPayGap.WebUI/Services/OrganisationService.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; using GenderPayGap.Core.Classes.Logger; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; diff --git a/GenderPayGap.WebUI/Services/ReturnService.cs b/GenderPayGap.WebUI/Services/ReturnService.cs index 21901843b..0cfa921d6 100644 --- a/GenderPayGap.WebUI/Services/ReturnService.cs +++ b/GenderPayGap.WebUI/Services/ReturnService.cs @@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using GenderPayGap.Core; -using GenderPayGap.Core.Classes; +using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; From e7ca43231ee7ecea7fc61ca537bbc55eda16e8e7 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:47:25 +0000 Subject: [PATCH 17/35] EHD-1411: Reduce code in Core project: Move methods out of Extensions.Url --- GenderPayGap.Core/Extensions/Url.cs | 58 ------------------- .../Classes/GoogleAnalyticsTracker.cs | 50 ++++++++++++++-- .../FileRepositories/AwsFileRepository.cs | 20 ++++--- 3 files changed, 58 insertions(+), 70 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/Url.cs diff --git a/GenderPayGap.Core/Extensions/Url.cs b/GenderPayGap.Core/Extensions/Url.cs deleted file mode 100644 index c6e758967..000000000 --- a/GenderPayGap.Core/Extensions/Url.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.IO; - -namespace GenderPayGap.Extensions -{ - public static class Url - { - - public static bool IsUrl(this string url) - { - try - { - if (!url.StartsWithI("http:") && !url.StartsWithI("https:") && !url.StartsWithI("file:")) - { - return false; - } - - var uri = new Uri(url, UriKind.Absolute); - return uri.IsAbsoluteUri; - } - catch - { - return false; - } - } - - public static Uri GetBaseUri(this Uri uri) - { - return new Uri($"{uri.Scheme}://{uri.Authority}/"); - } - - public static string RelativeToAbsoluteUrl(string relativeUrl, Uri baseUrl) - { - if (baseUrl == null) - { - throw new ArgumentNullException(nameof(baseUrl)); - } - - if (relativeUrl.StartsWithI("http://", "https://")) - { - return relativeUrl; - } - - if (!relativeUrl.StartsWith("/")) - { - relativeUrl += $"/{relativeUrl}"; - } - - return new Uri(GetBaseUri(baseUrl), relativeUrl).ToString(); - } - - public static string DirToUrlSeparator(string filePath) - { - return filePath?.Replace('\\', '/'); - } - - } -} diff --git a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs index 80dfe6527..79f05a16a 100644 --- a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs +++ b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs @@ -64,9 +64,9 @@ public void TrackPageView(Controller controller, string pageTitle = null, string { pageUrl = $"{controller.HttpContext.Request.Path}{controller.HttpContext.Request.QueryString}"; } - else if (!pageUrl.IsUrl()) + else if (!IsUrl(pageUrl)) { - pageUrl = Url.RelativeToAbsoluteUrl(pageUrl, new Uri($"{controller.HttpContext.Request.Path}{controller.HttpContext.Request.QueryString}")); + pageUrl = RelativeToAbsoluteUrl(pageUrl, new Uri($"{controller.HttpContext.Request.Path}{controller.HttpContext.Request.QueryString}")); } SendPageViewTracking(pageTitle, pageUrl); @@ -85,12 +85,13 @@ private async void SendPageViewTracking(string title, string url) throw new ArgumentNullException(nameof(url)); } - if (!url.IsUrl()) + if (!IsUrl(url)) { throw new ArgumentException("Url is not absolute", nameof(url)); } - var postData = new List> { + var postData = new List> + { new KeyValuePair("v", googleVersion), new KeyValuePair("tid", googleTrackingId), new KeyValuePair("cid", googleClientId), @@ -121,5 +122,46 @@ public static IAsyncPolicy GetRetryPolicy() TimeSpan.FromMilliseconds(new Random().Next(1, 1000)) + TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); } + private static bool IsUrl(string url) + { + try + { + if (!url.StartsWithI("http:") && !url.StartsWithI("https:") && !url.StartsWithI("file:")) + { + return false; + } + + var uri = new Uri(url, UriKind.Absolute); + return uri.IsAbsoluteUri; + } + catch + { + return false; + } + } + + private static string RelativeToAbsoluteUrl(string relativeUrl, Uri baseUrl) + { + if (baseUrl == null) + { + throw new ArgumentNullException(nameof(baseUrl)); + } + + if (relativeUrl.StartsWithI("http://", "https://")) + { + return relativeUrl; + } + + if (!relativeUrl.StartsWith("/")) + { + relativeUrl += $"/{relativeUrl}"; + } + + var baseUri = new Uri($"{baseUrl.Scheme}://{baseUrl.Authority}/"); + var absoluteUri = new Uri(baseUri, relativeUrl); + + return absoluteUri.ToString(); + } + } } diff --git a/GenderPayGap.WebUI/ExternalServices/FileRepositories/AwsFileRepository.cs b/GenderPayGap.WebUI/ExternalServices/FileRepositories/AwsFileRepository.cs index 2a6a8a621..4da1e2036 100644 --- a/GenderPayGap.WebUI/ExternalServices/FileRepositories/AwsFileRepository.cs +++ b/GenderPayGap.WebUI/ExternalServices/FileRepositories/AwsFileRepository.cs @@ -5,7 +5,6 @@ using Amazon.Runtime; using Amazon.S3; using Amazon.S3.Model; -using GenderPayGap.Extensions; namespace GenderPayGap.WebUI.ExternalServices.FileRepositories { @@ -37,7 +36,7 @@ public void Write(string relativeFilePath, string fileContents) var putRequest = new PutObjectRequest { BucketName = bucketName, - Key = Url.DirToUrlSeparator(relativeFilePath), + Key = DirToUrlSeparator(relativeFilePath), ContentBody = fileContents }; @@ -55,7 +54,7 @@ public void Write(string relativeFilePath, byte[] fileContents) var putRequest = new PutObjectRequest { BucketName = bucketName, - Key = Url.DirToUrlSeparator(relativeFilePath), + Key = DirToUrlSeparator(relativeFilePath), InputStream = memoryStream }; @@ -70,7 +69,7 @@ public string Read(string relativeFilePath) GetObjectRequest request = new GetObjectRequest { BucketName = bucketName, - Key = Url.DirToUrlSeparator(relativeFilePath) + Key = DirToUrlSeparator(relativeFilePath) }; using (GetObjectResponse response = client.GetObjectAsync(request).Result) @@ -90,7 +89,7 @@ public List GetFiles(string relativeDirectoryPath) ListObjectsV2Request request = new ListObjectsV2Request { BucketName = bucketName, - Prefix = Url.DirToUrlSeparator(relativeDirectoryPath), + Prefix = DirToUrlSeparator(relativeDirectoryPath), MaxKeys = 10000 }; @@ -125,7 +124,7 @@ public void Delete(string relativeFilePath) var request = new DeleteObjectRequest { BucketName = bucketName, - Key = Url.DirToUrlSeparator(relativeFilePath) + Key = DirToUrlSeparator(relativeFilePath) }; client.DeleteObjectAsync(request).Wait(); @@ -139,7 +138,7 @@ public bool FileExists(string relativeFilePath) var request = new GetObjectMetadataRequest { BucketName = bucketName, - Key = Url.DirToUrlSeparator(relativeFilePath) + Key = DirToUrlSeparator(relativeFilePath) }; try @@ -161,7 +160,7 @@ public bool FileExists(string relativeFilePath) var request = new GetObjectMetadataRequest { BucketName = bucketName, - Key = Url.DirToUrlSeparator(relativeFilePath) + Key = DirToUrlSeparator(relativeFilePath) }; try @@ -184,5 +183,10 @@ private AmazonS3Client CreateAmazonS3Client() return amazonS3Client; } + private static string DirToUrlSeparator(string filePath) + { + return filePath?.Replace('\\', '/'); + } + } } From 2cacce3aee86af632075aa0e0ba816f36531b791 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 15:59:27 +0000 Subject: [PATCH 18/35] EHD-1411: Reduce code in Core project: Move methods out of Extensions.FileSystem --- GenderPayGap.Core/Extensions/FileSystem.cs | 46 ------------------- .../FileRepositories/SystemFileRepository.cs | 38 ++++++++++++++- 2 files changed, 37 insertions(+), 47 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/FileSystem.cs diff --git a/GenderPayGap.Core/Extensions/FileSystem.cs b/GenderPayGap.Core/Extensions/FileSystem.cs deleted file mode 100644 index cb8e1d85e..000000000 --- a/GenderPayGap.Core/Extensions/FileSystem.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.IO; - -namespace GenderPayGap.Extensions -{ - public static class FileSystem - { - - /// Expands a condensed path relative to the application path (or basePath) up to a full path - public static string ExpandLocalPath(string path, string basePath = null) - { - if (string.IsNullOrWhiteSpace(path)) - { - return null; - } - - if (string.IsNullOrWhiteSpace(basePath)) - { - basePath = AppDomain.CurrentDomain.BaseDirectory; - } - - path = path.Replace(@"/", @"\"); - path = path.Replace(@"~\", @".\"); - path = path.Replace(@"\\", @"\"); - - if (path.StartsWith(@".\") || path.StartsWith(@"..\")) - { - var uri = new Uri(Path.Combine(basePath, path)); - return Path.GetFullPath(uri.LocalPath); - } - - while (path.StartsWithAny('\\', '/')) - { - path = path.Substring(1); - } - - if (!Path.IsPathRooted(path)) - { - path = Path.Combine(basePath, path); - } - - return path; - } - - } -} diff --git a/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs b/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs index 7d844cc83..b95555c69 100644 --- a/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs +++ b/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs @@ -14,7 +14,7 @@ public class SystemFileRepository : IFileRepository public SystemFileRepository(string rootPath = null) { - rootPath = string.IsNullOrWhiteSpace(rootPath) ? AppDomain.CurrentDomain.BaseDirectory : FileSystem.ExpandLocalPath(rootPath); + rootPath = string.IsNullOrWhiteSpace(rootPath) ? AppDomain.CurrentDomain.BaseDirectory : ExpandLocalPath(rootPath); _rootDir = new DirectoryInfo(rootPath); } @@ -137,5 +137,41 @@ private bool GetDirectoryExists(string directoryPath) return Directory.Exists(directoryPath); } + /// Expands a condensed path relative to the application path (or basePath) up to a full path + private static string ExpandLocalPath(string path, string basePath = null) + { + if (string.IsNullOrWhiteSpace(path)) + { + return null; + } + + if (string.IsNullOrWhiteSpace(basePath)) + { + basePath = AppDomain.CurrentDomain.BaseDirectory; + } + + path = path.Replace(@"/", @"\"); + path = path.Replace(@"~\", @".\"); + path = path.Replace(@"\\", @"\"); + + if (path.StartsWith(@".\") || path.StartsWith(@"..\")) + { + var uri = new Uri(Path.Combine(basePath, path)); + return Path.GetFullPath(uri.LocalPath); + } + + while (path.StartsWithAny('\\', '/')) + { + path = path.Substring(1); + } + + if (!Path.IsPathRooted(path)) + { + path = Path.Combine(basePath, path); + } + + return path; + } + } } From 0523da2c4ec17fb70ab90da207a7e12e6ca17523 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 16:17:01 +0000 Subject: [PATCH 19/35] EHD-1411: Reduce code in Core project: Simplify PITP pin generation --- GenderPayGap.Core/Extensions/Crypto.cs | 31 ++++++++------------------ GenderPayGap.Core/Extensions/Lists.cs | 17 +------------- 2 files changed, 10 insertions(+), 38 deletions(-) diff --git a/GenderPayGap.Core/Extensions/Crypto.cs b/GenderPayGap.Core/Extensions/Crypto.cs index 43013ae83..f452ff401 100644 --- a/GenderPayGap.Core/Extensions/Crypto.cs +++ b/GenderPayGap.Core/Extensions/Crypto.cs @@ -46,32 +46,19 @@ public static string GetSHA512Checksum(string text, bool base64encode = true) return calculatedChecksum; } - public static string GeneratePasscode(char[] charset, int passcodeLength) + public static string GeneratePinInThePost() { - //Ensure characters are distinct and mixed up - charset = charset.Distinct().ToList().Randomise().ToArray(); - - var chars = new char[passcodeLength]; - - //Generate a load of random numbers - var randomData = new byte[chars.Length]; - using (var generator = new RNGCryptoServiceProvider()) - { - generator.GetBytes(randomData); - } + string pin = ""; - //use the random number to pick from the character set - for (int i = 0; i < chars.Length; i++) + while (pin.Length < 7) { - chars[i] = charset[randomData[i] % charset.Length]; + int randomIndex = new Random().Next(Global.PINChars.Length); + char nextCharacter = Global.PINChars[randomIndex]; + + pin += nextCharacter; } - - return new string(chars); - } - - public static string GeneratePinInThePost() - { - return GeneratePasscode(Global.PINChars.ToCharArray(), 7); + + return pin; } } diff --git a/GenderPayGap.Core/Extensions/Lists.cs b/GenderPayGap.Core/Extensions/Lists.cs index 906e2167a..25f71a366 100644 --- a/GenderPayGap.Core/Extensions/Lists.cs +++ b/GenderPayGap.Core/Extensions/Lists.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; @@ -156,21 +156,6 @@ public static List ToListOrEmpty(this IEnumerable collection) return collection.ToList(); } - public static IEnumerable Randomise(this IList list) - { - int[] indexes = Enumerable.Range(0, list.Count).ToArray(); - var generator = new Random(); - - for (var i = 0; i < list.Count; ++i) - { - int position = generator.Next(i, list.Count); - - yield return list[indexes[position]]; - - indexes[position] = indexes[i]; - } - } - public static void ForEach(this IEnumerable source, Action action) { if (source == null) From cd39daf2cca7e0cbb7335295a048c55a4f4e4040 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 16:34:10 +0000 Subject: [PATCH 20/35] EHD-1411: Reduce code in Core project: Remove ToDelimitedString --- GenderPayGap.Core/Extensions/EventLog.cs | 2 +- GenderPayGap.Core/Extensions/Lists.cs | 33 ------------------- .../Models/Extensions/Organisation.cs | 14 ++++---- .../Models/Extensions/OrganisationAddress.cs | 2 +- 4 files changed, 10 insertions(+), 41 deletions(-) diff --git a/GenderPayGap.Core/Extensions/EventLog.cs b/GenderPayGap.Core/Extensions/EventLog.cs index 832b3505f..f401ab2f1 100644 --- a/GenderPayGap.Core/Extensions/EventLog.cs +++ b/GenderPayGap.Core/Extensions/EventLog.cs @@ -133,7 +133,7 @@ public static string FullStackTrace(this Exception exception) environmentStackTraceLines.AddRange(stackTraceLines); } - return exception.Message + Environment.NewLine + environmentStackTraceLines.ToDelimitedString(Environment.NewLine); + return exception.Message + Environment.NewLine + string.Join(Environment.NewLine, environmentStackTraceLines); } /// diff --git a/GenderPayGap.Core/Extensions/Lists.cs b/GenderPayGap.Core/Extensions/Lists.cs index 25f71a366..d9f2658fe 100644 --- a/GenderPayGap.Core/Extensions/Lists.cs +++ b/GenderPayGap.Core/Extensions/Lists.cs @@ -104,39 +104,6 @@ public static NameValueCollection FromQueryString(this string querystring) return string.IsNullOrWhiteSpace(querystring) ? null : HttpUtility.ParseQueryString(querystring); } - public static string ToDelimitedString(this IEnumerable list, string delimiter = ",", string appendage = null) - { - if (list == null) - { - return null; - } - - string result = null; - - foreach (T item in list) - { - if (item == null) - { - continue; - } - - string text = item.ToString(); - if (string.IsNullOrWhiteSpace(text)) - { - continue; - } - - if (result != null && !string.IsNullOrEmpty(delimiter) && !result.EndsWithI(delimiter)) - { - result += delimiter; - } - - result += text + appendage; - } - - return result; - } - public static List ToList(this ICollection collection) { var list = new List(collection.Count); diff --git a/GenderPayGap.Database/Models/Extensions/Organisation.cs b/GenderPayGap.Database/Models/Extensions/Organisation.cs index 4295c175b..46610572d 100644 --- a/GenderPayGap.Database/Models/Extensions/Organisation.cs +++ b/GenderPayGap.Database/Models/Extensions/Organisation.cs @@ -54,10 +54,10 @@ public bool GetIsOrphan() public string GetSicSectorsString(DateTime? maxDate = null, string delimiter = ", ") { IEnumerable organisationSicCodes = GetSicCodes(maxDate); - return organisationSicCodes.Select(s => s.SicCode.SicSection.Description.Trim()) - .UniqueI() - .OrderBy(s => s) - .ToDelimitedString(delimiter); + IOrderedEnumerable sicSectionDescriptions = organisationSicCodes.Select(s => s.SicCode.SicSection.Description.Trim()) + .Distinct() + .OrderBy(s => s); + return string.Join(delimiter, sicSectionDescriptions); } /// @@ -90,13 +90,15 @@ public SortedSet GetSicCodeIds(DateTime? maxDate = null) public string GetSicCodeIdsString(DateTime? maxDate = null, string delimiter = ", ") { - return GetSicCodes(maxDate).OrderBy(s => s.SicCodeId).Select(s => s.SicCodeId).ToDelimitedString(delimiter); + IEnumerable sicCodeIds = GetSicCodes(maxDate).OrderBy(s => s.SicCodeId).Select(s => s.SicCodeId); + return string.Join(delimiter, sicCodeIds); } public string GetSicSectionIdsString(DateTime? maxDate = null, string delimiter = ", ") { IEnumerable organisationSicCodes = GetSicCodes(maxDate); - return organisationSicCodes.Select(s => s.SicCode.SicSectionId).UniqueI().OrderBy(s => s).ToDelimitedString(delimiter); + IOrderedEnumerable sicSectionIds = organisationSicCodes.Select(s => s.SicCode.SicSectionId).Distinct().OrderBy(s => s); + return string.Join(delimiter, sicSectionIds); } #region Scope diff --git a/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs b/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs index e3d9c71fb..09b5bbf9e 100644 --- a/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs +++ b/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs @@ -80,7 +80,7 @@ public override bool Equals(object obj) public string GetAddressString(string delimiter = ", ") { - return this.GetAddressLines().ToDelimitedString(delimiter); + return string.Join(delimiter, this.GetAddressLines()); } public bool AddressMatches(OrganisationAddress other) From b10ec0113ad0dad1617af9d67e7be59013f218c8 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 16:39:38 +0000 Subject: [PATCH 21/35] EHD-1411: Reduce code in Core project: Replace non-standard ForEach extension with standard C# foreach loop --- GenderPayGap.Core/Extensions/Lists.cs | 18 ------------------ ...inDatabaseIntegrityChecksControllerTests.cs | 6 +++++- .../Services/ScopeBusinessLogicTests.cs | 5 ++++- .../ScheduledJobs/PurgeOrganisationsJob.cs | 5 ++++- .../Admin/AdminOrganisationSectorController.cs | 14 ++++++++------ .../Controllers/ScopeController.cs | 5 ++++- 6 files changed, 25 insertions(+), 28 deletions(-) diff --git a/GenderPayGap.Core/Extensions/Lists.cs b/GenderPayGap.Core/Extensions/Lists.cs index d9f2658fe..ebc2c196a 100644 --- a/GenderPayGap.Core/Extensions/Lists.cs +++ b/GenderPayGap.Core/Extensions/Lists.cs @@ -123,23 +123,5 @@ public static List ToListOrEmpty(this IEnumerable collection) return collection.ToList(); } - public static void ForEach(this IEnumerable source, Action action) - { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } - - if (action == null) - { - throw new ArgumentNullException(nameof(action)); - } - - foreach (T item in source) - { - action(item); - } - } - } } diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs index 4c8ec0c5c..7eebd47a5 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs @@ -689,7 +689,11 @@ private void AssertReturnsAreDisplayed(PartialViewResult result, params Return[] Assert.NotNull(result); var model = result.Model as List; Assert.AreEqual(returns.Length, model.Count); - returns.ForEach(r => Assert.Contains(r, model)); + + foreach (Return ret in returns) + { + Assert.Contains(ret, model); + } } } diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Services/ScopeBusinessLogicTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Services/ScopeBusinessLogicTests.cs index d8d3af050..7669c2fdc 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Services/ScopeBusinessLogicTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Services/ScopeBusinessLogicTests.cs @@ -84,7 +84,10 @@ private void GenerateTestData() } }); - testOrgData.ForEach(o => o.OrganisationScopes = testOrgScopeData.Where(os => o.OrganisationId == os.OrganisationId).ToList()); + foreach (Organisation organisation in testOrgData) + { + organisation.OrganisationScopes = testOrgScopeData.Where(os => organisation.OrganisationId == os.OrganisationId).ToList(); + } } #endregion diff --git a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/PurgeOrganisationsJob.cs b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/PurgeOrganisationsJob.cs index 5d8a42d56..f2f451246 100644 --- a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/PurgeOrganisationsJob.cs +++ b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/PurgeOrganisationsJob.cs @@ -80,7 +80,10 @@ private void PurgeOrganisation(Organisation org) }); // Un-register all users for this Organisation - org.UserOrganisations.ForEach(uo => dataRepository.Delete(uo)); + foreach (UserOrganisation uo in org.UserOrganisations) + { + dataRepository.Delete(uo); + } // Soft-Delete the Organisation org.SetStatus(OrganisationStatuses.Deleted, details: "Organisation deleted by PurgeOrganisationJob"); diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs index 833eef595..76d1888cf 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs @@ -201,14 +201,16 @@ private void ChangeSector(AdminChangeSectorViewModel viewModel, long organisatio organisation.OrganisationSicCodes.Clear(); // Change snapshot date for all organisation scopes to match new sector - organisation.OrganisationScopes.ForEach( - scope => scope.SnapshotDate = organisation.SectorType.GetAccountingStartDate(scope.SnapshotDate.Year) - ); + foreach (OrganisationScope scope in organisation.OrganisationScopes) + { + scope.SnapshotDate = organisation.SectorType.GetAccountingStartDate(scope.SnapshotDate.Year); + } // Change accounting date for all returns to match new sector - organisation.Returns.ForEach( - returnItem => returnItem.AccountingDate = organisation.SectorType.GetAccountingStartDate(returnItem.AccountingDate.Year) - ); + foreach (Return returnItem in organisation.Returns) + { + returnItem.AccountingDate = organisation.SectorType.GetAccountingStartDate(returnItem.AccountingDate.Year); + } dataRepository.SaveChanges(); diff --git a/GenderPayGap.WebUI/Controllers/ScopeController.cs b/GenderPayGap.WebUI/Controllers/ScopeController.cs index cc21dac8f..010b3fc83 100644 --- a/GenderPayGap.WebUI/Controllers/ScopeController.cs +++ b/GenderPayGap.WebUI/Controllers/ScopeController.cs @@ -241,7 +241,10 @@ private static bool OrganisationIsNewThisYearAndHasNotProvidedScopeForLastYear(O public void RetireOldScopes(Organisation organisation, int reportingYear) { - organisation.OrganisationScopes.Where(o => o.SnapshotDate.Year == reportingYear).ForEach(s => s.Status = ScopeRowStatuses.Retired); + foreach (OrganisationScope s in organisation.OrganisationScopes.Where(o => o.SnapshotDate.Year == reportingYear)) + { + s.Status = ScopeRowStatuses.Retired; + } } public void UpdateScopes(Organisation organisation, ScopeStatuses newStatus, int reportingYear, string reasonForChange, bool? haveReadGuidance) From 47032c1c527ed6afa79ae1b7f5efe9f6e9fdcc70 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 16:47:36 +0000 Subject: [PATCH 22/35] EHD-1411: Reduce code in Core project: Replace non-standard SplitI extension with standard C# code --- GenderPayGap.Core/Extensions/Encryption.cs | 2 +- GenderPayGap.Core/Extensions/EventLog.cs | 2 +- GenderPayGap.Core/Extensions/Lists.cs | 30 +------------------ .../Presentation/CompareViewService.cs | 2 +- 4 files changed, 4 insertions(+), 32 deletions(-) diff --git a/GenderPayGap.Core/Extensions/Encryption.cs b/GenderPayGap.Core/Extensions/Encryption.cs index b05a1ca5c..9687ec485 100644 --- a/GenderPayGap.Core/Extensions/Encryption.cs +++ b/GenderPayGap.Core/Extensions/Encryption.cs @@ -338,7 +338,7 @@ public static string DecryptQuerystring(string querystring, params string[] pass querystring = ns[null]; ns.Remove(null); ns = new NameValueCollection(ns); - foreach (string qs in querystring.SplitI(",")) + foreach (string qs in querystring.Split(",")) { querystring = qs.Replace('-', '+'); querystring = querystring.Replace('_', '/'); diff --git a/GenderPayGap.Core/Extensions/EventLog.cs b/GenderPayGap.Core/Extensions/EventLog.cs index f401ab2f1..5177935fd 100644 --- a/GenderPayGap.Core/Extensions/EventLog.cs +++ b/GenderPayGap.Core/Extensions/EventLog.cs @@ -142,7 +142,7 @@ public static string FullStackTrace(this Exception exception) /// Stack trace string. private static List GetStackTraceLines(string stackTrace) { - return stackTrace.SplitI(Environment.NewLine).ToList(); + return stackTrace.Split(Environment.NewLine).ToList(); } /// diff --git a/GenderPayGap.Core/Extensions/Lists.cs b/GenderPayGap.Core/Extensions/Lists.cs index ebc2c196a..cdffbfb63 100644 --- a/GenderPayGap.Core/Extensions/Lists.cs +++ b/GenderPayGap.Core/Extensions/Lists.cs @@ -14,34 +14,6 @@ namespace GenderPayGap.Extensions public static class Lists { - public static string[] SplitI(this string list, - string separators = ";,", - int maxItems = 0, - StringSplitOptions options = StringSplitOptions.RemoveEmptyEntries) - { - if (string.IsNullOrWhiteSpace(list)) - { - return new string[0]; - } - - if (separators == null) - { - throw new ArgumentNullException("separators"); - } - - if (separators == string.Empty) - { - return list.ToCharArray().Select(c => c.ToString()).ToArray(); - } - - if (maxItems > 0) - { - return list.Split(separators.ToCharArray(), maxItems, options); - } - - return list.Split(separators.ToCharArray(), options); - } - public static IEnumerable UniqueI(this IEnumerable list, bool ignoreCase = true) { return list.Distinct(ignoreCase ? StringComparer.CurrentCultureIgnoreCase : StringComparer.CurrentCulture); @@ -62,7 +34,7 @@ public static string ToQueryString(this NameValueCollection collection, bool all if (allowDuplicateKeys) { - foreach (string value in collection[key].SplitI(",")) + foreach (string value in collection[key].Split(",")) { keyValues.Add(new KeyValuePair(key, value)); } diff --git a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs index c05feeb9c..910fde497 100644 --- a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs +++ b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs @@ -55,7 +55,7 @@ public void LoadComparedEmployersFromCookie() cookieValue = ""; } - string[] employerIds = cookieValue.SplitI(","); + string[] employerIds = cookieValue.Split(","); ComparedEmployers.Clear(); foreach (string employerId in employerIds) From d864d70de459c1a32073078e7147b06529249bf3 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 16:51:14 +0000 Subject: [PATCH 23/35] EHD-1411: Reduce code in Core project: Remove unused code --- GenderPayGap.Core/Extensions/Encryption.cs | 59 ++++++ GenderPayGap.Core/Extensions/Lists.cs | 99 ---------- GenderPayGap.Core/Extensions/Numeric.cs | 75 ------- GenderPayGap.Core/Extensions/Text.cs | 33 ---- .../TestsCommon/Classes/CompareHelpers.cs | 186 ------------------ 5 files changed, 59 insertions(+), 393 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/Lists.cs delete mode 100644 GenderPayGap.Core/Extensions/Numeric.cs delete mode 100644 GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/CompareHelpers.cs diff --git a/GenderPayGap.Core/Extensions/Encryption.cs b/GenderPayGap.Core/Extensions/Encryption.cs index 9687ec485..ad126c046 100644 --- a/GenderPayGap.Core/Extensions/Encryption.cs +++ b/GenderPayGap.Core/Extensions/Encryption.cs @@ -5,8 +5,10 @@ using System.IO; using System.IO.Compression; using System.Linq; +using System.Net; using System.Security.Cryptography; using System.Text; +using System.Web; using Newtonsoft.Json; namespace GenderPayGap.Extensions @@ -541,5 +543,62 @@ public static string DecryptData(string data, out bool isPrivate, params string[ #endregion + private static string ToQueryString(this NameValueCollection collection, bool allowDuplicateKeys = false) + { + var data = ""; + if (collection != null) + { + var keyValues = new List>(); + foreach (string key in collection.Keys) + { + if (string.IsNullOrWhiteSpace(collection[key])) + { + continue; + } + + if (allowDuplicateKeys) + { + foreach (string value in collection[key].Split(",")) + { + keyValues.Add(new KeyValuePair(key, value)); + } + } + else + { + keyValues.Add(new KeyValuePair(key, collection[key])); + } + } + + foreach (KeyValuePair keyValue in keyValues) + { + if (string.IsNullOrWhiteSpace(keyValue.Value)) + { + continue; + } + + if (!string.IsNullOrWhiteSpace(data)) + { + data += "&"; + } + + if (string.IsNullOrWhiteSpace(keyValue.Key)) + { + data += keyValue.Value; + } + else + { + data += $"{WebUtility.UrlEncode(keyValue.Key)}={keyValue.Value}"; + } + } + } + + return data; + } + + private static NameValueCollection FromQueryString(this string querystring) + { + return string.IsNullOrWhiteSpace(querystring) ? null : HttpUtility.ParseQueryString(querystring); + } + } } diff --git a/GenderPayGap.Core/Extensions/Lists.cs b/GenderPayGap.Core/Extensions/Lists.cs deleted file mode 100644 index cdffbfb63..000000000 --- a/GenderPayGap.Core/Extensions/Lists.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Data; -using System.Linq; -using System.Net; -using System.Web; -using Microsoft.Extensions.Primitives; -using Newtonsoft.Json.Linq; - -namespace GenderPayGap.Extensions -{ - public static class Lists - { - - public static IEnumerable UniqueI(this IEnumerable list, bool ignoreCase = true) - { - return list.Distinct(ignoreCase ? StringComparer.CurrentCultureIgnoreCase : StringComparer.CurrentCulture); - } - - public static string ToQueryString(this NameValueCollection collection, bool allowDuplicateKeys = false) - { - var data = ""; - if (collection != null) - { - var keyValues = new List>(); - foreach (string key in collection.Keys) - { - if (string.IsNullOrWhiteSpace(collection[key])) - { - continue; - } - - if (allowDuplicateKeys) - { - foreach (string value in collection[key].Split(",")) - { - keyValues.Add(new KeyValuePair(key, value)); - } - } - else - { - keyValues.Add(new KeyValuePair(key, collection[key])); - } - } - - foreach (KeyValuePair keyValue in keyValues) - { - if (string.IsNullOrWhiteSpace(keyValue.Value)) - { - continue; - } - - if (!string.IsNullOrWhiteSpace(data)) - { - data += "&"; - } - - if (string.IsNullOrWhiteSpace(keyValue.Key)) - { - data += keyValue.Value; - } - else - { - data += $"{WebUtility.UrlEncode(keyValue.Key)}={keyValue.Value}"; - } - } - } - - return data; - } - - public static NameValueCollection FromQueryString(this string querystring) - { - return string.IsNullOrWhiteSpace(querystring) ? null : HttpUtility.ParseQueryString(querystring); - } - - public static List ToList(this ICollection collection) - { - var list = new List(collection.Count); - - list.AddRange(collection.Cast()); - - return list; - } - - public static List ToListOrEmpty(this IEnumerable collection) - { - if (collection == null) - { - return new List(); - } - - return collection.ToList(); - } - - } -} diff --git a/GenderPayGap.Core/Extensions/Numeric.cs b/GenderPayGap.Core/Extensions/Numeric.cs deleted file mode 100644 index 89143a52e..000000000 --- a/GenderPayGap.Core/Extensions/Numeric.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace GenderPayGap.Extensions -{ - public static class Numeric - { - - public static Random Random = new Random(VirtualDateTime.Now.Millisecond); - - /// - /// Returns a randam value between two ranges (inclusive) but excludes certain values - /// - /// The minimum value of the returned result - /// The maximum value of the returned result - /// Values to exclude from results - /// The random value between the min and max values (excluding specified results) - public static int Rand(int Min, int Max, params int[] excludes) - { - int result; - if (excludes == null || excludes.Length == 0) - { - result = Random.Next(Min, Max + 1); - return result; - } - - //Get all values within the range - int[] range = Enumerable.Range(Min, (Max - Min) + 1).ToArray(); - - //Normalise all excludes and sort - excludes = new SortedSet(excludes).ToArray(); - - //Throw wrror if all values are excluded - if (range.SequenceEqual(excludes)) - { - throw new ArgumentOutOfRangeException(nameof(excludes), "All values cannot be excluded"); - } - - //Get a random value unit it is not in the cluded range - do - { - result = Random.Next(Min, Max + 1); - } while (excludes.Contains(result)); - - return result; - } - - public static bool Between(this int num, int lower, int upper, bool inclusive = true) - { - return inclusive - ? lower <= num && num <= upper - : lower < num && num < upper; - } - - public static bool Contains(this int[] numbers, int value) - { - if (numbers == null || numbers.Length < 1) - { - return false; - } - - foreach (int i in numbers) - { - if (i == value) - { - return true; - } - } - - return false; - } - - } -} diff --git a/GenderPayGap.Core/Extensions/Text.cs b/GenderPayGap.Core/Extensions/Text.cs index 2f235b7a0..699b103ad 100644 --- a/GenderPayGap.Core/Extensions/Text.cs +++ b/GenderPayGap.Core/Extensions/Text.cs @@ -32,16 +32,6 @@ public static bool IsNullOrWhiteSpace(this string input, params string[] inputs) return false; } - public static string TrimI(this string source, string trimChars) - { - if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(trimChars)) - { - return source; - } - - return source.Trim(trimChars.ToCharArray()); - } - public static string TrimI(this string source, params char[] trimChars) { if (string.IsNullOrEmpty(source)) @@ -85,29 +75,6 @@ public static bool ContainsI(this string source, string pattern) return source.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0; } - public static bool EndsWithI(this string source, params string[] strings) - { - if (string.IsNullOrWhiteSpace(source)) - { - return false; - } - - foreach (string str in strings) - { - if (string.IsNullOrWhiteSpace(str)) - { - continue; - } - - if (source.ToLower().EndsWith(str.ToLower())) - { - return true; - } - } - - return false; - } - public static bool StartsWithAny(this string source, params char[] chars) { return source.Length > 0 && source[0].IsAny(chars); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/CompareHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/CompareHelpers.cs deleted file mode 100644 index df6142208..000000000 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/CompareHelpers.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using AutoMapper; -using GenderPayGap.Extensions; -using KellermanSoftware.CompareNetObjects; -using NUnit.Framework; - -namespace GenderPayGap.Tests.Common.Classes -{ - public static class CompareHelpers - { - - /// - /// Looks for properties which exist in two objects and compares them and throws an exception containing all the - /// differences. - /// - /// Source object (or list) to compare. - /// Target object (or list) to compare. - /// - /// Ignore Data Table Names, Data Table Column Names, properties, or fields by name during - /// the comparison. Case sensitive. The default is to compare all members - /// - /// - /// Only compare elements by name for Data Table Names, Data Table Column Names, properties - /// and fields. Case sensitive. The default is to compare all members - /// - /// - /// if false (default) items are compared exactly according to order in collection. If - /// true item order is dependent on the default comparer. - /// - /// When comparing strings or StringBuilder types, perform a case sensitive comparison - /// The maximum number of differences to return. Default is -1 ( for int.maxvalue) - /// - /// If true, child objects will be compared. The default is true. If false, and a list or - /// array is compared list items will be compared but not their children. - /// - /// If true, objects will be compared ignore their type diferences. The default is true. - [DebuggerStepThrough] - [Obsolete("We are trying to reduce the use of Automapper. Please don't use this")] - public static void Compare(this object expectedValues, - object actualValues, - IEnumerable membersToIgnore = null, - IEnumerable membersToInclude = null, - bool ignoreCollectionOrder = false, - bool caseSensitive = true, - int maxDifferences = -1, - bool compareChildren = true, - bool ignoreObjectTypes = true) - { - Assert.Multiple( - () => { - foreach (Diff diff in expectedValues.GetDifferences( - actualValues, - membersToIgnore, - membersToInclude, - ignoreCollectionOrder, - caseSensitive, - maxDifferences < 1 ? int.MaxValue : maxDifferences, - compareChildren, - ignoreObjectTypes) - .ToListOrEmpty()) - { - Assert.Fail($"{diff.Name}='{diff.NewValue}' and was expecting '{diff.OldValue}'"); - } - }); - } - - private static T Convert(this S source) - { - if (source == null || source.Equals(default(S)) || source.Equals(default(T))) - { - return default; - } - - var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap(); }); - IMapper iMapper = mapperConfig.CreateMapper(); - - return iMapper.Map(source); - } - - /// - /// - /// - /// - /// - /// - /// - /// Ignore Data Table Names, Data Table Column Names, properties, or fields by name during - /// the comparison. Case sensitive. The default is to compare all members - /// - /// - /// Only compare elements by name for Data Table Names, Data Table Column Names, properties - /// and fields. Case sensitive. The default is to compare all members - /// - /// - /// if false (default) items are compared exactly according to order in collection. If - /// true item order is dependent on the default comparer. - /// - /// When comparing strings or StringBuilder types, perform a case sensitive comparison - /// The maximum number of differences to return. Default is int.MaxValue - /// - /// If true, child objects will be compared. The default is true. If false, and a list or - /// array is compared list items will be compared but not their children. - /// - /// If true, objects will be compared ignore their type diferences. The default is false. - /// - [Obsolete("We are trying to reduce the use of Automapper. Please don't use this")] - private static IEnumerable GetDifferences(this S oldObject, - T newObject, - IEnumerable membersToIgnore = null, - IEnumerable membersToInclude = null, - bool ignoreCollectionOrder = false, - bool caseSensitive = true, - int maxDifferences = int.MaxValue, - bool compareChildren = true, - bool ignoreObjectTypes = false) where S : class - { - var target = newObject as S; - if (target == default(S)) - { - target = Convert(newObject); - } - - var config = new ComparisonConfig - { - CaseSensitive = caseSensitive, - IgnoreCollectionOrder = ignoreCollectionOrder, - ShowBreadcrumb = true, - TreatStringEmptyAndNullTheSame = true, - MaxMillisecondsDateDifference = 1000, - MaxDifferences = maxDifferences, - CompareChildren = compareChildren, - IgnoreObjectDisposedException = true, - IgnoreUnknownObjectTypes = true, - IgnoreObjectTypes = ignoreObjectTypes, - MaxStructDepth = 1 - }; - - if (membersToIgnore != null && membersToIgnore.Any()) - { - config.MembersToIgnore = membersToIgnore.ToList(); - } - - if (membersToInclude != null && membersToInclude.Any()) - { - config.MembersToInclude = membersToInclude.ToList(); - } - - //This is the comparison class - var compareLogic = new CompareLogic(config); - ComparisonResult results = compareLogic.Compare(oldObject, target); - foreach (Difference diff in results.Differences) - { - yield return new Diff - { - Name = - $"{(diff.PropertyName.StartsWith($"{diff.ParentPropertyName}.") ? null : diff.ParentPropertyName)}{diff.PropertyName}.{diff.ChildPropertyName}" - .TrimI("."), - OldValue = diff.Object1Value, - NewValue = diff.Object2Value, - Description = diff.ToString() - }; - } - } - - } - - internal class Diff - { - - public string Description; - public object Name; - public object NewValue; - public object OldValue; - - public override string ToString() - { - return Description; - } - - } - - -} From 2f55cb4a050b885714c7c15d712c975e2007155a Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Mon, 4 Nov 2024 17:38:28 +0000 Subject: [PATCH 24/35] EHD-1411: Reduce code in Core project: Replace long-winded GetAttribute().Name with GetDisplayName() --- GenderPayGap.Core/Enums.cs | 21 ++++++++++++++++++ GenderPayGap.Core/Extensions/Attributes.cs | 22 ------------------- .../Models/Extensions/Return.cs | 1 - .../UpdatePublicFacingDownloadFilesJob.cs | 4 +--- .../Admin/AdminDownloadsController.cs | 5 ++--- .../AdminOrganisationReturnController.cs | 4 +--- .../Controllers/CompareEmployersController.cs | 4 +--- GenderPayGap.WebUI/Services/ReturnService.cs | 2 +- .../CompareEmployersForYear.cshtml | 3 +-- .../ReportOverview/ReportOverview.cshtml | 3 +-- .../Views/Search/SearchPage.cshtml | 3 +-- .../Views/ViewReports/ReportForYear.cshtml | 3 +-- 12 files changed, 31 insertions(+), 44 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/Attributes.cs diff --git a/GenderPayGap.Core/Enums.cs b/GenderPayGap.Core/Enums.cs index ecfb0bf12..dcf8e364e 100644 --- a/GenderPayGap.Core/Enums.cs +++ b/GenderPayGap.Core/Enums.cs @@ -152,6 +152,27 @@ public enum OrganisationSizes } + public static class OrganisationSizesExtensions + { + public static string GetDisplayName(this OrganisationSizes organisationSize) + { + DisplayAttribute displayAttribute = organisationSize.GetType() + .GetMember(organisationSize.ToString()) + .FirstOrDefault() + ?.GetCustomAttribute(); + + return displayAttribute?.Name; + } + + public static RangeAttribute GetRange(this OrganisationSizes organisationSize) + { + return organisationSize.GetType() + .GetMember(organisationSize.ToString()) + .FirstOrDefault() + ?.GetCustomAttribute(); + } + } + public enum AuditedAction { [Display(Name = "Admin changed late flag")] diff --git a/GenderPayGap.Core/Extensions/Attributes.cs b/GenderPayGap.Core/Extensions/Attributes.cs deleted file mode 100644 index 68de4b826..000000000 --- a/GenderPayGap.Core/Extensions/Attributes.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; - -namespace GenderPayGap.Extensions -{ - - public static class Attributes - { - - // Enum - public static TAttribute GetAttribute(this Enum value) where TAttribute : Attribute - { - return value.GetType() - .GetMember(value.ToString()) - .FirstOrDefault() - ?.GetCustomAttribute(); - } - - } - -} diff --git a/GenderPayGap.Database/Models/Extensions/Return.cs b/GenderPayGap.Database/Models/Extensions/Return.cs index 3ed567747..040909da4 100644 --- a/GenderPayGap.Database/Models/Extensions/Return.cs +++ b/GenderPayGap.Database/Models/Extensions/Return.cs @@ -1,5 +1,4 @@ using System; -using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using GenderPayGap.Core; using GenderPayGap.Core.Helpers; diff --git a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs index 4788beafd..c685a88fb 100644 --- a/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs +++ b/GenderPayGap.WebUI/BackgroundJobs/ScheduledJobs/UpdatePublicFacingDownloadFilesJob.cs @@ -1,7 +1,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; using CsvHelper.Configuration; @@ -11,7 +10,6 @@ using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; -using GenderPayGap.Extensions; using GenderPayGap.WebUI.ExternalServices.FileRepositories; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Download; @@ -148,7 +146,7 @@ private static DownloadResult ToDownloadResult(Return ret) FemaleTopQuartile = ret.FemaleUpperQuartilePayBand, CompanyLinkToGPGInfo = ret.CompanyLinkToGPGInfo, ResponsiblePerson = ret.ResponsiblePerson, - EmployerSize = ret.OrganisationSize.GetAttribute().Name, + EmployerSize = ret.OrganisationSize.GetDisplayName(), CurrentName = ret.Organisation?.OrganisationName, SubmittedAfterTheDeadline = ret.IsLateSubmission, DueDate = ret.GetDueDate(), diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs index 44318f634..22ad5ce19 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminDownloadsController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Dynamic; using System.Linq; using GenderPayGap.Core; @@ -270,7 +269,7 @@ private static object ConvertReturnToDownloadFormat(Return returnForYear) CompanyLinkToGPGInfo = returnForYear.CompanyLinkToGPGInfo, ResponsiblePerson = returnForYear.ResponsiblePerson, - OrganisationSize = returnForYear.OrganisationSize.GetAttribute().Name, + OrganisationSize = returnForYear.OrganisationSize.GetDisplayName(), }; } @@ -589,7 +588,7 @@ private static IEnumerable BuildOrganisationsWithNoSubmittedReturnsReco .OrderByDescending(r => r.StatusDate) .FirstOrDefault(r => r.Status == ReturnStatuses.Submitted); - record.Size = latestReturn?.OrganisationSize.GetAttribute().Name; + record.Size = latestReturn?.OrganisationSize.GetDisplayName(); record.FirstName = latestUserOrg?.User.Firstname; record.LastName = latestUserOrg?.User.Lastname; record.JobTitle = latestUserOrg?.User.JobTitle; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationReturnController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationReturnController.cs index 588004402..6d39c2d03 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationReturnController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationReturnController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; using GenderPayGap.Core; @@ -8,7 +7,6 @@ using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Admin; using GenderPayGap.WebUI.Services; @@ -78,7 +76,7 @@ public IActionResult DownloadReturnDetailsCsv(long id) Late = ret.IsLateSubmission, LateReason = ret.LateReason, - Employees = ret.OrganisationSize.GetAttribute().Name, + Employees = ret.OrganisationSize.GetDisplayName(), HourlyPayGapMean = ret.DiffMeanHourlyPayPercent, HourlyPayGapMedian = ret.DiffMedianHourlyPercent, diff --git a/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs b/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs index 5f1d84f96..df18182ab 100644 --- a/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs +++ b/GenderPayGap.WebUI/Controllers/CompareEmployersController.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Linq; using GenderPayGap.Core; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; -using GenderPayGap.Extensions; using GenderPayGap.WebUI.Classes.Presentation; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Compare; @@ -181,7 +179,7 @@ public IActionResult DownloadCSVOfCompareEmployersForYear(int year, string emplo { EmployerName = organisation.OrganisationName, ReportStatus = reportStatusTag.ToString(), - NumberOfEmployees = hasEmployerReportedForYear ? returnForYear.OrganisationSize.GetAttribute().Name : "", + NumberOfEmployees = hasEmployerReportedForYear ? returnForYear.OrganisationSize.GetDisplayName() : "", GenderPayGap_HourlyPay_Mean_Percent = hasEmployerReportedForYear ? returnForYear.DiffMeanHourlyPayPercent.ToString() : "", GenderPayGap_HourlyPay_Median_Percent = hasEmployerReportedForYear ? returnForYear.DiffMedianHourlyPercent.ToString() : "", diff --git a/GenderPayGap.WebUI/Services/ReturnService.cs b/GenderPayGap.WebUI/Services/ReturnService.cs index 0cfa921d6..4aa18914b 100644 --- a/GenderPayGap.WebUI/Services/ReturnService.cs +++ b/GenderPayGap.WebUI/Services/ReturnService.cs @@ -90,7 +90,7 @@ private Return CreateReturnFromDraftReturn( { Organisation organisation = dataRepository.Get(draftReturn.OrganisationId); Return existingReturn = organisation.GetReturn(draftReturn.SnapshotYear); - var organisationSizeRange = draftReturn.OrganisationSize?.GetAttribute(); + RangeAttribute organisationSizeRange = draftReturn.OrganisationSize?.GetRange(); var newReturn = new Return { diff --git a/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml b/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml index 685b20fe1..88cf4175d 100644 --- a/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml +++ b/GenderPayGap.WebUI/Views/CompareEmployers/CompareEmployersForYear.cshtml @@ -6,7 +6,6 @@ @using GovUkDesignSystem.GovUkDesignSystemComponents @using Microsoft.AspNetCore.Mvc.TagHelpers @using GenderPayGap.Core -@using System.ComponentModel.DataAnnotations @inject ICompareViewService CompareViewService @model GenderPayGap.WebUI.Models.Compare.CompareEmployersForYearViewModel @@ -286,7 +285,7 @@ @if (hasEmployerReportedForYear) { - @(returnForYear.OrganisationSize.GetAttribute().Name) + @(returnForYear.OrganisationSize.GetDisplayName()) @(returnForYear.DiffMeanHourlyPayPercent)% diff --git a/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml b/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml index f11439140..203296a08 100644 --- a/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml +++ b/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml @@ -1,7 +1,6 @@ @using GenderPayGap.Core.Helpers @using GovUkDesignSystem @using GovUkDesignSystem.GovUkDesignSystemComponents -@using System.ComponentModel.DataAnnotations @using GenderPayGap.Core @using GenderPayGap.WebUI.Models.Report @using GenderPayGap.WebUI.Views.Components.StatusMessages @@ -212,7 +211,7 @@ Title = @Number of employees used to establish your headcount for gender pay gap reporting, on your snapshot date, RightValue = !Model.SizeOfOrganisation.HasValue ? await Html.GovUkHtmlText(new HtmlText(null, "Not Provided" )) - : await Html.GovUkHtmlText(new HtmlText(null, Model.SizeOfOrganisation.GetAttribute().Name)) + : await Html.GovUkHtmlText(new HtmlText(null, Model.SizeOfOrganisation.Value.GetDisplayName())) } } }; diff --git a/GenderPayGap.WebUI/Views/Search/SearchPage.cshtml b/GenderPayGap.WebUI/Views/Search/SearchPage.cshtml index 429e9ee65..0a8eb5b5e 100644 --- a/GenderPayGap.WebUI/Views/Search/SearchPage.cshtml +++ b/GenderPayGap.WebUI/Views/Search/SearchPage.cshtml @@ -2,7 +2,6 @@ @using GovUkDesignSystem.GovUkDesignSystemComponents @using Microsoft.AspNetCore.Mvc.TagHelpers @using GenderPayGap.Core -@using System.ComponentModel.DataAnnotations @using GenderPayGap.Core.Helpers @model GenderPayGap.WebUI.Models.Search.SearchPageViewModel @@ -109,7 +108,7 @@ orgSize => orgSize, orgSize => new LabelViewModel { - Text = orgSize.GetAttribute().Name + Text = orgSize.GetDisplayName() } ), classOptions: new Dictionary {{OrganisationSizes.NotProvided, "gpg-search-page--filter-employerSize--not-provided"}}, diff --git a/GenderPayGap.WebUI/Views/ViewReports/ReportForYear.cshtml b/GenderPayGap.WebUI/Views/ViewReports/ReportForYear.cshtml index 074e9152f..f277cc45e 100644 --- a/GenderPayGap.WebUI/Views/ViewReports/ReportForYear.cshtml +++ b/GenderPayGap.WebUI/Views/ViewReports/ReportForYear.cshtml @@ -4,7 +4,6 @@ @using GenderPayGap.WebUI.Helpers @using GenderPayGap.Core @using Microsoft.AspNetCore.Mvc.TagHelpers -@using System.ComponentModel.DataAnnotations @model GenderPayGap.Database.Return @{ @@ -494,7 +493,7 @@ Employee headcount
    - @(Model.OrganisationSize.GetAttribute().Name) employees + @(Model.OrganisationSize.GetDisplayName()) employees
    @if (Model.Organisation.SectorType == SectorTypes.Private) From e914236366103ea0ef49de933c63a7553b8fed5c Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 10:33:33 +0000 Subject: [PATCH 25/35] EHD-1411: Reduce code in Core project: Move methods out of Crypto --- .../Builders/UserBuilder.cs | 5 +- .../UserRepository/CheckPasswordTests.cs | 6 +- .../UserRepository/UpdatePasswordTests.cs | 5 +- .../PasswordResetControllerTests.cs | 5 +- .../TestsCommon/TestHelpers/UserHelper.cs | 3 +- .../Account/AccountCreationController.cs | 7 +- .../Account/PasswordResetController.cs | 4 +- .../Admin/AdminUnconfirmedPinsController.cs | 4 +- .../Helpers/PasswordHelper.cs | 112 ++++++++---------- .../Repositories/UserRepository.cs | 12 +- .../Services/PinInThePostService.cs | 21 +++- 11 files changed, 90 insertions(+), 94 deletions(-) rename GenderPayGap.Core/Extensions/Crypto.cs => GenderPayGap.WebUI/Helpers/PasswordHelper.cs (70%) diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/UserBuilder.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/UserBuilder.cs index b1202dc3c..349d745ce 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/UserBuilder.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/UserBuilder.cs @@ -3,6 +3,7 @@ using GenderPayGap.Core; using GenderPayGap.Database; using GenderPayGap.Extensions; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Tests.TestHelpers; namespace GenderPayGap.WebUI.Tests.Builders @@ -28,7 +29,7 @@ public UserBuilder() UserOrganisations = new List(), HashingAlgorithm = HashingAlgorithm.PBKDF2, Salt = Salt, - PasswordHash = Crypto.GetPBKDF2("password", Convert.FromBase64String(Salt)), + PasswordHash = PasswordHelper.GetPBKDF2("password", Convert.FromBase64String(Salt)), PasswordResetCode = null }; } @@ -86,7 +87,7 @@ public UserBuilder WithOrganisation(Organisation organisation) public UserBuilder WithPassword(string password) { userInProgress.Salt = Salt; - userInProgress.PasswordHash = Crypto.GetPBKDF2(password, Convert.FromBase64String(Salt)); + userInProgress.PasswordHash = PasswordHelper.GetPBKDF2(password, Convert.FromBase64String(Salt)); userInProgress.HashingAlgorithm = HashingAlgorithm.PBKDF2; return this; } diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/CheckPasswordTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/CheckPasswordTests.cs index 2e85afc52..68b362c76 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/CheckPasswordTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/CheckPasswordTests.cs @@ -2,8 +2,8 @@ using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; -using GenderPayGap.Extensions; using GenderPayGap.WebUI.BusinessLogic.Abstractions; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Services; using Moq; using NUnit.Framework; @@ -42,7 +42,7 @@ public void CorrectPasswordShouldResetLoginAttempts() var testPassword = "currentPassword123"; var salt = "testSalt"; var testUser = new User { - PasswordHash = Crypto.GetPBKDF2(testPassword, Convert.FromBase64String(salt)), + PasswordHash = PasswordHelper.GetPBKDF2(testPassword, Convert.FromBase64String(salt)), Salt = salt, HashingAlgorithm = HashingAlgorithm.PBKDF2, LoginAttempts = 3 }; @@ -66,7 +66,7 @@ public void IncorrectPasswordShouldIncreaseLoginAttempts() var testPassword = "currentPassword123"; var salt = "testSalt"; var testUser = new User { - PasswordHash = Crypto.GetPBKDF2("WrongPassword123", Convert.FromBase64String(salt)), Salt = salt, HashingAlgorithm = HashingAlgorithm.PBKDF2, LoginAttempts = 0 + PasswordHash = PasswordHelper.GetPBKDF2("WrongPassword123", Convert.FromBase64String(salt)), Salt = salt, HashingAlgorithm = HashingAlgorithm.PBKDF2, LoginAttempts = 0 }; var testAttempts = 3; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs index 866e43076..3d80e2f35 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs @@ -6,6 +6,7 @@ using GenderPayGap.Tests.Common.Classes; using GenderPayGap.Tests.Common.TestHelpers; using GenderPayGap.WebUI.BusinessLogic.Abstractions; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Services; using Moq; using NUnit.Framework; @@ -53,7 +54,7 @@ public void SavesNewPasswordHash() // Assert Assert.IsTrue(saveChangesCalled, "Expected SaveChanges to be called"); - Assert.AreEqual(Crypto.GetPBKDF2(testPassword, Convert.FromBase64String(testUserToUpdate.Salt)), testUserToUpdate.PasswordHash, "Expected to change password"); + Assert.AreEqual(PasswordHelper.GetPBKDF2(testPassword, Convert.FromBase64String(testUserToUpdate.Salt)), testUserToUpdate.PasswordHash, "Expected to change password"); Assert.AreEqual(HashingAlgorithm.PBKDF2, testUserToUpdate.HashingAlgorithm, "Expected hashing algorithm to change"); } @@ -66,7 +67,7 @@ public void ThrowsErrorWhenUserStatusIsNotActive(string testCurrentEmail, UserSt // Arrange User testUserToUpdate = testUserRepo.FindByEmail(testCurrentEmail); DateTime testEmailVerifiedDate = VirtualDateTime.Now.Date.AddDays(-7); - string testExistingPasswordHash = Crypto.GetPBKDF2("ExistingPassword123", Convert.FromBase64String(testUserToUpdate.Salt)); + string testExistingPasswordHash = PasswordHelper.GetPBKDF2("ExistingPassword123", Convert.FromBase64String(testUserToUpdate.Salt)); testUserToUpdate.PasswordHash = testExistingPasswordHash; testUserToUpdate.Status = testStatus; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs index 0a09dc9df..9b5e0f4d2 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; using GenderPayGap.Database; @@ -7,10 +6,10 @@ using GenderPayGap.Extensions; using GenderPayGap.WebUI.Controllers.Account; using GenderPayGap.WebUI.ErrorHandling; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; -using Microsoft.Extensions.Primitives; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.PasswordReset @@ -108,7 +107,7 @@ public void POST_Valid_Reset_Code_In_URL_Allows_User_To_Change_Their_Password() controller.ChooseNewPasswordPost(new ChooseNewPasswordViewModel { ResetCode = "code", NewPassword = "NewPassword1", ConfirmNewPassword = "NewPassword1"}); // Assert - Assert.AreEqual(Crypto.GetPBKDF2("NewPassword1", Convert.FromBase64String(user.Salt)), user.PasswordHash); + Assert.AreEqual(PasswordHelper.GetPBKDF2("NewPassword1", Convert.FromBase64String(user.Salt)), user.PasswordHash); Assert.IsNull(user.PasswordResetCode); Assert.AreEqual(1, controllerBuilder.EmailsSent.Count); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/UserHelper.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/UserHelper.cs index 2380e0d97..fcaf0a67b 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/UserHelper.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/TestHelpers/UserHelper.cs @@ -3,6 +3,7 @@ using GenderPayGap.Core; using GenderPayGap.Database; using GenderPayGap.Extensions; +using GenderPayGap.WebUI.Helpers; namespace GenderPayGap.Tests.Common.TestHelpers { @@ -13,7 +14,7 @@ public static class UserHelpers public static List CreateUsers() { byte[] salt = Convert.FromBase64String("TestSalt"); - string passwordHash = Crypto.GetPBKDF2("ad5bda75-e514-491b-b74d-4672542cbd15", salt); + string passwordHash = PasswordHelper.GetPBKDF2("ad5bda75-e514-491b-b74d-4672542cbd15", salt); return new List { new User { diff --git a/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs b/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs index e2bd81bcc..23b2d7085 100644 --- a/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs +++ b/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs @@ -5,10 +5,9 @@ using GenderPayGap.Database; using GenderPayGap.Extensions; using GenderPayGap.WebUI.BusinessLogic.Abstractions; -using GenderPayGap.WebUI.Classes; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.AccountCreation; using GenderPayGap.WebUI.Services; -using GovUkDesignSystem; using Microsoft.AspNetCore.Mvc; namespace GenderPayGap.WebUI.Controllers.Account @@ -180,9 +179,9 @@ private User CreateNewOrUpdateRetiredUser(CreateUserAccountViewModel viewModel, user.AllowContact = viewModel.AllowContact; user.SendUpdates = viewModel.SendUpdates; - byte[] salt = Crypto.GetSalt(); + byte[] salt = PasswordHelper.GetSalt(); user.Salt = Convert.ToBase64String(salt); - user.PasswordHash = Crypto.GetPBKDF2(viewModel.Password, salt); + user.PasswordHash = PasswordHelper.GetPBKDF2(viewModel.Password, salt); user.HashingAlgorithm = HashingAlgorithm.PBKDF2; user.EmailVerifySendDate = null; diff --git a/GenderPayGap.WebUI/Controllers/Account/PasswordResetController.cs b/GenderPayGap.WebUI/Controllers/Account/PasswordResetController.cs index f6df6a8df..e2c378e1c 100644 --- a/GenderPayGap.WebUI/Controllers/Account/PasswordResetController.cs +++ b/GenderPayGap.WebUI/Controllers/Account/PasswordResetController.cs @@ -6,8 +6,8 @@ using GenderPayGap.Database; using GenderPayGap.Extensions; using GenderPayGap.WebUI.BusinessLogic.Abstractions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.ErrorHandling; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using Microsoft.AspNetCore.Mvc; @@ -93,7 +93,7 @@ private static bool PasswordResetEmailSentTooRecently(User userForPasswordReset) private void SendPasswordResetEmail(User userForPasswordReset) { // Generate a random string as a unique identifier for the password reset - string resetCode = Convert.ToBase64String(Crypto.GetSalt()); + string resetCode = Convert.ToBase64String(PasswordHelper.GetSalt()); // Store the reset code on the user entity for verification userForPasswordReset.PasswordResetCode = resetCode; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminUnconfirmedPinsController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminUnconfirmedPinsController.cs index 5c72bbd99..ac68b6c9d 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminUnconfirmedPinsController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminUnconfirmedPinsController.cs @@ -4,12 +4,10 @@ using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; namespace GenderPayGap.WebUI.Controllers.Admin { @@ -61,7 +59,7 @@ public IActionResult SendPin(long userId, long organisationId) if (userOrganisation.PINSentDate.Value.AddDays(Global.PinInPostExpiryDays) < VirtualDateTime.Now) { - string newPin = Crypto.GeneratePinInThePost(); + string newPin = PinInThePostService.GeneratePinInThePost(); userOrganisation.PIN = newPin; } diff --git a/GenderPayGap.Core/Extensions/Crypto.cs b/GenderPayGap.WebUI/Helpers/PasswordHelper.cs similarity index 70% rename from GenderPayGap.Core/Extensions/Crypto.cs rename to GenderPayGap.WebUI/Helpers/PasswordHelper.cs index f452ff401..ec3f9622a 100644 --- a/GenderPayGap.Core/Extensions/Crypto.cs +++ b/GenderPayGap.WebUI/Helpers/PasswordHelper.cs @@ -1,65 +1,47 @@ -using System; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using GenderPayGap.Core; -using Microsoft.AspNetCore.Cryptography.KeyDerivation; - -namespace GenderPayGap.Extensions -{ - public static class Crypto - { - - public static string GetPBKDF2(string password, - byte[] salt, - KeyDerivationPrf prfunction = KeyDerivationPrf.HMACSHA1, - int iterationCount = 10000, - int hashSizeInBit = 256) - { - return Convert.ToBase64String( - KeyDerivation.Pbkdf2( - password, - salt, - prfunction, - iterationCount, - hashSizeInBit / 8)); - } - - public static byte[] GetSalt(int saltSizeInBit = 128) - { - // generate a salt using a secure PRNG - var salt = new byte[saltSizeInBit / 8]; - using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) - { - rng.GetBytes(salt); - } - - return salt; - } - - - public static string GetSHA512Checksum(string text, bool base64encode = true) - { - byte[] checksumData = Encoding.UTF8.GetBytes(text); - byte[] hash = SHA512.Create().ComputeHash(checksumData); - string calculatedChecksum = base64encode ? Convert.ToBase64String(hash) : Encoding.UTF8.GetString(hash); - return calculatedChecksum; - } - - public static string GeneratePinInThePost() - { - string pin = ""; - - while (pin.Length < 7) - { - int randomIndex = new Random().Next(Global.PINChars.Length); - char nextCharacter = Global.PINChars[randomIndex]; - - pin += nextCharacter; - } - - return pin; - } - - } -} +using System; +using System.Security.Cryptography; +using System.Text; +using Microsoft.AspNetCore.Cryptography.KeyDerivation; + +namespace GenderPayGap.WebUI.Helpers +{ + public static class PasswordHelper + { + + public static string GetPBKDF2(string password, + byte[] salt, + KeyDerivationPrf prfunction = KeyDerivationPrf.HMACSHA1, + int iterationCount = 10000, + int hashSizeInBit = 256) + { + return Convert.ToBase64String( + KeyDerivation.Pbkdf2( + password, + salt, + prfunction, + iterationCount, + hashSizeInBit / 8)); + } + + public static byte[] GetSalt(int saltSizeInBit = 128) + { + // generate a salt using a secure PRNG + var salt = new byte[saltSizeInBit / 8]; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(salt); + } + + return salt; + } + + public static string GetSHA512Checksum(string text, bool base64encode = true) + { + byte[] checksumData = Encoding.UTF8.GetBytes(text); + byte[] hash = SHA512.Create().ComputeHash(checksumData); + string calculatedChecksum = base64encode ? Convert.ToBase64String(hash) : Encoding.UTF8.GetString(hash); + return calculatedChecksum; + } + + } +} diff --git a/GenderPayGap.WebUI/Repositories/UserRepository.cs b/GenderPayGap.WebUI/Repositories/UserRepository.cs index 0ec5a6648..42791efac 100644 --- a/GenderPayGap.WebUI/Repositories/UserRepository.cs +++ b/GenderPayGap.WebUI/Repositories/UserRepository.cs @@ -1,12 +1,12 @@ using System; using System.ComponentModel; using System.Linq; -using System.Linq.Expressions; using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; using GenderPayGap.WebUI.BusinessLogic.Abstractions; +using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Services; namespace GenderPayGap.WebUI.Repositories @@ -169,11 +169,11 @@ private bool CheckPasswordBasedOnHashingAlgorithm(User user, string password) switch (user.HashingAlgorithm) { case HashingAlgorithm.SHA512: - return user.PasswordHash == Crypto.GetSHA512Checksum(password); + return user.PasswordHash == PasswordHelper.GetSHA512Checksum(password); case HashingAlgorithm.PBKDF2: - return user.PasswordHash == Crypto.GetPBKDF2(password, Convert.FromBase64String(user.Salt)); + return user.PasswordHash == PasswordHelper.GetPBKDF2(password, Convert.FromBase64String(user.Salt)); case HashingAlgorithm.PBKDF2AppliedToSHA512: - return user.PasswordHash == Crypto.GetPBKDF2(Crypto.GetSHA512Checksum(password), Convert.FromBase64String(user.Salt)); + return user.PasswordHash == PasswordHelper.GetPBKDF2(PasswordHelper.GetSHA512Checksum(password), Convert.FromBase64String(user.Salt)); case HashingAlgorithm.Unknown: throw new InvalidOperationException($"Hashing algorithm should not be unknown {user.HashingAlgorithm}"); default: @@ -188,9 +188,9 @@ private void UpdateUserPasswordUsingPBKDF2(User user, string password) throw new ArgumentNullException(nameof(user)); } - byte[] salt = Crypto.GetSalt(); + byte[] salt = PasswordHelper.GetSalt(); user.Salt = Convert.ToBase64String(salt); - user.PasswordHash = Crypto.GetPBKDF2(password, salt); + user.PasswordHash = PasswordHelper.GetPBKDF2(password, salt); user.HashingAlgorithm = HashingAlgorithm.PBKDF2; dataRepository.SaveChanges(); diff --git a/GenderPayGap.WebUI/Services/PinInThePostService.cs b/GenderPayGap.WebUI/Services/PinInThePostService.cs index 6f09aa398..1406e2177 100644 --- a/GenderPayGap.WebUI/Services/PinInThePostService.cs +++ b/GenderPayGap.WebUI/Services/PinInThePostService.cs @@ -5,7 +5,6 @@ using GenderPayGap.Core.Classes.Logger; using GenderPayGap.Database; using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Controllers; using GenderPayGap.WebUI.ExternalServices; using Microsoft.AspNetCore.Mvc; using Notify.Models.Responses; @@ -27,7 +26,7 @@ public PinInThePostService(IGovNotifyAPI govNotifyApi) public bool GenerateAndSendPinInThePostAndUpdateUserOrganisationWithLetterId(UserOrganisation userOrganisation, IUrlHelper urlHelper) { - string pin = Crypto.GeneratePinInThePost(); + string pin = GeneratePinInThePost(); bool sendSuccess = SendPinInThePost(urlHelper, userOrganisation, pin, out string letterId); @@ -55,7 +54,8 @@ public bool SendPinInThePost(IUrlHelper urlHelper, UserOrganisation userOrganisa DateTime pinExpiryDate = VirtualDateTime.Now.AddDays(Global.PinInPostExpiryDays); - var personalisation = new Dictionary { + var personalisation = new Dictionary + { {"address_line_1", userFullNameAndJobTitle}, {"address_line_2", companyName}, {"address_line_3", address.Count > 0 ? address[0] : ""}, @@ -185,5 +185,20 @@ private static void ReduceByOneLine(List address) } } + public static string GeneratePinInThePost() + { + string pin = ""; + + while (pin.Length < 7) + { + int randomIndex = new Random().Next(Global.PINChars.Length); + char nextCharacter = Global.PINChars[randomIndex]; + + pin += nextCharacter; + } + + return pin; + } + } } From c5a4c1252884704f16253db4a79617592e5632fa Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 11:00:39 +0000 Subject: [PATCH 26/35] EHD-1411: Reduce code in Core project: Move some methods out of Misc --- GenderPayGap.Core/Enums.cs | 4 ++++ GenderPayGap.Core/Extensions/Text.cs | 5 ----- GenderPayGap.Database/Models/Extensions/Return.cs | 8 ++++---- .../FileRepositories/SystemFileRepository.cs | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/GenderPayGap.Core/Enums.cs b/GenderPayGap.Core/Enums.cs index dcf8e364e..846e6d9e1 100644 --- a/GenderPayGap.Core/Enums.cs +++ b/GenderPayGap.Core/Enums.cs @@ -112,6 +112,10 @@ public static bool IsInScopeVariant(this ScopeStatuses scopeStatus) { return scopeStatus == ScopeStatuses.InScope || scopeStatus == ScopeStatuses.PresumedInScope; } + public static bool IsOutOfScopeVariant(this ScopeStatuses scopeStatus) + { + return scopeStatus == ScopeStatuses.OutOfScope || scopeStatus == ScopeStatuses.PresumedOutOfScope; + } public static bool IsScopePresumed(this ScopeStatuses scopeStatus) { diff --git a/GenderPayGap.Core/Extensions/Text.cs b/GenderPayGap.Core/Extensions/Text.cs index 699b103ad..51656b70e 100644 --- a/GenderPayGap.Core/Extensions/Text.cs +++ b/GenderPayGap.Core/Extensions/Text.cs @@ -75,11 +75,6 @@ public static bool ContainsI(this string source, string pattern) return source.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0; } - public static bool StartsWithAny(this string source, params char[] chars) - { - return source.Length > 0 && source[0].IsAny(chars); - } - public static bool StartsWithI(this string original, params string[] texts) { if (string.IsNullOrWhiteSpace(original)) diff --git a/GenderPayGap.Database/Models/Extensions/Return.cs b/GenderPayGap.Database/Models/Extensions/Return.cs index 040909da4..b40bd5d0d 100644 --- a/GenderPayGap.Database/Models/Extensions/Return.cs +++ b/GenderPayGap.Database/Models/Extensions/Return.cs @@ -80,7 +80,7 @@ public override int GetHashCode() public bool IsRequired() { return OrganisationSize != OrganisationSizes.Employees0To249 - && GetScopeStatus().IsAny(ScopeStatuses.InScope, ScopeStatuses.PresumedInScope) + && GetScopeStatus().IsInScopeVariant() && !Global.ReportingStartYearsToExcludeFromLateFlagEnforcement.Contains(AccountingDate.Year); } @@ -103,15 +103,15 @@ public bool CalculateIsLateSubmission() { return Modified > GetDueDate() && OrganisationSize != OrganisationSizes.Employees0To249 - && GetScopeStatus().IsAny(ScopeStatuses.InScope, ScopeStatuses.PresumedInScope) + && GetScopeStatus().IsInScopeVariant() && !Global.ReportingStartYearsToExcludeFromLateFlagEnforcement.Contains(AccountingDate.Year); } public bool IsVoluntarySubmission() { return ReturnId > 0 - && OrganisationSize.IsAny(OrganisationSizes.Employees0To249) - && GetScopeStatus().IsAny(ScopeStatuses.OutOfScope, ScopeStatuses.PresumedOutOfScope); + && OrganisationSize == OrganisationSizes.Employees0To249 + && GetScopeStatus().IsOutOfScopeVariant(); } public void SetStatus(ReturnStatuses status, long byUserId, string details = null) diff --git a/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs b/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs index b95555c69..a21435de8 100644 --- a/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs +++ b/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs @@ -160,7 +160,7 @@ private static string ExpandLocalPath(string path, string basePath = null) return Path.GetFullPath(uri.LocalPath); } - while (path.StartsWithAny('\\', '/')) + while (path.StartsWith('\\') || path.StartsWith('/')) { path = path.Substring(1); } From ed29996e9ccbe123185ee2469eb7195f9256c122 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 11:01:30 +0000 Subject: [PATCH 27/35] EHD-1411: Reduce code in Core project: Move FindParentWithAttribute out of Misc --- GenderPayGap.Core/Extensions/Misc.cs | 24 +------------- .../Builders/ControllerBuilder.cs | 2 +- .../TestHelpers/UiTestHelpers.cs | 33 +++++++++++++++++-- .../TestsCommon/Classes/AutoFacHelpers.cs | 3 +- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/GenderPayGap.Core/Extensions/Misc.cs b/GenderPayGap.Core/Extensions/Misc.cs index 0ff47e1b8..f8c4b4198 100644 --- a/GenderPayGap.Core/Extensions/Misc.cs +++ b/GenderPayGap.Core/Extensions/Misc.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; @@ -231,27 +231,5 @@ public static DateTime ToDateTime(this object text) return DateTime.MinValue; } - public static MethodBase FindParentWithAttribute(this MethodBase callingMethod, int parentOffset = 0) where T : Attribute - { - // Iterate throught all attributes - StackFrame[] frames = new StackTrace().GetFrames(); - - for (int i = 1 + parentOffset; i < frames.Length; i++) - { - StackFrame frame = frames[i]; - if (frame.HasMethod()) - { - MethodBase method = frame.GetMethod(); - - if (method.GetCustomAttribute() != null) - { - return method; - } - } - } - - return callingMethod; - } - } } diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs index 56f82cdc5..a8d6d584d 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs @@ -196,7 +196,7 @@ private IDataRepository CreateInMemoryTestDatabase() string testName = TestContext.CurrentContext.Test.FullName; if (string.IsNullOrWhiteSpace(testName)) { - testName = MethodBase.GetCurrentMethod().FindParentWithAttribute().Name; + testName = UiTestHelper.GetCurrentTestName(); } DbContextOptionsBuilder optionsBuilder = diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs index ee342ec08..583aad5b3 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Net; @@ -111,7 +112,8 @@ public static T GetController(long userId = 0, RouteData routeData = null, pa var requestHeaders = new HeaderDictionary(); var requestCookies = new MockRequestCookieCollection( - new Dictionary { + new Dictionary + { { "cookie_settings", JsonConvert.SerializeObject( @@ -350,7 +352,7 @@ public static GpgDatabaseContext CreateInMemoryTestDatabase(params object[] dbOb string testName = TestContext.CurrentContext.Test.FullName; if (string.IsNullOrWhiteSpace(testName)) { - testName = MethodBase.GetCurrentMethod().FindParentWithAttribute().Name; + testName = GetCurrentTestName(); } DbContextOptionsBuilder optionsBuilder = @@ -397,5 +399,32 @@ public static void AddMockUriHelperNew(this Controller controller, string url) controller.Url = mockUrlHelper.Object; } + public static string GetCurrentTestName() + { + return FindParentMethodWithTestAttribute(MethodBase.GetCurrentMethod()).Name; + } + + private static MethodBase FindParentMethodWithTestAttribute(MethodBase callingMethod) + { + // Iterate throught all attributes + StackFrame[] frames = new StackTrace().GetFrames(); + + for (int i = 1; i < frames.Length; i++) + { + StackFrame frame = frames[i]; + if (frame.HasMethod()) + { + MethodBase method = frame.GetMethod(); + + if (method.GetCustomAttribute() != null) + { + return method; + } + } + } + + return callingMethod; + } + } } diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs index 9fb4c03ae..562394224 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs @@ -4,6 +4,7 @@ using Autofac; using GenderPayGap.Database; using GenderPayGap.Extensions; +using GenderPayGap.WebUI.Tests.TestHelpers; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Moq; @@ -47,7 +48,7 @@ public static GpgDatabaseContext CreateInMemoryTestDatabase(params object[] dbOb string testName = TestContext.CurrentContext.Test.FullName; if (string.IsNullOrWhiteSpace(testName)) { - testName = MethodBase.GetCurrentMethod().FindParentWithAttribute().Name; + testName = UiTestHelper.GetCurrentTestName(); } DbContextOptionsBuilder optionsBuilder = From a0f5b6a18196ef3e3523eb659efd9bd0932f19e7 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 11:33:27 +0000 Subject: [PATCH 28/35] EHD-1411: Reduce code in Core project: Replace non-standard extension methods in Misc with standard C# code --- .../Extensions/AspNetCore/Config.cs | 44 +++- GenderPayGap.Core/Extensions/Encryption.cs | 73 +++++- GenderPayGap.Core/Extensions/Misc.cs | 235 ------------------ GenderPayGap.Core/Global.cs | 20 +- .../TestHelpers/UiTestHelpers.cs | 68 ----- .../Classes/Extensions/Extensions.cs | 2 +- .../Account/AccountCreationController.cs | 6 +- .../Helpers/FeatureFlagHelper.cs | 21 +- .../ReportStatusBadge.cshtml | 2 +- .../ReportOverview/ReportOverview.cshtml | 2 +- 10 files changed, 122 insertions(+), 351 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/Misc.cs diff --git a/GenderPayGap.Core/Extensions/AspNetCore/Config.cs b/GenderPayGap.Core/Extensions/AspNetCore/Config.cs index f95ba0748..26feffb08 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/Config.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/Config.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using System.Linq; using Microsoft.Extensions.Configuration; @@ -46,7 +47,7 @@ public static string EnvironmentName _EnvironmentName = Environment.GetEnvironmentVariable("Environment"); //This is used by webjobs SDK v3 } - if (string.IsNullOrWhiteSpace(_EnvironmentName) && Environment.GetEnvironmentVariable("DEV_ENVIRONMENT").ToBoolean()) + if (string.IsNullOrWhiteSpace(_EnvironmentName) && Environment.GetEnvironmentVariable("DEV_ENVIRONMENT") == "true") { _EnvironmentName = "Local"; } @@ -121,6 +122,47 @@ public static string GetAppSetting(string key, string defaultValue = null) return string.IsNullOrWhiteSpace(value) ? defaultValue : value; } + public static bool GetAppSettingBool(string key, bool defaultValue = false) + { + string settingValue = GetAppSetting(key); + + if (bool.TryParse(settingValue, out bool settingValueBool)) + { + return settingValueBool; + } + + return defaultValue; + } + + public static int GetAppSettingInt(string key, int defaultValue = 0) + { + string settingValue = GetAppSetting(key); + + if (int.TryParse(settingValue, out int settingValueInt)) + { + return settingValueInt; + } + + return defaultValue; + } + + public static DateTime GetAppSettingDateTime(string key) + { + string settingValue = GetAppSetting(key); + + if (DateTime.TryParseExact(settingValue, "yyMMddHHmmss", null, DateTimeStyles.AssumeLocal, out DateTime parsedValueShortFormat)) + { + return parsedValueShortFormat; + } + + if (DateTime.TryParse(settingValue, out DateTime parsedValueOtherFormat)) + { + return parsedValueOtherFormat; + } + + return DateTime.MinValue; + } + private static IConfiguration GetAppSettings() { IConfiguration appSettings = Configuration.GetSection("AppSettings"); diff --git a/GenderPayGap.Core/Extensions/Encryption.cs b/GenderPayGap.Core/Extensions/Encryption.cs index ad126c046..288b78f0a 100644 --- a/GenderPayGap.Core/Extensions/Encryption.cs +++ b/GenderPayGap.Core/Extensions/Encryption.cs @@ -18,7 +18,7 @@ public static class Encryption private static string DefaultEncryptionKey = "BA9138B8C0724F168A05482456802405"; - public static Encoding EncryptionEncoding = Encoding.UTF8; + private static Encoding EncryptionEncoding = Encoding.UTF8; public static void SetDefaultEncryptionKey(string defaultEncryptionKey) { @@ -114,12 +114,12 @@ private static byte[] CipherStreamWrite(ICryptoTransform cryptor, byte[] input) private static readonly byte[] PrimerBytes = {0, 0, 0, 0}; //Check the unencrypted data is delimited by the primer bytes - public static bool WasEncrypted(this byte[] bytes) + private static bool WasEncrypted(this byte[] bytes) { return bytes.IsWrapped(PrimerBytes, PrimerBytes); } - public static byte[] Encrypt(byte[] bytes, string password = null) + private static byte[] Encrypt(byte[] bytes, string password = null) { password = DefaultEncryptionKey + password; @@ -135,7 +135,7 @@ public static byte[] Encrypt(byte[] bytes, string password = null) return Compress(bytes); } - public static string Encrypt(string text, string password = null, bool base64Encode = true) + private static string Encrypt(string text, string password = null, bool base64Encode = true) { if (string.IsNullOrWhiteSpace(text)) { @@ -210,13 +210,13 @@ public static string EncryptModel(TModel model) #region AES-256 Decryption //[DebuggerStepThrough] - public static byte[] Decrypt(byte[] bytes, params string[] passwords) + private static byte[] Decrypt(byte[] bytes, params string[] passwords) { return Decrypt(bytes, new List(passwords)); } //[DebuggerStepThrough] - public static byte[] Decrypt(byte[] encryptedBytes, List passwords) + private static byte[] Decrypt(byte[] encryptedBytes, List passwords) { //Ensure the bytes are decompressed encryptedBytes = Decompress(encryptedBytes); @@ -293,7 +293,7 @@ private static bool DecryptBytes(byte[] encryptedBytes, List passwords, } [DebuggerStepThrough] - public static string Decrypt(string text, bool base64Encoded = true, params string[] passwords) + private static string Decrypt(string text, bool base64Encoded = true, params string[] passwords) { if (string.IsNullOrWhiteSpace(text)) { @@ -371,7 +371,7 @@ public static TModel DecryptModel(string encText) private static readonly byte[] GZipLevel10HeaderBytes = {0x1f, 0x8b, 8, 0, 0, 0, 0, 0, 2, 0}; private static readonly byte[] GZipLevel12HeaderBytes = {0x1f, 0x8b, 8, 0, 0, 0, 0, 0, 0, 11}; - public static bool IsCompressed(this byte[] bytes) + private static bool IsCompressed(this byte[] bytes) { if (bytes.Length <= 14) { @@ -399,7 +399,7 @@ public static bool IsCompressed(this byte[] bytes) ///
    /// The text. /// - public static byte[] Compress(byte[] buffer, bool mandatory = false) + private static byte[] Compress(byte[] buffer, bool mandatory = false) { using (var memoryStream = new MemoryStream()) { @@ -430,7 +430,7 @@ public static byte[] Compress(byte[] buffer, bool mandatory = false) ///
    /// The compressed text. /// - public static byte[] Decompress(byte[] gZipBuffer) + private static byte[] Decompress(byte[] gZipBuffer) { if (gZipBuffer == null || gZipBuffer.Length < 1 || !gZipBuffer.IsCompressed()) { @@ -458,7 +458,7 @@ public static byte[] Decompress(byte[] gZipBuffer) #region Public General Encryption Methods - public static bool IsEncryptedData(string data) + private static bool IsEncryptedData(string data) { if (string.IsNullOrWhiteSpace(data)) { @@ -468,7 +468,7 @@ public static bool IsEncryptedData(string data) return data.StartsWith("===") && data.EndsWith("==="); } - public static bool IsPrivateData(this string data, params string[] passwords) + private static bool IsPrivateData(this string data, params string[] passwords) { if (string.IsNullOrWhiteSpace(data)) { @@ -519,7 +519,7 @@ public static string DecryptData(string data) return DecryptData(data, out isPrivate); } - public static string DecryptData(string data, out bool isPrivate, params string[] passwords) + private static string DecryptData(string data, out bool isPrivate, params string[] passwords) { if (string.IsNullOrWhiteSpace(data)) { @@ -600,5 +600,52 @@ private static NameValueCollection FromQueryString(this string querystring) return string.IsNullOrWhiteSpace(querystring) ? null : HttpUtility.ParseQueryString(querystring); } + private static bool IsWrapped(this T[] data, T[] prefix, T[] suffix) + { + if (data.Length < prefix.Length + suffix.Length) + { + return false; + } + + T[] end = data.SubArray(0, prefix.Length); + + if (!end.SequenceEqual(prefix)) + { + return false; + } + + end = data.SubArray(data.Length - suffix.Length, suffix.Length); + + return end.SequenceEqual(suffix); + } + + private static T[] Wrap(this T[] data, T[] prefix, T[] suffix) + { + var result = new T[data.Length + prefix.Length + suffix.Length]; + Buffer.BlockCopy(prefix, 0, result, 0, prefix.Length); + Buffer.BlockCopy(data, 0, result, prefix.Length, data.Length); + Buffer.BlockCopy(suffix, 0, result, prefix.Length + data.Length, suffix.Length); + return result; + } + + private static T[] Strip(this T[] data, int left, int right) + { + var result = new T[data.Length - (left + right)]; + Buffer.BlockCopy(data, left, result, 0, result.Length); + return result; + } + + private static T[] SubArray(this T[] data, int index, int length) + { + if (length > data.Length) + { + length = data.Length; + } + + var result = new T[length]; + Buffer.BlockCopy(data, index, result, 0, length); + return result; + } + } } diff --git a/GenderPayGap.Core/Extensions/Misc.cs b/GenderPayGap.Core/Extensions/Misc.cs deleted file mode 100644 index f8c4b4198..000000000 --- a/GenderPayGap.Core/Extensions/Misc.cs +++ /dev/null @@ -1,235 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Reflection; - -namespace GenderPayGap.Extensions -{ - public static class Misc - { - - public static bool IsNull(this object item) - { - if (item == null || System.Convert.IsDBNull(item)) - { - return true; - } - - return false; - } - - public static bool IsWrapped(this T[] data, T[] prefix, T[] suffix) - { - if (data.Length < prefix.Length + suffix.Length) - { - return false; - } - - T[] end = data.SubArray(0, prefix.Length); - - if (!end.SequenceEqual(prefix)) - { - return false; - } - - end = data.SubArray(data.Length - suffix.Length, suffix.Length); - - return end.SequenceEqual(suffix); - } - - public static T[] Wrap(this T[] data, T[] prefix, T[] suffix) - { - var result = new T[data.Length + prefix.Length + suffix.Length]; - Buffer.BlockCopy(prefix, 0, result, 0, prefix.Length); - Buffer.BlockCopy(data, 0, result, prefix.Length, data.Length); - Buffer.BlockCopy(suffix, 0, result, prefix.Length + data.Length, suffix.Length); - return result; - } - - public static T[] Strip(this T[] data, int left, int right) - { - var result = new T[data.Length - (left + right)]; - Buffer.BlockCopy(data, left, result, 0, result.Length); - return result; - } - - public static T[] SubArray(this T[] data, int index, int length) - { - if (length > data.Length) - { - length = data.Length; - } - - var result = new T[length]; - Buffer.BlockCopy(data, index, result, 0, length); - return result; - } - - public static bool IsAny(this object item, params object[] values) - { - if (item == null && values.Contains(null)) - { - return true; - } - - foreach (object value in values) - { - if (item.Equals(value)) - { - return true; - } - } - - return false; - } - - public static bool IsAny(this char text, params char[] chars) - { - foreach (char ch in chars) - { - if (text.Equals(ch)) - { - return true; - } - } - - return false; - } - - public static bool ToBoolean(this object text, bool defaultValue = false) - { - if (text.IsNull()) - { - return defaultValue; - } - - if (text is bool) - { - return (bool) text; - } - - string str = System.Convert.ToString(text); - if (!string.IsNullOrWhiteSpace(str)) - { - if (str.EqualsI("1", "yes")) - { - return true; - } - - if (str.EqualsI("0", "no")) - { - return false; - } - - bool parsedValue; - if (bool.TryParse(str, out parsedValue)) - { - return parsedValue; - } - } - - return defaultValue; - } - - public static int ToInt32(this object text, int defaultValue = 0) - { - if (text.IsNull()) - { - return defaultValue; - } - - if (text is decimal || text is double || text is int || text is long || text is byte || text.GetType().IsEnum) - { - return System.Convert.ToInt32(text); - } - - string str = System.Convert.ToString(text); - int parsedValue; - if (!string.IsNullOrWhiteSpace(str) && int.TryParse(str, out parsedValue)) - { - return parsedValue; - } - - return defaultValue; - } - - public static long ToInt64(this object text, long defaultValue = 0) - { - if (text.IsNull()) - { - return defaultValue; - } - - if (text is decimal || text is double || text is int || text is long || text is byte || text.GetType().IsEnum) - { - return System.Convert.ToInt64(text); - } - - string str = System.Convert.ToString(text); - long parsedValue; - if (!string.IsNullOrWhiteSpace(str) && long.TryParse(str, out parsedValue)) - { - return parsedValue; - } - - return defaultValue; - } - - public static string ToStringOrNull(this object text) - { - string result = null; - if (text is string) - { - result = (string) text; - } - else if (!text.IsNull()) - { - result = System.Convert.ToString(text); - } - - return string.IsNullOrWhiteSpace(result) ? null : result; - } - - public static DateTime ToDateTime(this object text) - { - if (text.IsNull()) - { - return DateTime.MinValue; - } - - if (text is DateTime) - { - return (DateTime) text; - } - - string str = System.Convert.ToString(text); - if (!string.IsNullOrWhiteSpace(str)) - { - string shortDateFormat = "yyMMddHHmmss"; - - DateTime parsedValue; - if (DateTime.TryParseExact(str, shortDateFormat, null, DateTimeStyles.AssumeLocal, out parsedValue)) - { - return parsedValue; - } - - if (DateTime.TryParseExact(str, shortDateFormat, null, DateTimeStyles.AssumeLocal, out parsedValue)) - { - return parsedValue; - } - - if (DateTime.TryParse(str, out parsedValue)) - { - return parsedValue; - } - } - - return DateTime.MinValue; - } - - } -} diff --git a/GenderPayGap.Core/Global.cs b/GenderPayGap.Core/Global.cs index 889279b77..5e5647109 100644 --- a/GenderPayGap.Core/Global.cs +++ b/GenderPayGap.Core/Global.cs @@ -41,8 +41,8 @@ public static class Global #region Settings that we expect to want to update at short notice - public static bool MaintenanceMode => Config.GetAppSetting("MaintenanceMode").ToBoolean(false); - public static DateTime? MaintenanceModeUpAgainTime => Config.GetAppSetting("MaintenanceModeUpAgainTime")?.ToDateTime(); + public static bool MaintenanceMode => Config.GetAppSettingBool("MaintenanceMode", defaultValue: false); + public static DateTime? MaintenanceModeUpAgainTime => Config.GetAppSettingDateTime("MaintenanceModeUpAgainTime"); public static List ReportingStartYearsToExcludeFromLateFlagEnforcement => LoadListOfIntegers("ReportingStartYearsToExcludeFromLateFlagEnforcement"); public static List ReportingStartYearsWithFurloughScheme => @@ -50,27 +50,27 @@ public static class Global public static string ReminderEmailDays => Config.GetAppSetting("ReminderEmailDays"); public static bool EnableSubmitAlerts { - get => Config.GetAppSetting("EnableSubmitAlerts").ToBoolean(false); + get => Config.GetAppSettingBool("EnableSubmitAlerts", defaultValue: false); set => Config.SetAppSetting("EnableSubmitAlerts", value.ToString()); } - public static bool DisableSearchCache => Config.GetAppSetting("DisableSearchCache").ToBoolean(); + public static bool DisableSearchCache => Config.GetAppSettingBool("DisableSearchCache"); #endregion #region Settings that only change per environment - public static bool SendGoogleAnalyticsDataToGovUk => Config.GetAppSetting("SendGoogleAnalyticsDataToGovUk").ToBoolean(); - public static int MaxNumCallsCompaniesHouseApiPerFiveMins => Config.GetAppSetting("MaxNumCallsCompaniesHouseApiPerFiveMins").ToInt32(10); + public static bool SendGoogleAnalyticsDataToGovUk => Config.GetAppSettingBool("SendGoogleAnalyticsDataToGovUk"); + public static int MaxNumCallsCompaniesHouseApiPerFiveMins => Config.GetAppSettingInt("MaxNumCallsCompaniesHouseApiPerFiveMins", defaultValue: 10); public static string GoogleAnalyticsAccountId => Config.GetAppSetting("GoogleAnalyticsAccountId"); public static List GeoDistributionList => Config.GetAppSetting("GEODistributionList").Split(";", StringSplitOptions.RemoveEmptyEntries).ToList(); - public static TimeSpan TimeToKeepBackupFiles => TimeSpan.FromDays(Config.GetAppSetting("DaysToKeepBackupFiles").ToInt32(35)); - public static bool LogToSentry => Config.GetAppSetting("LogToSentry").ToBoolean(defaultValue: false); + public static TimeSpan TimeToKeepBackupFiles => TimeSpan.FromDays(Config.GetAppSettingInt("DaysToKeepBackupFiles", defaultValue: 35)); + public static bool LogToSentry => Config.GetAppSettingBool("LogToSentry", defaultValue: false); #endregion #region Settings that change per deployment slot - public static bool BackgroundJobsEnabled => Config.GetAppSetting("WEBJOBS_STOPPED").ToInt32(0) == 0; + public static bool BackgroundJobsEnabled => Config.GetAppSettingInt("WEBJOBS_STOPPED", defaultValue: 0) == 0; #endregion @@ -103,7 +103,7 @@ public static bool EnableSubmitAlerts public static int MinIOThreads => 300; public static int MinWorkerThreads => 300; public static string StartUrl => - Config.GetAppSetting("UseStartUrl").ToBoolean() + Config.GetAppSettingBool("UseStartUrl") ? "https://www.gov.uk/report-gender-pay-gap-data" : null; public static string DoneUrl => "https://www.gov.uk/done/report-gender-pay-gap-data"; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs index 583aad5b3..b0d0af441 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs @@ -257,68 +257,6 @@ public static IContainer BuildContainerIoC(params object[] dbObjects) return container; } - public static void Bind(this Controller controller, object Model) - { - var validationContext = new ValidationContext(Model, null, null); - var validationResults = new List(); - Validator.TryValidateObject(Model, validationContext, validationResults, true); - foreach (ValidationResult validationResult in validationResults) - { - controller.ModelState.AddModelError(string.Join(", ", validationResult.MemberNames), validationResult.ErrorMessage); - } - } - - /// - /// Adds a new mock url to the action method of an existing or new Mock URl helper of the controller - /// - /// The source controller to add the mock setup - /// The url to be returned by the Action method - /// The name of the action to mock. If null tries to get from Controller.RoutData. - /// - /// The name of the action to mock. If null tries to get from Controller.RoutData, then uses - /// the Controller name. - /// - public static void AddMockUriHelper(this Controller controller, string url, string actionName = null, string controllerName = null) - { - actionName = actionName ?? controller.RouteData?.Values["Action"].ToStringOrNull(); - if (string.IsNullOrWhiteSpace(actionName)) - { - throw new ArgumentNullException(nameof(actionName)); - } - - controllerName = controllerName ?? controller.RouteData?.Values["Controller"].ToStringOrNull(); - if (string.IsNullOrWhiteSpace(controllerName)) - { - controllerName = controller.GetType().Name; - } - - if (string.IsNullOrWhiteSpace(controllerName)) - { - throw new ArgumentNullException(nameof(controllerName)); - } - - if (controllerName != null) - { - controllerName = controllerName.Replace("Controller", ""); - } - - var uri = new Uri(url); - if (uri.Authority.EqualsI(Uri.Authority)) - { - url = uri.PathAndQuery; - } - - Mock mockUrlHelper = controller.Url?.GetMockFromObject() ?? new Mock(); - Expression> urlSetup = helper => helper.Action( - It.Is( - uac => (string.IsNullOrWhiteSpace(actionName) || uac.Action == actionName) - && (string.IsNullOrWhiteSpace(controllerName) || uac.Controller == controllerName || uac.Controller == null))); - - mockUrlHelper.Setup(urlSetup).Returns(url).Verifiable(); - - controller.Url = mockUrlHelper.Object; - } - public static void AssertCookieAdded(this Controller controller, string key, string value) { Mock mockCookies = Mock.Get(controller.HttpContext.Response.Cookies); @@ -328,12 +266,6 @@ public static void AssertCookieAdded(this Controller controller, string key, str $"The cookie '{key}' was not saved with value '{value}'"); } - public static void AssertCookieDeleted(this Controller controller, string key) - { - Mock mockCookies = Mock.Get(controller.HttpContext.Response.Cookies); - mockCookies.Verify(c => c.Delete(key), Times.Once(), $"The cookie '{key}' was not deleted"); - } - /// /// Registers an InMemory SQLRespository and populates with entities diff --git a/GenderPayGap.WebUI/Classes/Extensions/Extensions.cs b/GenderPayGap.WebUI/Classes/Extensions/Extensions.cs index c646c74ff..aa07d2c83 100644 --- a/GenderPayGap.WebUI/Classes/Extensions/Extensions.cs +++ b/GenderPayGap.WebUI/Classes/Extensions/Extensions.cs @@ -36,7 +36,7 @@ public static bool DecryptToId(this string enc, out long decId) long id; try { - id = Encryption.DecryptQuerystring(enc).ToInt64(); + id = long.Parse(Encryption.DecryptQuerystring(enc)); } catch (Exception e) { diff --git a/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs b/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs index 23b2d7085..34fa3138a 100644 --- a/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs +++ b/GenderPayGap.WebUI/Controllers/Account/AccountCreationController.cs @@ -119,7 +119,7 @@ public IActionResult CreateUserAccountPost(CreateUserAccountViewModel viewModel) var user = CreateNewOrUpdateRetiredUser(viewModel, retiredUser); - if (retiredUser.IsNull()) + if (retiredUser == null) { dataRepository.Insert(user); } @@ -167,8 +167,8 @@ private User CreateNewOrUpdateRetiredUser(CreateUserAccountViewModel viewModel, // If user creates a new account with same email address as retired account, reuse the old // account to avoid duplicates, add status change details and update all info except created date. var user = retiredUser ?? new User(); - var createdDate = retiredUser.IsNull() ? currentTime : retiredUser.Created; - var statusDetails = retiredUser.IsNull() ? null : "Retired user account has been reactivated"; + var createdDate = retiredUser == null ? currentTime : retiredUser.Created; + var statusDetails = retiredUser == null ? null : "Retired user account has been reactivated"; user.Created = createdDate; user.Modified = currentTime; diff --git a/GenderPayGap.WebUI/Helpers/FeatureFlagHelper.cs b/GenderPayGap.WebUI/Helpers/FeatureFlagHelper.cs index b628884ce..759d01094 100644 --- a/GenderPayGap.WebUI/Helpers/FeatureFlagHelper.cs +++ b/GenderPayGap.WebUI/Helpers/FeatureFlagHelper.cs @@ -1,30 +1,15 @@ -using GenderPayGap.Extensions; -using GenderPayGap.Extensions.AspNetCore; +using GenderPayGap.Extensions.AspNetCore; namespace GenderPayGap.WebUI.Helpers { public static class FeatureFlagHelper { public static bool IsFeatureEnabled(FeatureFlag featureFlag) - { - bool? flagValue = GetFeatureFlagValue(featureFlag); - - return flagValue.HasValue && flagValue.Value; - } - - public static bool? GetFeatureFlagValue(FeatureFlag featureFlag) { string appSettingName = $"FeatureFlag{featureFlag}"; - - string appSettingValue = Config.GetAppSetting(appSettingName); - - if (string.IsNullOrEmpty(appSettingValue)) - { - return null; - } - - return appSettingValue.ToBoolean(); + return Config.GetAppSettingBool(appSettingName, defaultValue: false); } + } public enum FeatureFlag diff --git a/GenderPayGap.WebUI/Views/ManageOrganisations/ReportStatusBadge.cshtml b/GenderPayGap.WebUI/Views/ManageOrganisations/ReportStatusBadge.cshtml index 57526ac14..6f443a183 100644 --- a/GenderPayGap.WebUI/Views/ManageOrganisations/ReportStatusBadge.cshtml +++ b/GenderPayGap.WebUI/Views/ManageOrganisations/ReportStatusBadge.cshtml @@ -44,7 +44,7 @@ reportTagColour = "govuk-tag--blue"; break; case ReportStatusTag.Overdue: - int daysOverdue = VirtualDateTime.Now.Date.Subtract(Model.DeadlineDate).TotalDays.ToInt32(); + int daysOverdue = (int)(VirtualDateTime.Now.Date.Subtract(Model.DeadlineDate).TotalDays); reportTagHtml = @ @(daysOverdue) @(daysOverdue == 1 ? "day" : "days") diff --git a/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml b/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml index 203296a08..0f10dcb19 100644 --- a/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml +++ b/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml @@ -247,7 +247,7 @@ Model.SectorType == SectorTypes.Private ? personResponsibleSection : null, employeeHeadcountSection, linkToGenderPayGapInformationSection - }.Where(s => !s.IsNull()).ToList() + }.Where(s => s != null).ToList() }; await Html.RenderPartialAsync("../Components/ReportOverview/ReportOverviewSections", reportOverviewSections); From cc7320b403468d63f7c2944f904d44fc53449442 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 11:39:13 +0000 Subject: [PATCH 29/35] EHD-1411: Reduce code in Core project: Replace use of extension methods --- .../Classes/Extensions/Extensions.cs | 58 ------------------- .../Helpers/ControllerHelper.cs | 32 +++++++++- GenderPayGap.WebUI/Startup.cs | 18 +++++- 3 files changed, 47 insertions(+), 61 deletions(-) delete mode 100644 GenderPayGap.WebUI/Classes/Extensions/Extensions.cs diff --git a/GenderPayGap.WebUI/Classes/Extensions/Extensions.cs b/GenderPayGap.WebUI/Classes/Extensions/Extensions.cs deleted file mode 100644 index aa07d2c83..000000000 --- a/GenderPayGap.WebUI/Classes/Extensions/Extensions.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Linq; -using GenderPayGap.Extensions; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; - -namespace GenderPayGap.WebUI.Classes -{ - public static class Extensions - { - - public static void AddStringTrimmingProvider(this MvcOptions option) - { - IModelBinderProvider binderToFind = - option.ModelBinderProviders.FirstOrDefault(x => x.GetType() == typeof(SimpleTypeModelBinderProvider)); - if (binderToFind == null) - { - return; - } - - int index = option.ModelBinderProviders.IndexOf(binderToFind); - option.ModelBinderProviders.Insert(index, new TrimmingModelBinderProvider()); - } - - #region Encypt Decrypt - - public static bool DecryptToId(this string enc, out long decId) - { - decId = 0; - if (string.IsNullOrWhiteSpace(enc)) - { - return false; - } - - long id; - try - { - id = long.Parse(Encryption.DecryptQuerystring(enc)); - } - catch (Exception e) - { - return false; - } - - if (id <= 0) - { - return false; - } - - decId = id; - return true; - } - - #endregion - - } -} diff --git a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs index d06047145..947dae2ac 100644 --- a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs +++ b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs @@ -5,6 +5,7 @@ using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; +using GenderPayGap.Extensions; using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.ErrorHandling; using Microsoft.AspNetCore.Mvc; @@ -133,7 +134,7 @@ public static void ThrowIfUserIsNotAwaitingPinInThePostForGivenOrganisation(Clai public static long DecryptOrganisationIdOrThrow404(string encryptedOrganisationId) { - if (!encryptedOrganisationId.DecryptToId(out long organisationId)) + if (!DecryptToId(encryptedOrganisationId, out long organisationId)) { throw new PageNotFoundException(); } @@ -163,7 +164,7 @@ public static void Throw404IfOrganisationIsNotSearchable(Organisation organisati public static long DecryptUserIdOrThrow404(string encryptedUserId) { - if (!encryptedUserId.DecryptToId(out long userId)) + if (!DecryptToId(encryptedUserId, out long userId)) { throw new PageNotFoundException(); } @@ -234,5 +235,32 @@ public static void RedirectIfUserNeedsToReadPrivacyPolicy(ClaimsPrincipal aspDot } } + private static bool DecryptToId(string encryptedId, out long decryptedId) + { + decryptedId = 0; + if (string.IsNullOrWhiteSpace(encryptedId)) + { + return false; + } + + long id; + try + { + id = long.Parse(Encryption.DecryptQuerystring(encryptedId)); + } + catch (Exception e) + { + return false; + } + + if (id <= 0) + { + return false; + } + + decryptedId = id; + return true; + } + } } diff --git a/GenderPayGap.WebUI/Startup.cs b/GenderPayGap.WebUI/Startup.cs index f8a7cd8c3..48f69ef64 100644 --- a/GenderPayGap.WebUI/Startup.cs +++ b/GenderPayGap.WebUI/Startup.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Net.Http; using Autofac; using Autofac.Extensions.DependencyInjection; @@ -29,6 +30,8 @@ using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.DependencyInjection; @@ -76,7 +79,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services) services.AddControllersWithViews( options => { - options.AddStringTrimmingProvider(); //Add modelstate binder to trim input + AddStringTrimmingProvider(options); //Add modelstate binder to trim input options.ModelMetadataDetailsProviders.Add( new TrimModelBinder()); //Set DisplayMetadata to input empty strings as null options.Filters.Add(); @@ -329,5 +332,18 @@ public void Configure(IApplicationBuilder app, IApplicationLifetime lifetime) }); } + private static void AddStringTrimmingProvider(MvcOptions option) + { + IModelBinderProvider binderToFind = + option.ModelBinderProviders.FirstOrDefault(x => x.GetType() == typeof(SimpleTypeModelBinderProvider)); + if (binderToFind == null) + { + return; + } + + int index = option.ModelBinderProviders.IndexOf(binderToFind); + option.ModelBinderProviders.Insert(index, new TrimmingModelBinderProvider()); + } + } } From 0aee7d98041ac82e9c069ae53bd2c3c70052331d Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 11:49:50 +0000 Subject: [PATCH 30/35] EHD-1411: Reduce code in Core project: Replace non-standard extension methods in Text with standard C# code --- .../Extensions/AspNetCore/Config.cs | 2 +- GenderPayGap.Core/Extensions/Encryption.cs | 28 +++- GenderPayGap.Core/Extensions/EventLog.cs | 4 +- GenderPayGap.Core/Extensions/Text.cs | 124 ------------------ .../Models/Extensions/OrganisationAddress.cs | 16 +-- .../Models/Extensions/User.cs | 2 +- .../Classes/GoogleAnalyticsTracker.cs | 4 +- .../CompaniesHouse/CompaniesHouseAPI.cs | 13 +- .../Helpers/MaintenancePageMiddleware.cs | 5 +- .../Repositories/UserRepository.cs | 4 +- 10 files changed, 57 insertions(+), 145 deletions(-) delete mode 100644 GenderPayGap.Core/Extensions/Text.cs diff --git a/GenderPayGap.Core/Extensions/AspNetCore/Config.cs b/GenderPayGap.Core/Extensions/AspNetCore/Config.cs index 26feffb08..822e931b5 100644 --- a/GenderPayGap.Core/Extensions/AspNetCore/Config.cs +++ b/GenderPayGap.Core/Extensions/AspNetCore/Config.cs @@ -105,7 +105,7 @@ public static bool IsEnvironment(params string[] environmentNames) { foreach (string environmentName in environmentNames) { - if (EnvironmentName.EqualsI(environmentName)) + if (EnvironmentName.Equals(environmentName, StringComparison.InvariantCultureIgnoreCase)) { return true; } diff --git a/GenderPayGap.Core/Extensions/Encryption.cs b/GenderPayGap.Core/Extensions/Encryption.cs index 288b78f0a..d1d43499f 100644 --- a/GenderPayGap.Core/Extensions/Encryption.cs +++ b/GenderPayGap.Core/Extensions/Encryption.cs @@ -480,12 +480,12 @@ private static bool IsPrivateData(this string data, params string[] passwords) data = Decrypt(data.Substring(3, data.Length - 6), true, passwords); } - if (data.StartsWithI("##mkPrivatePassword:")) + if (data.StartsWith("##mkPrivatePassword:", StringComparison.InvariantCultureIgnoreCase)) { return true; } - if (data.StartsWithI("mkRecipientPassword:")) + if (data.StartsWith("mkRecipientPassword:", StringComparison.InvariantCultureIgnoreCase)) { return true; } @@ -647,5 +647,29 @@ private static T[] SubArray(this T[] data, int index, int length) return result; } + private static string EncodeUrlBase64(this string base64String) + { + if (!string.IsNullOrWhiteSpace(base64String)) + { + base64String = base64String.Replace('+', '-'); + base64String = base64String.Replace('/', '_'); + base64String = base64String.Replace('=', '!'); + } + + return base64String; + } + + private static string DecodeUrlBase64(this string base64String) + { + if (!string.IsNullOrWhiteSpace(base64String)) + { + base64String = base64String.Replace('-', '+'); + base64String = base64String.Replace('_', '/'); + base64String = base64String.Replace('!', '='); + } + + return base64String; + } + } } diff --git a/GenderPayGap.Core/Extensions/EventLog.cs b/GenderPayGap.Core/Extensions/EventLog.cs index 5177935fd..360bcb8e8 100644 --- a/GenderPayGap.Core/Extensions/EventLog.cs +++ b/GenderPayGap.Core/Extensions/EventLog.cs @@ -44,7 +44,7 @@ public static Assembly TopAssembly for (int i = stackFrames.Length - 1; i > -1; i--) { _TopAssembly = stackFrames[i].GetMethod().ReflectedType.Assembly; - if (_TopAssembly.GetName() != null && _TopAssembly.GetName().Name.ContainsI(LogName)) + if (_TopAssembly.GetName() != null && _TopAssembly.GetName().Name.Contains(LogName)) { break; } @@ -54,7 +54,7 @@ public static Assembly TopAssembly if (((AssemblyCompanyAttribute) Attribute.GetCustomAttribute( _TopAssembly, typeof(AssemblyCompanyAttribute), - false)).Company.ContainsI(LogName)) + false)).Company.Contains(LogName)) { break; } diff --git a/GenderPayGap.Core/Extensions/Text.cs b/GenderPayGap.Core/Extensions/Text.cs deleted file mode 100644 index 51656b70e..000000000 --- a/GenderPayGap.Core/Extensions/Text.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Linq; -using System.Text.RegularExpressions; - -namespace GenderPayGap.Extensions -{ - public static class Text - { - - public static bool IsNumber(this string input) - { - if (string.IsNullOrWhiteSpace(input)) - { - return false; - } - - return Regex.IsMatch(input, "^\\d+$"); - } - - public static bool IsNullOrWhiteSpace(this string input, params string[] inputs) - { - if (string.IsNullOrWhiteSpace(input)) - { - return true; - } - - if (inputs.Any(i => string.IsNullOrWhiteSpace(i))) - { - return true; - } - - return false; - } - - public static string TrimI(this string source, params char[] trimChars) - { - if (string.IsNullOrEmpty(source)) - { - return source; - } - - return trimChars == null || trimChars.Length == 0 ? source.Trim() : source.Trim(trimChars); - } - - public static bool EqualsI(this string original, params string[] target) - { - if (string.IsNullOrWhiteSpace(original)) - { - original = ""; - } - - for (var i = 0; i < target.Length; i++) - { - if (string.IsNullOrWhiteSpace(target[i])) - { - target[i] = ""; - } - - if (original.Equals(target[i], StringComparison.InvariantCultureIgnoreCase)) - { - return true; - } - } - - return false; - } - - public static bool ContainsI(this string source, string pattern) - { - if (string.IsNullOrWhiteSpace(source) || string.IsNullOrEmpty(pattern)) - { - return false; - } - - return source.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0; - } - - public static bool StartsWithI(this string original, params string[] texts) - { - if (string.IsNullOrWhiteSpace(original)) - { - return false; - } - - if (texts != null) - { - foreach (string text in texts) - { - if (text != null && original.ToLower().StartsWith(text.ToLower())) - { - return true; - } - } - } - - return false; - } - - public static string EncodeUrlBase64(this string base64String) - { - if (!string.IsNullOrWhiteSpace(base64String)) - { - base64String = base64String.Replace('+', '-'); - base64String = base64String.Replace('/', '_'); - base64String = base64String.Replace('=', '!'); - } - - return base64String; - } - - public static string DecodeUrlBase64(this string base64String) - { - if (!string.IsNullOrWhiteSpace(base64String)) - { - base64String = base64String.Replace('-', '+'); - base64String = base64String.Replace('_', '/'); - base64String = base64String.Replace('!', '='); - } - - return base64String; - } - - } -} diff --git a/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs b/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs index 09b5bbf9e..4d554c872 100644 --- a/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs +++ b/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs @@ -16,42 +16,42 @@ public static List GetAddressLines(this OrganisationAddress address) if (!string.IsNullOrWhiteSpace(address.Address1)) { - list.Add(address.Address1.TrimI()); + list.Add(address.Address1.Trim()); } if (!string.IsNullOrWhiteSpace(address.Address2)) { - list.Add(address.Address2.TrimI()); + list.Add(address.Address2.Trim()); } if (!string.IsNullOrWhiteSpace(address.Address3)) { - list.Add(address.Address3.TrimI()); + list.Add(address.Address3.Trim()); } if (!string.IsNullOrWhiteSpace(address.TownCity)) { - list.Add(address.TownCity.TrimI()); + list.Add(address.TownCity.Trim()); } if (!string.IsNullOrWhiteSpace(address.County)) { - list.Add(address.County.TrimI()); + list.Add(address.County.Trim()); } if (!string.IsNullOrWhiteSpace(address.Country)) { - list.Add(address.Country.TrimI()); + list.Add(address.Country.Trim()); } if (!string.IsNullOrWhiteSpace(address.GetPostCodeInAllCaps())) { - list.Add(address.GetPostCodeInAllCaps().TrimI()); + list.Add(address.GetPostCodeInAllCaps().Trim()); } if (!string.IsNullOrWhiteSpace(address.PoBox)) { - list.Add(address.PoBox.TrimI()); + list.Add(address.PoBox.Trim()); } return list; diff --git a/GenderPayGap.Database/Models/Extensions/User.cs b/GenderPayGap.Database/Models/Extensions/User.cs index 6bccf4429..27c039131 100644 --- a/GenderPayGap.Database/Models/Extensions/User.cs +++ b/GenderPayGap.Database/Models/Extensions/User.cs @@ -73,7 +73,7 @@ public string NewEmailAddress } [NotMapped] - public string Fullname => (Firstname + " " + Lastname).TrimI(); + public string Fullname => (Firstname + " " + Lastname).Trim(); public bool IsFullAdministrator() { diff --git a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs index 79f05a16a..f80d4a6e9 100644 --- a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs +++ b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs @@ -126,7 +126,7 @@ private static bool IsUrl(string url) { try { - if (!url.StartsWithI("http:") && !url.StartsWithI("https:") && !url.StartsWithI("file:")) + if (!url.StartsWith("http:") && !url.StartsWith("https:") && !url.StartsWith("file:")) { return false; } @@ -147,7 +147,7 @@ private static string RelativeToAbsoluteUrl(string relativeUrl, Uri baseUrl) throw new ArgumentNullException(nameof(baseUrl)); } - if (relativeUrl.StartsWithI("http://", "https://")) + if (relativeUrl.StartsWith("http://") || relativeUrl.StartsWith("https://")) { return relativeUrl; } diff --git a/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs b/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs index edf9fd5cb..0d455953b 100644 --- a/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs +++ b/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Net; using System.Net.Http; +using System.Text.RegularExpressions; using GenderPayGap.Core; using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; @@ -37,7 +38,7 @@ public CompaniesHouseAPI(HttpClient httpClient) public CompaniesHouseCompany GetCompany(string companyNumber) { - if (companyNumber.IsNumber()) + if (IsDigits(companyNumber)) { companyNumber = companyNumber.PadLeft(8, '0'); } @@ -108,5 +109,15 @@ public static IAsyncPolicy GetRetryPolicy() TimeSpan.FromMilliseconds(new Random().Next(1, 1000)) + TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); } + private static bool IsDigits(string input) + { + if (string.IsNullOrWhiteSpace(input)) + { + return false; + } + + return Regex.IsMatch(input, "^\\d+$"); + } + } } diff --git a/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs b/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs index 42292d022..5943426e8 100644 --- a/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs +++ b/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using GenderPayGap.Extensions; using Microsoft.AspNetCore.Http; using HttpContext = Microsoft.AspNetCore.Http.HttpContext; @@ -27,7 +28,7 @@ public async Task Invoke(HttpContext httpContext) } // Redirect to holding page if in maintenance mode - if (_enabled && !httpContext.Request.Path.Value.StartsWithI(@"/error/service-unavailable")) + if (_enabled && !httpContext.Request.Path.Value.StartsWith(@"/error/service-unavailable", StringComparison.InvariantCultureIgnoreCase)) { httpContext.Response.Redirect(@"/error/service-unavailable", permanent: false); } diff --git a/GenderPayGap.WebUI/Repositories/UserRepository.cs b/GenderPayGap.WebUI/Repositories/UserRepository.cs index 42791efac..0a2d976d4 100644 --- a/GenderPayGap.WebUI/Repositories/UserRepository.cs +++ b/GenderPayGap.WebUI/Repositories/UserRepository.cs @@ -72,7 +72,7 @@ public void UpdateEmail(User userToUpdate, string newEmailAddress) throw new ArgumentNullException(nameof(userToUpdate)); } - if (newEmailAddress.IsNullOrWhiteSpace()) + if (string.IsNullOrWhiteSpace(newEmailAddress)) { throw new ArgumentNullException(nameof(newEmailAddress)); } @@ -112,7 +112,7 @@ public void UpdatePassword(User userToUpdate, string newPassword) throw new ArgumentNullException(nameof(userToUpdate)); } - if (newPassword.IsNullOrWhiteSpace()) + if (string.IsNullOrWhiteSpace(newPassword)) { throw new ArgumentNullException(nameof(newPassword)); } From 5d771eaf7b251499fbb0fd1aa317f18ec80b5b44 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 12:07:15 +0000 Subject: [PATCH 31/35] EHD-1411: Reduce code in Core project: Remove some unused using statements --- GenderPayGap.Core/Global.cs | 1 - .../Models/Extensions/OrganisationAddress.cs | 1 - GenderPayGap.Database/Models/PublicSectorType.cs | 1 - GenderPayGap.Database/Models/SicCode.cs | 4 +--- GenderPayGap.Database/Models/SicSection.cs | 4 +--- .../GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs | 3 --- .../Controllers/Account/AccountCreationTests.cs | 4 ---- .../Controllers/Account/CloseAccountTests.cs | 5 +---- .../Controllers/Scope/ScopeControllerTests.cs | 4 +--- .../GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs | 4 ---- .../GenderPayGap.WebUI.Tests/TestHelpers/UserHelper.cs | 2 -- .../TestsCommon/Classes/AutoFacHelpers.cs | 2 -- GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs | 1 - .../Classes/Presentation/CompareViewService.cs | 1 - .../Controllers/Account/ChangePersonalDetailsController.cs | 1 - .../Controllers/Account/ManageAccountController.cs | 3 +-- .../AddOrganisationConfirmationController.cs | 1 - .../AddOrganisationManualConfirmController.cs | 2 -- .../Controllers/Admin/AdminDataMigrationController.cs | 1 - .../Controllers/Admin/AdminOrganisationScopeController.cs | 3 --- .../Controllers/Admin/AdminOrganisationSectorController.cs | 3 --- .../Admin/AdminOrganisationSicCodesController.cs | 1 - .../Controllers/Admin/AdminReferenceDataController.cs | 1 - .../Admin/AdminUserResendVerificationEmailController.cs | 1 - GenderPayGap.WebUI/Controllers/ScopeController.cs | 3 --- .../Controllers/SendFeedback/FeedbackController.cs | 1 - .../ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs | 2 -- .../FileRepositories/SystemFileRepository.cs | 2 -- GenderPayGap.WebUI/Helpers/ControllerHelper.cs | 1 - GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs | 1 - GenderPayGap.WebUI/Models/Report/ReportOverviewViewModel.cs | 6 ------ GenderPayGap.WebUI/Services/ReturnService.cs | 1 - 32 files changed, 5 insertions(+), 66 deletions(-) diff --git a/GenderPayGap.Core/Global.cs b/GenderPayGap.Core/Global.cs index 5e5647109..a5a530dbc 100644 --- a/GenderPayGap.Core/Global.cs +++ b/GenderPayGap.Core/Global.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; using Newtonsoft.Json; diff --git a/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs b/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs index 4d554c872..351b5da67 100644 --- a/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs +++ b/GenderPayGap.Database/Models/Extensions/OrganisationAddress.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using GenderPayGap.Extensions; namespace GenderPayGap.Database { diff --git a/GenderPayGap.Database/Models/PublicSectorType.cs b/GenderPayGap.Database/Models/PublicSectorType.cs index c6531c9b5..687c7378c 100644 --- a/GenderPayGap.Database/Models/PublicSectorType.cs +++ b/GenderPayGap.Database/Models/PublicSectorType.cs @@ -1,5 +1,4 @@ using System; -using GenderPayGap.Extensions; using Newtonsoft.Json; namespace GenderPayGap.Database diff --git a/GenderPayGap.Database/Models/SicCode.cs b/GenderPayGap.Database/Models/SicCode.cs index c1832a431..0e7c114a3 100644 --- a/GenderPayGap.Database/Models/SicCode.cs +++ b/GenderPayGap.Database/Models/SicCode.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using GenderPayGap.Extensions; +using System.Collections.Generic; using Newtonsoft.Json; namespace GenderPayGap.Database diff --git a/GenderPayGap.Database/Models/SicSection.cs b/GenderPayGap.Database/Models/SicSection.cs index 921c4da79..71cc24096 100644 --- a/GenderPayGap.Database/Models/SicSection.cs +++ b/GenderPayGap.Database/Models/SicSection.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using GenderPayGap.Extensions; +using System.Collections.Generic; using Newtonsoft.Json; namespace GenderPayGap.Database diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs index a8d6d584d..a3a103a11 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Builders/ControllerBuilder.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Security.Claims; using Autofac; using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; -using GenderPayGap.Extensions; -using GenderPayGap.Tests.Common.TestHelpers; using GenderPayGap.WebUI.BackgroundJobs; using GenderPayGap.WebUI.BusinessLogic.Abstractions; using GenderPayGap.WebUI.Cookies; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs index 855aa9aeb..ab981a484 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using GenderPayGap.Core; using GenderPayGap.Database; using GenderPayGap.Extensions; @@ -8,10 +7,7 @@ using GenderPayGap.WebUI.Models.AccountCreation; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; -using GenderPayGap.WebUI.Tests.TestHelpers; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Primitives; -using Moq; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.Account diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs index a7474c166..cadd103e9 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs @@ -1,15 +1,12 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using GenderPayGap.Core; using GenderPayGap.Database; using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; -using GenderPayGap.WebUI.Controllers.Account; using GenderPayGap.WebUI.ExternalServices; using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; -using Microsoft.Extensions.Primitives; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.Account diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs index 4672ff33c..be174439f 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs @@ -1,11 +1,9 @@ -using System.Collections.Generic; -using GenderPayGap.Core; +using GenderPayGap.Core; using GenderPayGap.Database; using GenderPayGap.Extensions; using GenderPayGap.WebUI.Controllers; using GenderPayGap.WebUI.Models.ScopeNew; using GenderPayGap.WebUI.Tests.Builders; -using Microsoft.Extensions.Primitives; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.Scope diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs index b0d0af441..9678d918c 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Linq; -using System.Linq.Expressions; using System.Net; using System.Reflection; using System.Security.Claims; @@ -11,7 +9,6 @@ using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; -using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; using GenderPayGap.Tests.Common.Classes; using GenderPayGap.Tests.Common.TestHelpers; @@ -43,7 +40,6 @@ using Moq; using Newtonsoft.Json; using NUnit.Framework; -using ValidationContext = System.ComponentModel.DataAnnotations.ValidationContext; namespace GenderPayGap.WebUI.Tests.TestHelpers { diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UserHelper.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UserHelper.cs index 1dbf6fe66..b979dc135 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UserHelper.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UserHelper.cs @@ -1,8 +1,6 @@ using System; using GenderPayGap.Core; using GenderPayGap.Database; -using GenderPayGap.Extensions; -using Moq; namespace GenderPayGap.Tests.TestHelpers { diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs index 562394224..c555abd92 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestsCommon/Classes/AutoFacHelpers.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Reflection; using Autofac; using GenderPayGap.Database; -using GenderPayGap.Extensions; using GenderPayGap.WebUI.Tests.TestHelpers; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; diff --git a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs index f80d4a6e9..648b6d0d8 100644 --- a/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs +++ b/GenderPayGap.WebUI/Classes/GoogleAnalyticsTracker.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Net; using System.Net.Http; -using GenderPayGap.Extensions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Polly; diff --git a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs index 910fde497..a30077935 100644 --- a/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs +++ b/GenderPayGap.WebUI/Classes/Presentation/CompareViewService.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Web; using GenderPayGap.Core; using GenderPayGap.Extensions; using GenderPayGap.WebUI.Helpers; diff --git a/GenderPayGap.WebUI/Controllers/Account/ChangePersonalDetailsController.cs b/GenderPayGap.WebUI/Controllers/Account/ChangePersonalDetailsController.cs index cd4fa42de..061a58d26 100644 --- a/GenderPayGap.WebUI/Controllers/Account/ChangePersonalDetailsController.cs +++ b/GenderPayGap.WebUI/Controllers/Account/ChangePersonalDetailsController.cs @@ -2,7 +2,6 @@ using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; diff --git a/GenderPayGap.WebUI/Controllers/Account/ManageAccountController.cs b/GenderPayGap.WebUI/Controllers/Account/ManageAccountController.cs index 4c7867eea..c7e56b76e 100644 --- a/GenderPayGap.WebUI/Controllers/Account/ManageAccountController.cs +++ b/GenderPayGap.WebUI/Controllers/Account/ManageAccountController.cs @@ -1,5 +1,4 @@ -using System; -using GenderPayGap.Core; +using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; diff --git a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs index a8c04ee29..1a7358c8e 100644 --- a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs +++ b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; diff --git a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs index 958828e96..e8a294041 100644 --- a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs +++ b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; @@ -8,7 +7,6 @@ using GenderPayGap.WebUI.Models.AddOrganisation; using GenderPayGap.WebUI.Repositories; using GenderPayGap.WebUI.Services; -using GovUkDesignSystem; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs index de7725fcd..d336f897e 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminDataMigrationController.cs @@ -12,7 +12,6 @@ using GenderPayGap.Database.Backup; using GenderPayGap.Database.Models; using GenderPayGap.Extensions; -using GenderPayGap.Extensions.AspNetCore; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Admin; using Microsoft.AspNetCore.Authorization; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationScopeController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationScopeController.cs index 6fa1b8edb..7ee229e3f 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationScopeController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationScopeController.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; using System.Linq; using GenderPayGap.Core; using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; -using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Admin; using GenderPayGap.WebUI.Services; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs index 76d1888cf..d4879de74 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSectorController.cs @@ -5,12 +5,9 @@ using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; -using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Admin; using GenderPayGap.WebUI.Services; -using GovUkDesignSystem; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSicCodesController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSicCodesController.cs index a5c5b51b5..a27988863 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSicCodesController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminOrganisationSicCodesController.cs @@ -10,7 +10,6 @@ using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Admin; using GenderPayGap.WebUI.Services; -using GovUkDesignSystem; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminReferenceDataController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminReferenceDataController.cs index c73e81056..5d9dc995f 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminReferenceDataController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminReferenceDataController.cs @@ -9,7 +9,6 @@ using GenderPayGap.WebUI.Models.Admin; using GenderPayGap.WebUI.Models.AdminReferenceData; using GenderPayGap.WebUI.Services; -using GovUkDesignSystem; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; diff --git a/GenderPayGap.WebUI/Controllers/Admin/AdminUserResendVerificationEmailController.cs b/GenderPayGap.WebUI/Controllers/Admin/AdminUserResendVerificationEmailController.cs index 49da2df91..0528ac01d 100644 --- a/GenderPayGap.WebUI/Controllers/Admin/AdminUserResendVerificationEmailController.cs +++ b/GenderPayGap.WebUI/Controllers/Admin/AdminUserResendVerificationEmailController.cs @@ -6,7 +6,6 @@ using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.Admin; using GenderPayGap.WebUI.Services; -using GovUkDesignSystem; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/GenderPayGap.WebUI/Controllers/ScopeController.cs b/GenderPayGap.WebUI/Controllers/ScopeController.cs index 010b3fc83..95ec6cbcc 100644 --- a/GenderPayGap.WebUI/Controllers/ScopeController.cs +++ b/GenderPayGap.WebUI/Controllers/ScopeController.cs @@ -5,9 +5,6 @@ using GenderPayGap.Core.Helpers; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; -using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; -using GenderPayGap.WebUI.ErrorHandling; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Models.ManageOrganisations; using GenderPayGap.WebUI.Models.Scope; diff --git a/GenderPayGap.WebUI/Controllers/SendFeedback/FeedbackController.cs b/GenderPayGap.WebUI/Controllers/SendFeedback/FeedbackController.cs index 66bf62ad2..25276cf5d 100644 --- a/GenderPayGap.WebUI/Controllers/SendFeedback/FeedbackController.cs +++ b/GenderPayGap.WebUI/Controllers/SendFeedback/FeedbackController.cs @@ -6,7 +6,6 @@ using GenderPayGap.Database; using GenderPayGap.Database.Models; using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.Helpers; using Microsoft.AspNetCore.Mvc; diff --git a/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs b/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs index 0d455953b..0ae7c6321 100644 --- a/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs +++ b/GenderPayGap.WebUI/ExternalServices/CompaniesHouse/CompaniesHouseAPI.cs @@ -4,8 +4,6 @@ using System.Net.Http; using System.Text.RegularExpressions; using GenderPayGap.Core; -using GenderPayGap.Extensions; -using GenderPayGap.Extensions.AspNetCore; using GenderPayGap.WebUI.Helpers; using Newtonsoft.Json; using Polly; diff --git a/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs b/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs index a21435de8..6c9efe2c2 100644 --- a/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs +++ b/GenderPayGap.WebUI/ExternalServices/FileRepositories/SystemFileRepository.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading; -using GenderPayGap.Extensions; namespace GenderPayGap.WebUI.ExternalServices.FileRepositories { diff --git a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs index 947dae2ac..dbab171d8 100644 --- a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs +++ b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs @@ -6,7 +6,6 @@ using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Extensions; -using GenderPayGap.WebUI.Classes; using GenderPayGap.WebUI.ErrorHandling; using Microsoft.AspNetCore.Mvc; diff --git a/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs b/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs index 5943426e8..8548a8119 100644 --- a/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs +++ b/GenderPayGap.WebUI/Helpers/MaintenancePageMiddleware.cs @@ -1,6 +1,5 @@ using System; using System.Threading.Tasks; -using GenderPayGap.Extensions; using Microsoft.AspNetCore.Http; using HttpContext = Microsoft.AspNetCore.Http.HttpContext; diff --git a/GenderPayGap.WebUI/Models/Report/ReportOverviewViewModel.cs b/GenderPayGap.WebUI/Models/Report/ReportOverviewViewModel.cs index ad3f08631..cd704cd82 100644 --- a/GenderPayGap.WebUI/Models/Report/ReportOverviewViewModel.cs +++ b/GenderPayGap.WebUI/Models/Report/ReportOverviewViewModel.cs @@ -3,17 +3,11 @@ using System.Linq.Expressions; using GenderPayGap.Core; using GenderPayGap.Core.Helpers; -using GenderPayGap.Extensions; using GovUkDesignSystem; -using GovUkDesignSystem.Attributes; -using GovUkDesignSystem.Attributes.ValidationAttributes; -using GovUkDesignSystem.GovUkDesignSystemComponents; using GovUkDesignSystem.GovUkDesignSystemComponents.SubComponents; -using GovUkDesignSystem.Helpers; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.AspNetCore.Mvc.ViewFeatures; namespace GenderPayGap.WebUI.Models.Report { diff --git a/GenderPayGap.WebUI/Services/ReturnService.cs b/GenderPayGap.WebUI/Services/ReturnService.cs index 4aa18914b..ee5cd5c60 100644 --- a/GenderPayGap.WebUI/Services/ReturnService.cs +++ b/GenderPayGap.WebUI/Services/ReturnService.cs @@ -6,7 +6,6 @@ using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; -using GenderPayGap.Extensions; using Microsoft.AspNetCore.Mvc; namespace GenderPayGap.WebUI.Services From 507bc835e367bf4ef2a369e1276d8a833e09509c Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Tue, 5 Nov 2024 12:15:19 +0000 Subject: [PATCH 32/35] EHD-1411: Reduce code in Core project: Move EventLog --- .../Helpers/ExceptionDetailsHelper.cs | 69 ++----------------- GenderPayGap.WebUI/Program.cs | 4 +- 2 files changed, 8 insertions(+), 65 deletions(-) rename GenderPayGap.Core/Extensions/EventLog.cs => GenderPayGap.WebUI/Helpers/ExceptionDetailsHelper.cs (59%) diff --git a/GenderPayGap.Core/Extensions/EventLog.cs b/GenderPayGap.WebUI/Helpers/ExceptionDetailsHelper.cs similarity index 59% rename from GenderPayGap.Core/Extensions/EventLog.cs rename to GenderPayGap.WebUI/Helpers/ExceptionDetailsHelper.cs index 360bcb8e8..78cb9337b 100644 --- a/GenderPayGap.Core/Extensions/EventLog.cs +++ b/GenderPayGap.WebUI/Helpers/ExceptionDetailsHelper.cs @@ -1,75 +1,18 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Reflection; using System.Text.RegularExpressions; using Newtonsoft.Json; -namespace GenderPayGap.Extensions +namespace GenderPayGap.WebUI.Helpers { - public static class EventLog + public static class ExceptionDetailsHelper { - public const string LogName = "GenderPayGap"; + private const string LogName = "GenderPayGap"; - private static Assembly _TopAssembly; - public static string LogSource; - static EventLog() - { - LogSource = TopAssembly.GetName().Name; - } - - public static Assembly TopAssembly - { - get - { - if (_TopAssembly == null) - { - if (Assembly.GetEntryAssembly() != null) - { - _TopAssembly = Assembly.GetEntryAssembly(); - } - //else if (HttpContext.Current != null && HttpContext.Current.ApplicationInstance != null) - //{ - // _TopAssembly = HttpContext.Current.ApplicationInstance.GetType().Assembly; - //} - else - { - var stackTrace = new StackTrace(); // get call stack - StackFrame[] stackFrames = stackTrace.GetFrames(); - - // write call stack method names - for (int i = stackFrames.Length - 1; i > -1; i--) - { - _TopAssembly = stackFrames[i].GetMethod().ReflectedType.Assembly; - if (_TopAssembly.GetName() != null && _TopAssembly.GetName().Name.Contains(LogName)) - { - break; - } - - try - { - if (((AssemblyCompanyAttribute) Attribute.GetCustomAttribute( - _TopAssembly, - typeof(AssemblyCompanyAttribute), - false)).Company.Contains(LogName)) - { - break; - } - } - catch { } - } - } - } - - return _TopAssembly; - } - } - - - public static string GetDetailsText(this Exception ex) + public static string GetDetailsText(Exception ex) { return JsonConvert.SerializeObject(ex.GetDetails(), Formatting.Indented); } @@ -119,7 +62,7 @@ private static object GetDetails(this Exception ex) /// /// Exception object. /// Environment stack trace, for pulling additional stack frames. - public static string FullStackTrace(this Exception exception) + private static string FullStackTrace(this Exception exception) { List environmentStackTraceLines = GetUserStackTraceLines(Environment.StackTrace); if (environmentStackTraceLines.Count > 0) @@ -166,7 +109,7 @@ private static List GetUserStackTraceLines(string fullStackTrace) return outputList; } - public class ErrorDetails + private class ErrorDetails { public string Message { get; set; } diff --git a/GenderPayGap.WebUI/Program.cs b/GenderPayGap.WebUI/Program.cs index fff9174fd..698fcb815 100644 --- a/GenderPayGap.WebUI/Program.cs +++ b/GenderPayGap.WebUI/Program.cs @@ -45,8 +45,8 @@ private static void CurrentDomain_UnhandledException(object sender, UnhandledExc { var ex = e.ExceptionObject as Exception; - Console.WriteLine($"UNHANDLED EXCEPTION ({Console.Title}): {ex.Message}{Environment.NewLine}{ex.GetDetailsText()}"); - Debug.WriteLine($"UNHANDLED EXCEPTION ({Console.Title}): {ex.Message}{Environment.NewLine}{ex.GetDetailsText()}"); + Console.WriteLine($"UNHANDLED EXCEPTION ({Console.Title}): {ex.Message}{Environment.NewLine}{ExceptionDetailsHelper.GetDetailsText(ex)}"); + Debug.WriteLine($"UNHANDLED EXCEPTION ({Console.Title}): {ex.Message}{Environment.NewLine}{ExceptionDetailsHelper.GetDetailsText(ex)}"); //Show thread availability Console.WriteLine(ThreadCountHelper.GetThreadCount()); From 5900a9bee7b1984b78b2f7a48ef31ba60702922f Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Wed, 6 Nov 2024 16:40:50 +0000 Subject: [PATCH 33/35] EHD-1411: Reduce code in Core project: Simplify Encryption and use newer AES --- GenderPayGap.Core/Extensions/Encryption.cs | 485 +++++++----------- GenderPayGap.Core/Global.cs | 1 + .../Account/ChangePasswordControllerTests.cs | 4 +- .../Controllers/Scope/ScopeControllerTests.cs | 2 +- .../AddOrganisationConfirmationController.cs | 2 +- .../AddOrganisationFoundController.cs | 2 +- .../AddOrganisationManualConfirmController.cs | 2 +- .../Report/LateSubmissionController.cs | 2 +- .../Report/ReportConfirmationController.cs | 3 +- .../Report/ReportOverviewController.cs | 2 +- .../Helpers/ControllerHelper.cs | 2 +- GenderPayGap.WebUI/Program.cs | 2 +- .../Confirmation.cshtml | 2 +- .../ServiceActivated.cshtml | 2 +- .../AlreadyRegistering.cshtml | 2 +- .../Errors/ReportAlreadySubmitted.cshtml | 2 +- .../LateSubmissionReason.cshtml | 2 +- .../LateSubmissionWarning.cshtml | 2 +- .../ManageOrganisation.cshtml | 4 +- .../ManageOrganisations.cshtml | 2 +- .../ConfirmRemove.cshtml | 4 +- .../UserRemoved.cshtml | 2 +- .../ReportConfirmation.cshtml | 2 +- .../ReportDiscardDraft.cshtml | 2 +- .../Views/ReportFigures/ReportFigures.cshtml | 2 +- .../ReportLinkToWebsite.cshtml | 2 +- .../ReportOverview/ReportOverview.cshtml | 2 +- .../ReportResponsiblePerson.cshtml | 2 +- .../ReportSizeOfOrganisation.cshtml | 2 +- .../ReportStarting/ReportStarting.cshtml | 2 +- .../Views/Scope/ConfirmScope.cshtml | 2 +- .../Views/Scope/DeclareScope.cshtml | 2 +- .../Scope/FinishOutOfScopeJourney.cshtml | 2 +- .../Views/Scope/OutOfScopeQuestions.cshtml | 2 +- .../Views/Scope/ScopeDeclared.cshtml | 2 +- terraform/elasticbeanstalk.tf | 6 + terraform/variables.tf | 4 + 37 files changed, 228 insertions(+), 341 deletions(-) diff --git a/GenderPayGap.Core/Extensions/Encryption.cs b/GenderPayGap.Core/Extensions/Encryption.cs index d1d43499f..304c5a6aa 100644 --- a/GenderPayGap.Core/Extensions/Encryption.cs +++ b/GenderPayGap.Core/Extensions/Encryption.cs @@ -1,34 +1,154 @@ using System; -using System.Collections.Generic; -using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; -using System.Net; using System.Security.Cryptography; using System.Text; -using System.Web; using Newtonsoft.Json; namespace GenderPayGap.Extensions { public static class Encryption { - - private static string DefaultEncryptionKey = "BA9138B8C0724F168A05482456802405"; + private static string _defaultEncryptionKey = null; + private static byte[] _keyBytes = null; + private static byte[] _ivBytes = null; private static Encoding EncryptionEncoding = Encoding.UTF8; - public static void SetDefaultEncryptionKey(string defaultEncryptionKey) + public static void SetDefaultEncryptionKey(string defaultEncryptionKey, string defaultIv) + { + _defaultEncryptionKey = defaultEncryptionKey; + _keyBytes = HexDecode(defaultEncryptionKey); + _ivBytes = HexDecode(defaultIv); + } + + + # region Encrypt + + public static string EncryptModel(TModel plainTextModel) + { + string plainText = JsonConvert.SerializeObject(plainTextModel); + return EncryptString(plainText); + } + + public static string EncryptId(long plainTextId) + { + string plainText = plainTextId.ToString(); + return EncryptString(plainText); + } + + public static string EncryptString(string plainText) + { + byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); + + // Encrypt + byte[] cypherTextBytes = EncryptBytes(plainTextBytes); + + // Base 16 encode (so it's suitable for all uses including in a QueryString) + string hexEncodedCypherText = HexEncode(cypherTextBytes); + + return hexEncodedCypherText; + } + + private static byte[] EncryptBytes(byte[] plainTextBytes) + { + if (_keyBytes == null || _ivBytes == null) + { + throw new Exception("_keyBytes or _ivBytes not set"); + } + + using (Aes aesAlg = Aes.Create()) + { + aesAlg.Key = _keyBytes; + aesAlg.IV = _ivBytes; + + using (ICryptoTransform encryptor = aesAlg.CreateEncryptor()) + using (MemoryStream msEncrypt = new MemoryStream()) + using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) + { + csEncrypt.Write(plainTextBytes); + csEncrypt.FlushFinalBlock(); + return msEncrypt.ToArray(); + } + } + } + + private static string HexEncode(byte[] bytesToHexEncode) + { + var sb = new StringBuilder(); + + foreach (var b in bytesToHexEncode) + { + sb.Append(b.ToString("X2")); + } + + return sb.ToString().ToLower(); + } + + #endregion + + + # region Decrypt + + public static TModel DecryptModel(string cypherText) + { + string plainText = DecryptString(cypherText); + TModel plainTextModel = JsonConvert.DeserializeObject(plainText); + return plainTextModel; + } + + public static long DecryptId(string cypherText) + { + string plainText = DecryptString(cypherText); + long plainTextId = long.Parse(plainText); + return plainTextId; + } + + public static string DecryptString(string hexEncodedCypherText) + { + // Base 16 decode + byte[] cypherTextBytes = HexDecode(hexEncodedCypherText); + + // Decrypt + string plainText = DecryptBytes(cypherTextBytes); + + return plainText; + } + + private static byte[] HexDecode(string hexEncodedString) { - if (!string.IsNullOrWhiteSpace(defaultEncryptionKey)) + var bytes = new byte[hexEncodedString.Length / 2]; + for (var i = 0; i < bytes.Length; i++) { - DefaultEncryptionKey = defaultEncryptionKey; + bytes[i] = Convert.ToByte(hexEncodedString.Substring(i * 2, 2), 16); + } + + return bytes; + } + + private static string DecryptBytes(byte[] cipherTextBytes) + { + using (Aes aesAlg = Aes.Create()) + { + aesAlg.Key = _keyBytes; + aesAlg.IV = _ivBytes; + + using (ICryptoTransform decryptor = aesAlg.CreateDecryptor()) + using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) + using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) + using (StreamReader streamReader = new StreamReader(cryptoStream)) + { + return streamReader.ReadToEnd(); + } } } - #region Shared Functions + #endregion + + + #region OLD CODE /// /// Generate salt from password. @@ -44,7 +164,6 @@ private static byte[] SaltFromPassword(string password) return salt; } - private static ICryptoTransform GetTransform(string password, bool encrypt) { // Create an instance of the Rihndael class. @@ -107,27 +226,21 @@ private static byte[] CipherStreamWrite(ICryptoTransform cryptor, byte[] input) return outputBuffer; } - #endregion - - #region AES-256 Encryption - private static readonly byte[] PrimerBytes = {0, 0, 0, 0}; //Check the unencrypted data is delimited by the primer bytes private static bool WasEncrypted(this byte[] bytes) { - return bytes.IsWrapped(PrimerBytes, PrimerBytes); + return IsWrapped(bytes, PrimerBytes, PrimerBytes); } - private static byte[] Encrypt(byte[] bytes, string password = null) + private static byte[] Encrypt(byte[] bytes) { - password = DefaultEncryptionKey + password; - // Create a encryptor. - ICryptoTransform encryptor = GetTransform(password, true); + ICryptoTransform encryptor = GetTransform(_defaultEncryptionKey, true); //Wrap in the primer bytes so we can later check if the decryption was correct for the key - bytes = bytes.Wrap(PrimerBytes, PrimerBytes); + bytes = Wrap(bytes, PrimerBytes, PrimerBytes); // Return encrypted bytes. bytes = CipherStreamWrite(encryptor, bytes); @@ -135,7 +248,7 @@ private static byte[] Encrypt(byte[] bytes, string password = null) return Compress(bytes); } - private static string Encrypt(string text, string password = null, bool base64Encode = true) + private static string Encrypt(string text) { if (string.IsNullOrWhiteSpace(text)) { @@ -146,93 +259,26 @@ private static string Encrypt(string text, string password = null, bool base64En byte[] bytes = EncryptionEncoding.GetBytes(text); // Get encrypted bytes. - byte[] encryptedBytes = Encrypt(bytes, password); - - if (base64Encode) - { - return Convert.ToBase64String(encryptedBytes); - } - - return EncryptionEncoding.GetString(encryptedBytes); - } - - /// - /// Decrypt string with AES-256 by using password key. - /// - /// String password. - /// Encrypted Base64 string. - /// Decrypted string. - public static string EncryptQuerystring(string querystring, string password = null, params string[] excludeNames) - { - if (string.IsNullOrWhiteSpace(querystring)) - { - return querystring; - } - - NameValueCollection nsEncrypted = querystring.FromQueryString(); - var nsDecrypted = new NameValueCollection(); - if (excludeNames != null) - { - foreach (string name in excludeNames) - { - if (string.IsNullOrWhiteSpace(name)) - { - continue; - } - - nsDecrypted[name] = nsEncrypted[name]; - nsEncrypted.Remove(name); - } - } - - querystring = Encrypt(nsEncrypted.ToQueryString(), password); - if (!string.IsNullOrEmpty(querystring)) - { - querystring = querystring.Replace('+', '-'); - querystring = querystring.Replace('/', '_'); - querystring = querystring.Replace('=', '!'); - } - - nsDecrypted[null] = string.IsNullOrWhiteSpace(nsEncrypted[null]) ? querystring : "," + querystring; - - return nsDecrypted.ToQueryString(); - } + byte[] encryptedBytes = Encrypt(bytes); - public static string EncryptModel(TModel model) - { - string modelSerialized = JsonConvert.SerializeObject(model); - string encString = EncryptData(modelSerialized); - return encString.EncodeUrlBase64(); + return Convert.ToBase64String(encryptedBytes); } - #endregion - - #region AES-256 Decryption - //[DebuggerStepThrough] - private static byte[] Decrypt(byte[] bytes, params string[] passwords) - { - return Decrypt(bytes, new List(passwords)); - } - - //[DebuggerStepThrough] - private static byte[] Decrypt(byte[] encryptedBytes, List passwords) + private static byte[] Decrypt(byte[] encryptedBytes) { //Ensure the bytes are decompressed encryptedBytes = Decompress(encryptedBytes); - //Always try using just the basic master password - passwords.Add(null); - // First, try with encryption primer bool tryWithPrimer = true; - bool found = DecryptBytes(encryptedBytes, passwords, tryWithPrimer, out byte[] decryptedBytes); + bool found = DecryptBytes(encryptedBytes, tryWithPrimer, out byte[] decryptedBytes); // Try again without encryption primer if (!found) { tryWithPrimer = false; - found = DecryptBytes(encryptedBytes, passwords, tryWithPrimer, out decryptedBytes); + found = DecryptBytes(encryptedBytes, tryWithPrimer, out decryptedBytes); } if (!found) @@ -242,58 +288,40 @@ private static byte[] Decrypt(byte[] encryptedBytes, List passwords) if (tryWithPrimer) { - decryptedBytes = decryptedBytes.Strip(PrimerBytes.Length, PrimerBytes.Length); + decryptedBytes = Strip(decryptedBytes, PrimerBytes.Length, PrimerBytes.Length); } return decryptedBytes; } - private static bool DecryptBytes(byte[] encryptedBytes, List passwords, bool tryWithPrimer, out byte[] decryptedBytes) + private static bool DecryptBytes(byte[] encryptedBytes, bool tryWithPrimer, out byte[] decryptedBytes) { var found = false; decryptedBytes = null; - var attempted = new HashSet(); - for (var p = 0; p < passwords.Count; p++) + ICryptoTransform decryptor; + var decrypted = false; + try { - if (attempted.Contains(passwords[p])) - { - continue; - } + decryptor = GetTransform(_defaultEncryptionKey, false); - //Skip all but the last empty password - if (p != passwords.Count - 1 && string.IsNullOrWhiteSpace(passwords[p])) - { - continue; - } - - attempted.Add(passwords[p]); - - ICryptoTransform decryptor; - var decrypted = false; - try - { - decryptor = GetTransform(DefaultEncryptionKey + passwords[p], false); - - decryptedBytes = CipherStreamWrite(decryptor, encryptedBytes); + decryptedBytes = CipherStreamWrite(decryptor, encryptedBytes); - decryptedBytes = Decompress(decryptedBytes); + decryptedBytes = Decompress(decryptedBytes); - decrypted = true; - } - catch (CryptographicException) { } + decrypted = true; + } + catch (CryptographicException) { } - if (decrypted && (!tryWithPrimer || decryptedBytes.WasEncrypted())) - { - found = true; - break; - } + if (decrypted && (!tryWithPrimer || decryptedBytes.WasEncrypted())) + { + found = true; } return found; } [DebuggerStepThrough] - private static string Decrypt(string text, bool base64Encoded = true, params string[] passwords) + private static string Decrypt(string text) { if (string.IsNullOrWhiteSpace(text)) { @@ -301,72 +329,19 @@ private static string Decrypt(string text, bool base64Encoded = true, params str } // Convert Base64 string into a byte array. - byte[] bytes; - if (base64Encoded) - { - text = text.Replace("\n", ""); - text = text.Replace("\r", ""); - text = text.Replace(" ", ""); - text = text.Trim(); + text = text.Replace("\n", ""); + text = text.Replace("\r", ""); + text = text.Replace(" ", ""); + text = text.Trim(); - bytes = Convert.FromBase64String(text); - } - else - { - bytes = EncryptionEncoding.GetBytes(text); - } + byte[] bytes = Convert.FromBase64String(text); // Return decrypted string. - bytes = Decrypt(bytes, passwords); + bytes = Decrypt(bytes); return EncryptionEncoding.GetString(bytes); } - /// - /// Decrypt string with AES-256 by using password key. - /// - /// String password. - /// Encrypted Base64 string. - /// Decrypted string. - //[DebuggerStepThrough] - public static string DecryptQuerystring(string querystring, params string[] passwords) - { - if (string.IsNullOrWhiteSpace(querystring)) - { - return querystring; - } - - NameValueCollection ns = querystring.FromQueryString(); - querystring = ns[null]; - ns.Remove(null); - ns = new NameValueCollection(ns); - foreach (string qs in querystring.Split(",")) - { - querystring = qs.Replace('-', '+'); - querystring = querystring.Replace('_', '/'); - querystring = querystring.Replace('!', '='); - - querystring = Decrypt(querystring, true, passwords); - NameValueCollection ns2 = querystring.FromQueryString(); - foreach (string key in ns2.Keys) - { - ns.Add(key, ns2[key]); - } - } - - return ns.ToQueryString(); - } - - public static TModel DecryptModel(string encText) - { - string serializedModel = DecryptData(encText.DecodeUrlBase64()); - return JsonConvert.DeserializeObject(serializedModel); - } - - #endregion - - #region Compression - private static readonly byte[] GZipHeaderBytes = {0x1f, 0x8b, 8, 0, 0, 0, 0, 0, 4, 0}; private static readonly byte[] GZipLevel10HeaderBytes = {0x1f, 0x8b, 8, 0, 0, 0, 0, 0, 2, 0}; private static readonly byte[] GZipLevel12HeaderBytes = {0x1f, 0x8b, 8, 0, 0, 0, 0, 0, 0, 11}; @@ -378,7 +353,7 @@ private static bool IsCompressed(this byte[] bytes) return false; } - byte[] header = bytes.SubArray(4, 10); + byte[] header = SubArray(bytes, 4, 10); if (header.SequenceEqual(GZipLevel12HeaderBytes) || header.SequenceEqual(GZipHeaderBytes) @@ -387,7 +362,7 @@ private static bool IsCompressed(this byte[] bytes) return true; } - header = bytes.SubArray(0, 10); + header = SubArray(bytes, 0, 10); return header.SequenceEqual(GZipLevel12HeaderBytes) || header.SequenceEqual(GZipHeaderBytes) @@ -454,10 +429,6 @@ private static byte[] Decompress(byte[] gZipBuffer) } } - #endregion - - #region Public General Encryption Methods - private static bool IsEncryptedData(string data) { if (string.IsNullOrWhiteSpace(data)) @@ -468,7 +439,7 @@ private static bool IsEncryptedData(string data) return data.StartsWith("===") && data.EndsWith("==="); } - private static bool IsPrivateData(this string data, params string[] passwords) + private static bool IsPrivateData(this string data) { if (string.IsNullOrWhiteSpace(data)) { @@ -477,7 +448,7 @@ private static bool IsPrivateData(this string data, params string[] passwords) if (IsEncryptedData(data)) { - data = Decrypt(data.Substring(3, data.Length - 6), true, passwords); + data = Decrypt(data.Substring(3, data.Length - 6)); } if (data.StartsWith("##mkPrivatePassword:", StringComparison.InvariantCultureIgnoreCase)) @@ -493,11 +464,12 @@ private static bool IsPrivateData(this string data, params string[] passwords) return false; } - public static string EncryptData(string data, bool isPrivate = false, string password = null) + [Obsolete] + public static string EncryptData(string data) { if (IsEncryptedData(data)) { - data = Decrypt(data.Substring(3, data.Length - 6), true, password); + data = Decrypt(data.Substring(3, data.Length - 6)); } if (string.IsNullOrWhiteSpace(data)) @@ -505,35 +477,23 @@ public static string EncryptData(string data, bool isPrivate = false, string pas return null; } - if (isPrivate && !IsPrivateData(data, password)) - { - data = "##mkPrivatePassword:" + data; - } - - return "===" + Encrypt(data, password) + "==="; + return "===" + Encrypt(data) + "==="; } + [Obsolete] public static string DecryptData(string data) - { - bool isPrivate; - return DecryptData(data, out isPrivate); - } - - private static string DecryptData(string data, out bool isPrivate, params string[] passwords) { if (string.IsNullOrWhiteSpace(data)) { - isPrivate = false; return null; } if (IsEncryptedData(data)) { - data = Decrypt(data.Substring(3, data.Length - 6), true, passwords); + data = Decrypt(data.Substring(3, data.Length - 6)); } - isPrivate = data.IsPrivateData(passwords); - if (isPrivate) + if (data.IsPrivateData()) { return data.Substring(20); } @@ -541,135 +501,54 @@ private static string DecryptData(string data, out bool isPrivate, params string return data; } - #endregion - - private static string ToQueryString(this NameValueCollection collection, bool allowDuplicateKeys = false) - { - var data = ""; - if (collection != null) - { - var keyValues = new List>(); - foreach (string key in collection.Keys) - { - if (string.IsNullOrWhiteSpace(collection[key])) - { - continue; - } - - if (allowDuplicateKeys) - { - foreach (string value in collection[key].Split(",")) - { - keyValues.Add(new KeyValuePair(key, value)); - } - } - else - { - keyValues.Add(new KeyValuePair(key, collection[key])); - } - } - - foreach (KeyValuePair keyValue in keyValues) - { - if (string.IsNullOrWhiteSpace(keyValue.Value)) - { - continue; - } - - if (!string.IsNullOrWhiteSpace(data)) - { - data += "&"; - } - - if (string.IsNullOrWhiteSpace(keyValue.Key)) - { - data += keyValue.Value; - } - else - { - data += $"{WebUtility.UrlEncode(keyValue.Key)}={keyValue.Value}"; - } - } - } - - return data; - } - - private static NameValueCollection FromQueryString(this string querystring) - { - return string.IsNullOrWhiteSpace(querystring) ? null : HttpUtility.ParseQueryString(querystring); - } - - private static bool IsWrapped(this T[] data, T[] prefix, T[] suffix) + private static bool IsWrapped(byte[] data, byte[] prefix, byte[] suffix) { if (data.Length < prefix.Length + suffix.Length) { return false; } - T[] end = data.SubArray(0, prefix.Length); + byte[] end = SubArray(data, 0, prefix.Length); if (!end.SequenceEqual(prefix)) { return false; } - end = data.SubArray(data.Length - suffix.Length, suffix.Length); + end = SubArray(data, data.Length - suffix.Length, suffix.Length); return end.SequenceEqual(suffix); } - private static T[] Wrap(this T[] data, T[] prefix, T[] suffix) + private static byte[] Wrap(byte[] data, byte[] prefix, byte[] suffix) { - var result = new T[data.Length + prefix.Length + suffix.Length]; + var result = new byte[data.Length + prefix.Length + suffix.Length]; Buffer.BlockCopy(prefix, 0, result, 0, prefix.Length); Buffer.BlockCopy(data, 0, result, prefix.Length, data.Length); Buffer.BlockCopy(suffix, 0, result, prefix.Length + data.Length, suffix.Length); return result; } - private static T[] Strip(this T[] data, int left, int right) + private static byte[] Strip(byte[] data, int left, int right) { - var result = new T[data.Length - (left + right)]; + var result = new byte[data.Length - (left + right)]; Buffer.BlockCopy(data, left, result, 0, result.Length); return result; } - private static T[] SubArray(this T[] data, int index, int length) + private static byte[] SubArray(byte[] data, int index, int length) { if (length > data.Length) { length = data.Length; } - var result = new T[length]; + var result = new byte[length]; Buffer.BlockCopy(data, index, result, 0, length); return result; } - private static string EncodeUrlBase64(this string base64String) - { - if (!string.IsNullOrWhiteSpace(base64String)) - { - base64String = base64String.Replace('+', '-'); - base64String = base64String.Replace('/', '_'); - base64String = base64String.Replace('=', '!'); - } - - return base64String; - } - - private static string DecodeUrlBase64(this string base64String) - { - if (!string.IsNullOrWhiteSpace(base64String)) - { - base64String = base64String.Replace('-', '+'); - base64String = base64String.Replace('_', '/'); - base64String = base64String.Replace('!', '='); - } - - return base64String; - } + #endregion } } diff --git a/GenderPayGap.Core/Global.cs b/GenderPayGap.Core/Global.cs index a5a530dbc..7da555a15 100644 --- a/GenderPayGap.Core/Global.cs +++ b/GenderPayGap.Core/Global.cs @@ -29,6 +29,7 @@ public static class Global public static string CompaniesHouseApiKey => Config.GetAppSetting("CompaniesHouseApiKey"); public static string GovUkNotifyApiKey => Config.GetAppSetting("GovUkNotifyApiKey"); public static string DefaultEncryptionKey => Config.GetAppSetting("DefaultEncryptionKey"); + public static string DefaultEncryptionIv => Config.GetAppSetting("DefaultEncryptionIv"); public static string DataMigrationPassword => Config.GetAppSetting("DataMigrationPassword"); public static string BasicAuthUsername => Config.GetAppSetting("BasicAuthUsername"); public static string BasicAuthPassword => Config.GetAppSetting("BasicAuthPassword"); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs index 2db605c03..2b4fbbd08 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Reflection; using GenderPayGap.Core; @@ -14,7 +13,6 @@ using GenderPayGap.WebUI.Tests.Builders; using GovUkDesignSystem.Attributes.ValidationAttributes; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Primitives; using Moq; using NUnit.Framework; diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs index be174439f..92cdd9b1d 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs @@ -37,7 +37,7 @@ public void POST_Existing_Scopes_Are_Retired_When_New_Scope_Is_Added() .Build(); // Act - string encryptedOrganisationId = Encryption.EncryptQuerystring(organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(organisation.OrganisationId); controller.ConfirmOutOfScopeAnswers(encryptedOrganisationId, 2018, new ScopeViewModel()); // Assert diff --git a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs index 1a7358c8e..9b83a8319 100644 --- a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs +++ b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationConfirmationController.cs @@ -38,7 +38,7 @@ private UserOrganisation LoadUserOrganisationWithConfirmationId(string confirmat { try { - string userIdAndOrganisationId = Encryption.DecryptQuerystring(confirmationId); + string userIdAndOrganisationId = Encryption.DecryptString(confirmationId); long userId = long.Parse(userIdAndOrganisationId.Split(":")[0]); long organisationId = long.Parse(userIdAndOrganisationId.Split(":")[1]); diff --git a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationFoundController.cs b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationFoundController.cs index 37ab92715..1bfaded62 100644 --- a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationFoundController.cs +++ b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationFoundController.cs @@ -201,7 +201,7 @@ private IActionResult FoundPostWithCompanyNumber(AddOrganisationFoundViewModel v private IActionResult RedirectToConfirmationPage(UserOrganisation userOrganisation) { string confirmationId = $"{userOrganisation.UserId}:{userOrganisation.OrganisationId}"; - string encryptedConfirmationId = Encryption.EncryptQuerystring(confirmationId); + string encryptedConfirmationId = Encryption.EncryptString(confirmationId); return RedirectToAction("Confirmation", "AddOrganisationConfirmation", new { confirmationId = encryptedConfirmationId }); } diff --git a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs index e8a294041..38dd7e8a9 100644 --- a/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs +++ b/GenderPayGap.WebUI/Controllers/AddOrganisation/AddOrganisationManualConfirmController.cs @@ -118,7 +118,7 @@ private void PopulateViewModel(AddOrganisationManualViewModel viewModel) private IActionResult RedirectToConfirmationPage(UserOrganisation userOrganisation) { string confirmationId = $"{userOrganisation.UserId}:{userOrganisation.OrganisationId}"; - string encryptedConfirmationId = Encryption.EncryptQuerystring(confirmationId); + string encryptedConfirmationId = Encryption.EncryptString(confirmationId); return RedirectToAction("Confirmation", "AddOrganisationConfirmation", new { confirmationId = encryptedConfirmationId }); } diff --git a/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs b/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs index 60a7338c1..02267cabc 100644 --- a/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs +++ b/GenderPayGap.WebUI/Controllers/Report/LateSubmissionController.cs @@ -111,7 +111,7 @@ public IActionResult LateSubmissionReasonPost(string encryptedOrganisationId, in { encryptedOrganisationId, reportingYear, - confirmationId = Encryption.EncryptQuerystring(newReturn.ReturnId.ToString()) + confirmationId = Encryption.EncryptId(newReturn.ReturnId) }); } diff --git a/GenderPayGap.WebUI/Controllers/Report/ReportConfirmationController.cs b/GenderPayGap.WebUI/Controllers/Report/ReportConfirmationController.cs index 9a74b1293..218d44fdc 100644 --- a/GenderPayGap.WebUI/Controllers/Report/ReportConfirmationController.cs +++ b/GenderPayGap.WebUI/Controllers/Report/ReportConfirmationController.cs @@ -57,8 +57,7 @@ private Return LoadReturnFromOrganisationIdReportingYearAndConfirmationId( int reportingYear, string confirmationId) { - string returnIdString = Encryption.DecryptQuerystring(confirmationId); - long returnId = long.Parse(returnIdString); + long returnId = Encryption.DecryptId(confirmationId); var foundReturn = dataRepository.Get(returnId); diff --git a/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs b/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs index 4861ca626..1c834d0d4 100644 --- a/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs +++ b/GenderPayGap.WebUI/Controllers/Report/ReportOverviewController.cs @@ -61,7 +61,7 @@ public IActionResult SubmitReturnPost(string encryptedOrganisationId, int report { encryptedOrganisationId, reportingYear, - confirmationId = Encryption.EncryptQuerystring(newReturn.ReturnId.ToString()) + confirmationId = Encryption.EncryptId(newReturn.ReturnId) }); } diff --git a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs index dbab171d8..86b02321d 100644 --- a/GenderPayGap.WebUI/Helpers/ControllerHelper.cs +++ b/GenderPayGap.WebUI/Helpers/ControllerHelper.cs @@ -245,7 +245,7 @@ private static bool DecryptToId(string encryptedId, out long decryptedId) long id; try { - id = long.Parse(Encryption.DecryptQuerystring(encryptedId)); + id = Encryption.DecryptId(encryptedId); } catch (Exception e) { diff --git a/GenderPayGap.WebUI/Program.cs b/GenderPayGap.WebUI/Program.cs index 698fcb815..2168a1c69 100644 --- a/GenderPayGap.WebUI/Program.cs +++ b/GenderPayGap.WebUI/Program.cs @@ -101,7 +101,7 @@ private static void ConfigureAppConfiguration(WebHostBuilderContext builderConte //Build the configuration Config.Configuration = Config.Build(configBuilder); - Encryption.SetDefaultEncryptionKey(Global.DefaultEncryptionKey); + Encryption.SetDefaultEncryptionKey(Global.DefaultEncryptionKey, Global.DefaultEncryptionIv); } public static void SetupSerilogLogger(IWebHostBuilder webHostBuilder) diff --git a/GenderPayGap.WebUI/Views/AddOrganisationConfirmation/Confirmation.cshtml b/GenderPayGap.WebUI/Views/AddOrganisationConfirmation/Confirmation.cshtml index 5b53c54e3..f46969dac 100644 --- a/GenderPayGap.WebUI/Views/AddOrganisationConfirmation/Confirmation.cshtml +++ b/GenderPayGap.WebUI/Views/AddOrganisationConfirmation/Confirmation.cshtml @@ -4,7 +4,7 @@ @model UserOrganisation @{ UserOrganisation userOrg = Model; - string encryptedOrgId = Encryption.EncryptQuerystring(userOrg.OrganisationId.ToString()); + string encryptedOrgId = Encryption.EncryptId(userOrg.OrganisationId); if (userOrg.PINConfirmedDate.HasValue) { diff --git a/GenderPayGap.WebUI/Views/AddOrganisationEnterPin/ServiceActivated.cshtml b/GenderPayGap.WebUI/Views/AddOrganisationEnterPin/ServiceActivated.cshtml index abb9f12c5..2b5c03753 100644 --- a/GenderPayGap.WebUI/Views/AddOrganisationEnterPin/ServiceActivated.cshtml +++ b/GenderPayGap.WebUI/Views/AddOrganisationEnterPin/ServiceActivated.cshtml @@ -2,7 +2,7 @@ @using GovUkDesignSystem @model GenderPayGap.Database.UserOrganisation @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); ViewBag.Title = "Service activated - Gender pay gap reporting service"; } diff --git a/GenderPayGap.WebUI/Views/AddOrganisationFound/AlreadyRegistering.cshtml b/GenderPayGap.WebUI/Views/AddOrganisationFound/AlreadyRegistering.cshtml index 827151c40..de32a2e44 100644 --- a/GenderPayGap.WebUI/Views/AddOrganisationFound/AlreadyRegistering.cshtml +++ b/GenderPayGap.WebUI/Views/AddOrganisationFound/AlreadyRegistering.cshtml @@ -6,7 +6,7 @@ @model GenderPayGap.WebUI.Models.AddOrganisation.AddOrganisationAlreadyRegisteringViewModel @{ UserOrganisation userOrg = Model.ExistingUserOrganisation; - string encryptedOrgId = Encryption.EncryptQuerystring(userOrg.OrganisationId.ToString()); + string encryptedOrgId = Encryption.EncryptId(userOrg.OrganisationId); ViewBag.Title = userOrg.PINConfirmedDate.HasValue ? "You are already registered - Gender pay gap service" diff --git a/GenderPayGap.WebUI/Views/Errors/ReportAlreadySubmitted.cshtml b/GenderPayGap.WebUI/Views/Errors/ReportAlreadySubmitted.cshtml index 30754df68..d54f2dceb 100644 --- a/GenderPayGap.WebUI/Views/Errors/ReportAlreadySubmitted.cshtml +++ b/GenderPayGap.WebUI/Views/Errors/ReportAlreadySubmitted.cshtml @@ -2,7 +2,7 @@ @model GenderPayGap.WebUI.ErrorHandling.ReportAlreadySubmittedException @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.OrganisationId); ViewBag.Title = $"Report already submitted - Gender pay gap service"; } diff --git a/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionReason.cshtml b/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionReason.cshtml index 17ac663ac..27a419a43 100644 --- a/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionReason.cshtml +++ b/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionReason.cshtml @@ -6,7 +6,7 @@ @model GenderPayGap.WebUI.Models.Report.LateSubmissionReasonViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); DateTime snapshotDate = Model.Organisation.SectorType.GetAccountingStartDate(Model.ReportingYear); diff --git a/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionWarning.cshtml b/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionWarning.cshtml index 36cb0f415..184c5e4fc 100644 --- a/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionWarning.cshtml +++ b/GenderPayGap.WebUI/Views/LateSubmission/LateSubmissionWarning.cshtml @@ -5,7 +5,7 @@ @model GenderPayGap.WebUI.Models.Report.LateSubmissionWarningViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); DateTime snapshotDate = Model.Organisation.SectorType.GetAccountingStartDate(Model.ReportingYear); diff --git a/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisation.cshtml b/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisation.cshtml index a7887e23f..dbecd543e 100644 --- a/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisation.cshtml +++ b/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisation.cshtml @@ -9,7 +9,7 @@ @{ ViewBag.Title = "Manage your employers - Gender pay gap service"; - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); } @section BeforeMain { @@ -191,7 +191,7 @@ @foreach (User userRegisteredToReport in usersRegisteredToReportForOrganisation) { - string encryptedUserId = Encryption.EncryptQuerystring(userRegisteredToReport.UserId.ToString()); + string encryptedUserId = Encryption.EncryptId(userRegisteredToReport.UserId); diff --git a/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisations.cshtml b/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisations.cshtml index c2cff09f5..f204cd9f8 100644 --- a/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisations.cshtml +++ b/GenderPayGap.WebUI/Views/ManageOrganisations/ManageOrganisations.cshtml @@ -39,7 +39,7 @@ @foreach (UserOrganisation userOrganisation in Model.UserOrganisations) { - string encryptedOrganisationId = Encryption.EncryptQuerystring(userOrganisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(userOrganisation.OrganisationId); @if (userOrganisation.IsAwaitingActivationPIN()) diff --git a/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/ConfirmRemove.cshtml b/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/ConfirmRemove.cshtml index 1e56c40b0..2d6f15082 100644 --- a/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/ConfirmRemove.cshtml +++ b/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/ConfirmRemove.cshtml @@ -5,8 +5,8 @@ @model GenderPayGap.WebUI.Models.RemoveUserFromOrganisation.RemoveUserFromOrganisationViewModel @{ ViewBag.Title = "Confirm removal of user - Gender pay gap service"; - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); - string encryptedUserId = Encryption.EncryptQuerystring(Model.UserToRemove.UserId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); + string encryptedUserId = Encryption.EncryptId(Model.UserToRemove.UserId); bool userRemovingSelf = Model.UserToRemove.UserId == Model.LoggedInUser.UserId; } diff --git a/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/UserRemoved.cshtml b/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/UserRemoved.cshtml index 08d9f99ec..608a5009f 100644 --- a/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/UserRemoved.cshtml +++ b/GenderPayGap.WebUI/Views/RemoveUserFromOrganisation/UserRemoved.cshtml @@ -3,7 +3,7 @@ @model GenderPayGap.WebUI.Models.RemoveUserFromOrganisation.RemoveUserFromOrganisationViewModel @{ ViewBag.Title = "Remove organisation reason - Gender pay gap service"; - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); bool userRemovedSelf = Model.UserToRemove.UserId == Model.LoggedInUser.UserId; } diff --git a/GenderPayGap.WebUI/Views/ReportConfirmation/ReportConfirmation.cshtml b/GenderPayGap.WebUI/Views/ReportConfirmation/ReportConfirmation.cshtml index c0da4b16a..4ca828aad 100644 --- a/GenderPayGap.WebUI/Views/ReportConfirmation/ReportConfirmation.cshtml +++ b/GenderPayGap.WebUI/Views/ReportConfirmation/ReportConfirmation.cshtml @@ -4,7 +4,7 @@ @model GenderPayGap.Database.Return @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); int reportingYear = Model.AccountingDate.Year; string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(reportingYear); diff --git a/GenderPayGap.WebUI/Views/ReportDiscardDraft/ReportDiscardDraft.cshtml b/GenderPayGap.WebUI/Views/ReportDiscardDraft/ReportDiscardDraft.cshtml index 75203e9e0..148c132c8 100644 --- a/GenderPayGap.WebUI/Views/ReportDiscardDraft/ReportDiscardDraft.cshtml +++ b/GenderPayGap.WebUI/Views/ReportDiscardDraft/ReportDiscardDraft.cshtml @@ -5,7 +5,7 @@ @model GenderPayGap.WebUI.Models.Report.ReportDiscardDraftViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); string editOrReportTitle = Model.IsEditingSubmittedReturn diff --git a/GenderPayGap.WebUI/Views/ReportFigures/ReportFigures.cshtml b/GenderPayGap.WebUI/Views/ReportFigures/ReportFigures.cshtml index d7cbbe009..a87f86e39 100644 --- a/GenderPayGap.WebUI/Views/ReportFigures/ReportFigures.cshtml +++ b/GenderPayGap.WebUI/Views/ReportFigures/ReportFigures.cshtml @@ -7,7 +7,7 @@ @model GenderPayGap.WebUI.Models.Report.ReportFiguresViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); string editOrReportTitle = Model.IsEditingSubmittedReturn diff --git a/GenderPayGap.WebUI/Views/ReportLinkToWebsite/ReportLinkToWebsite.cshtml b/GenderPayGap.WebUI/Views/ReportLinkToWebsite/ReportLinkToWebsite.cshtml index 9d8f6fb9c..b84be3313 100644 --- a/GenderPayGap.WebUI/Views/ReportLinkToWebsite/ReportLinkToWebsite.cshtml +++ b/GenderPayGap.WebUI/Views/ReportLinkToWebsite/ReportLinkToWebsite.cshtml @@ -7,7 +7,7 @@ @model GenderPayGap.WebUI.Models.Report.ReportLinkToWebsiteViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); string editOrReportTitle = Model.IsEditingSubmittedReturn diff --git a/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml b/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml index 0f10dcb19..a71927508 100644 --- a/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml +++ b/GenderPayGap.WebUI/Views/ReportOverview/ReportOverview.cshtml @@ -8,7 +8,7 @@ @model GenderPayGap.WebUI.Models.Report.ReportOverviewViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); string editOrReportTitle = Model.IsEditingSubmittedReturn diff --git a/GenderPayGap.WebUI/Views/ReportResponsiblePerson/ReportResponsiblePerson.cshtml b/GenderPayGap.WebUI/Views/ReportResponsiblePerson/ReportResponsiblePerson.cshtml index feb812134..8bd07fbb7 100644 --- a/GenderPayGap.WebUI/Views/ReportResponsiblePerson/ReportResponsiblePerson.cshtml +++ b/GenderPayGap.WebUI/Views/ReportResponsiblePerson/ReportResponsiblePerson.cshtml @@ -7,7 +7,7 @@ @model GenderPayGap.WebUI.Models.Report.ReportResponsiblePersonViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); string editOrReportTitle = Model.IsEditingSubmittedReturn diff --git a/GenderPayGap.WebUI/Views/ReportSizeOfOrganisation/ReportSizeOfOrganisation.cshtml b/GenderPayGap.WebUI/Views/ReportSizeOfOrganisation/ReportSizeOfOrganisation.cshtml index 6982aaf2c..629e7cbb7 100644 --- a/GenderPayGap.WebUI/Views/ReportSizeOfOrganisation/ReportSizeOfOrganisation.cshtml +++ b/GenderPayGap.WebUI/Views/ReportSizeOfOrganisation/ReportSizeOfOrganisation.cshtml @@ -7,7 +7,7 @@ @model GenderPayGap.WebUI.Models.Report.ReportSizeOfOrganisationViewModel @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); string editOrReportTitle = Model.IsEditingSubmittedReturn diff --git a/GenderPayGap.WebUI/Views/ReportStarting/ReportStarting.cshtml b/GenderPayGap.WebUI/Views/ReportStarting/ReportStarting.cshtml index ba7aa2682..5d9596400 100644 --- a/GenderPayGap.WebUI/Views/ReportStarting/ReportStarting.cshtml +++ b/GenderPayGap.WebUI/Views/ReportStarting/ReportStarting.cshtml @@ -6,7 +6,7 @@ @{ ViewBag.Title = $"Report gender pay gap data - reporting year {Model.ReportingYear} - Gender pay gap service"; - var encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + var encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); } diff --git a/GenderPayGap.WebUI/Views/Scope/ConfirmScope.cshtml b/GenderPayGap.WebUI/Views/Scope/ConfirmScope.cshtml index 29252c604..cdbf75a01 100644 --- a/GenderPayGap.WebUI/Views/Scope/ConfirmScope.cshtml +++ b/GenderPayGap.WebUI/Views/Scope/ConfirmScope.cshtml @@ -11,7 +11,7 @@ } @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string reportingYearsString = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear.Year, "/"); string whyOutOfScopeFormatted = Model.WhyOutOfScope == WhyOutOfScope.Under250 ? "My employer had a headcount less than 250 employees on our snapshot date of " + Model.ReportingYear.ToString("d MMMM yyyy") : "Other: " + Model.WhyOutOfScopeDetails; diff --git a/GenderPayGap.WebUI/Views/Scope/DeclareScope.cshtml b/GenderPayGap.WebUI/Views/Scope/DeclareScope.cshtml index 02488b893..5f8211a99 100644 --- a/GenderPayGap.WebUI/Views/Scope/DeclareScope.cshtml +++ b/GenderPayGap.WebUI/Views/Scope/DeclareScope.cshtml @@ -8,7 +8,7 @@ @{ ViewBag.Title = "Declare scope - Gender pay gap service"; - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.PreviousReportingYear); DateTime snapshotDate = Model.Organisation.SectorType.GetAccountingStartDate(Model.PreviousReportingYear); } diff --git a/GenderPayGap.WebUI/Views/Scope/FinishOutOfScopeJourney.cshtml b/GenderPayGap.WebUI/Views/Scope/FinishOutOfScopeJourney.cshtml index 159752a59..55afc8645 100644 --- a/GenderPayGap.WebUI/Views/Scope/FinishOutOfScopeJourney.cshtml +++ b/GenderPayGap.WebUI/Views/Scope/FinishOutOfScopeJourney.cshtml @@ -8,7 +8,7 @@ } @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string reportingYearsString = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear.Year); string reason = Model.WhyOutOfScope == WhyOutOfScope.Under250 ? "My organisation had fewer than 250 employees on " + Model.ReportingYear.ToString("d MMMM yyyy") diff --git a/GenderPayGap.WebUI/Views/Scope/OutOfScopeQuestions.cshtml b/GenderPayGap.WebUI/Views/Scope/OutOfScopeQuestions.cshtml index d943b2f8e..63b6f658c 100644 --- a/GenderPayGap.WebUI/Views/Scope/OutOfScopeQuestions.cshtml +++ b/GenderPayGap.WebUI/Views/Scope/OutOfScopeQuestions.cshtml @@ -11,7 +11,7 @@ } @{ - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string reportingYearsString = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear.Year, "/"); var breadcrumbModel = new ManageOrganisationBreadcrumbs { diff --git a/GenderPayGap.WebUI/Views/Scope/ScopeDeclared.cshtml b/GenderPayGap.WebUI/Views/Scope/ScopeDeclared.cshtml index fba6f4ca0..9574883da 100644 --- a/GenderPayGap.WebUI/Views/Scope/ScopeDeclared.cshtml +++ b/GenderPayGap.WebUI/Views/Scope/ScopeDeclared.cshtml @@ -6,7 +6,7 @@ @{ ViewBag.Title = "Scope declared - Gender pay gap reporting service"; - string encryptedOrganisationId = Encryption.EncryptQuerystring(Model.Organisation.OrganisationId.ToString()); + string encryptedOrganisationId = Encryption.EncryptId(Model.Organisation.OrganisationId); string formattedReportingYears = ReportingYearsHelper.FormatYearAsReportingPeriod(Model.ReportingYear); } diff --git a/terraform/elasticbeanstalk.tf b/terraform/elasticbeanstalk.tf index 64251655d..2fc326577 100644 --- a/terraform/elasticbeanstalk.tf +++ b/terraform/elasticbeanstalk.tf @@ -426,6 +426,12 @@ resource "aws_elastic_beanstalk_environment" "gpg_elastic_beanstalk_environment" value = var.ELB_DEFAULT_ENCRYPTION_KEY } + setting { + namespace = "aws:elasticbeanstalk:application:environment" + name = "DefaultEncryptionIv" + value = var.ELB_DEFAULT_ENCRYPTION_IV + } + setting { namespace = "aws:elasticbeanstalk:application:environment" name = "DisableSearchCache" diff --git a/terraform/variables.tf b/terraform/variables.tf index a2f406a95..1fa5be0f4 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -118,6 +118,10 @@ variable "ELB_DEFAULT_ENCRYPTION_KEY" { type = string } +variable "ELB_DEFAULT_ENCRYPTION_IV" { + type = string +} + variable "ELB_DISABLE_SEARCH_CACHE" { type = string } From 99c1f585155ad9c066436278c02fb509169811b3 Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Wed, 6 Nov 2024 17:22:45 +0000 Subject: [PATCH 34/35] EHD-1411: Reduce code in Core project: Simplify Encryption: Fix unit tests --- .../RegistrationRepository/RemoveRegistrationTests.cs | 3 +++ .../RemoveRetiredUserRegistrationsTests.cs | 3 +++ .../Repositories/UserRepository/FindByEmailTests.cs | 4 ++++ .../Repositories/UserRepository/RetireUserTests.cs | 3 +++ .../Repositories/UserRepository/UpdateEmailTests.cs | 3 +++ .../Repositories/UserRepository/UpdatePasswordTests.cs | 3 +++ .../Controllers/Account/AccountCreationTests.cs | 7 +++++++ .../Controllers/Account/ChangeEmailTests.cs | 7 +++++++ .../Controllers/Account/ChangePasswordControllerTests.cs | 4 ++++ .../Controllers/Account/CloseAccountTests.cs | 2 ++ .../AdminDatabaseIntegrityChecksControllerTests.cs | 2 ++ .../Administration/AdminUnconfirmedPinsControllerTests.cs | 6 ++++++ .../PasswordReset/PasswordResetControllerTests.cs | 7 +++++++ .../Controllers/Scope/ScopeControllerTests.cs | 7 +++++++ .../GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs | 6 ++++++ 15 files changed, 67 insertions(+) diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRegistrationTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRegistrationTests.cs index ac8dcf5c1..390cab40d 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRegistrationTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRegistrationTests.cs @@ -2,6 +2,7 @@ using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; +using GenderPayGap.Extensions; using GenderPayGap.Tests.Common.Classes; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.TestHelpers; @@ -19,6 +20,8 @@ public class RemoveRegistrationTests [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + // mock data GpgDatabaseContext dbContext = AutoFacHelpers.CreateInMemoryTestDatabase(UserOrganisationHelper.CreateRegistrations()); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRetiredUserRegistrationsTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRetiredUserRegistrationsTests.cs index 9de44c418..7d22072a2 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRetiredUserRegistrationsTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/RegistrationRepository/RemoveRetiredUserRegistrationsTests.cs @@ -2,6 +2,7 @@ using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; +using GenderPayGap.Extensions; using GenderPayGap.Tests.Common.Classes; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.TestHelpers; @@ -19,6 +20,8 @@ public class RemoveRetiredUserRegistrationsTests [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + // mock data GpgDatabaseContext dbContext = AutoFacHelpers.CreateInMemoryTestDatabase(UserOrganisationHelper.CreateRegistrations()); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/FindByEmailTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/FindByEmailTests.cs index 36dbf7276..c24ed31d0 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/FindByEmailTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/FindByEmailTests.cs @@ -2,10 +2,12 @@ using GenderPayGap.Core; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; +using GenderPayGap.Extensions; using GenderPayGap.Tests.Common.Classes; using GenderPayGap.Tests.Common.TestHelpers; using GenderPayGap.WebUI.BusinessLogic.Abstractions; using GenderPayGap.WebUI.Services; +using GenderPayGap.WebUI.Tests.TestHelpers; using Moq; using NUnit.Framework; @@ -20,6 +22,8 @@ public class FindByEmailTests [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + // mock data mockDataRepo = new Mock().SetupGetAll(UserHelpers.CreateUsers()); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/RetireUserTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/RetireUserTests.cs index b3b0cdc88..0c0f373f4 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/RetireUserTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/RetireUserTests.cs @@ -7,6 +7,7 @@ using GenderPayGap.Tests.Common.TestHelpers; using GenderPayGap.WebUI.BusinessLogic.Abstractions; using GenderPayGap.WebUI.Services; +using GenderPayGap.WebUI.Tests.TestHelpers; using Moq; using NUnit.Framework; @@ -21,6 +22,8 @@ public class RetireUserTests [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + // mock data mockDataRepo = new Mock().SetupGetAll(UserHelpers.CreateUsers()); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdateEmailTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdateEmailTests.cs index a00b7c3a9..ebb7b93bd 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdateEmailTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdateEmailTests.cs @@ -7,6 +7,7 @@ using GenderPayGap.Tests.Common.TestHelpers; using GenderPayGap.WebUI.BusinessLogic.Abstractions; using GenderPayGap.WebUI.Services; +using GenderPayGap.WebUI.Tests.TestHelpers; using Moq; using NUnit.Framework; @@ -21,6 +22,8 @@ public class UpdateEmailTests [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + // mock data mockDataRepo = new Mock().SetupGetAll(UserHelpers.CreateUsers()); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs index 3d80e2f35..c28ac4dfc 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/BusinessLogicTests/Repositories/UserRepository/UpdatePasswordTests.cs @@ -8,6 +8,7 @@ using GenderPayGap.WebUI.BusinessLogic.Abstractions; using GenderPayGap.WebUI.Helpers; using GenderPayGap.WebUI.Services; +using GenderPayGap.WebUI.Tests.TestHelpers; using Moq; using NUnit.Framework; @@ -22,6 +23,8 @@ public class UpdatePasswordTests [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + // mock data mockDataRepo = new Mock().SetupGetAll(UserHelpers.CreateUsers()); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs index ab981a484..f572514b0 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/AccountCreationTests.cs @@ -7,6 +7,7 @@ using GenderPayGap.WebUI.Models.AccountCreation; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; +using GenderPayGap.WebUI.Tests.TestHelpers; using Microsoft.AspNetCore.Mvc; using NUnit.Framework; @@ -16,6 +17,12 @@ namespace GenderPayGap.WebUI.Tests.Controllers.Account [SetCulture("en-GB")] public class AccountCreationTests { + + [SetUp] + public void SetUp() + { + UiTestHelper.SetDefaultEncryptionKeys(); + } [Test] [Description("POST: Verification email is sent after creating a user account")] diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs index 7f06ac8fa..c3a5c1bfa 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangeEmailTests.cs @@ -8,6 +8,7 @@ using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; +using GenderPayGap.WebUI.Tests.TestHelpers; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.Account @@ -17,6 +18,12 @@ namespace GenderPayGap.WebUI.Tests.Controllers.Account public class ChangeEmailTests { + [SetUp] + public void SetUp() + { + UiTestHelper.SetDefaultEncryptionKeys(); + } + [Test] [Description("POST: Providing a valid new email address results in a verification email being sent")] public void POST_Providing_A_Valid_New_Email_Address_Results_In_A_Verification_Email_Being_Sent() diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs index 2b4fbbd08..ba4c36a62 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/ChangePasswordControllerTests.cs @@ -5,12 +5,14 @@ using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; using GenderPayGap.Database.Models; +using GenderPayGap.Extensions; using GenderPayGap.WebUI.BusinessLogic.Abstractions; using GenderPayGap.WebUI.Controllers.Account; using GenderPayGap.WebUI.ExternalServices; using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; +using GenderPayGap.WebUI.Tests.TestHelpers; using GovUkDesignSystem.Attributes.ValidationAttributes; using Microsoft.AspNetCore.Mvc; using Moq; @@ -29,6 +31,8 @@ public class ChangePasswordControllerTests [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + // mock data mockDataRepo = new Mock(); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs index cadd103e9..de9f41d67 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Account/CloseAccountTests.cs @@ -7,6 +7,7 @@ using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; +using GenderPayGap.WebUI.Tests.TestHelpers; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.Account @@ -19,6 +20,7 @@ public class CloseAccountTests [SetUp] public void Setup() { + UiTestHelper.SetDefaultEncryptionKeys(); VirtualDateTime.Initialise(Config.OffsetCurrentDateTimeForSite()); } diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs index 7eebd47a5..8366b8cb1 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminDatabaseIntegrityChecksControllerTests.cs @@ -85,6 +85,8 @@ private static Return CreateReturn(long organisationId) [SetUp] public void BeforeEach() { + UiTestHelper.SetDefaultEncryptionKeys(); + organisation = CreateOrganisation(); user = CreateUser(); userOrganisation = CreateUserOrganisation(organisation, user.UserId); diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminUnconfirmedPinsControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminUnconfirmedPinsControllerTests.cs index a6a486979..24f909003 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminUnconfirmedPinsControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Administration/AdminUnconfirmedPinsControllerTests.cs @@ -49,6 +49,12 @@ private static User CreateUser(long userId, string emailAddress) }; } + [SetUp] + public void BeforeEach() + { + UiTestHelper.SetDefaultEncryptionKeys(); + } + [Test] [Description("AdminUnconfirmedPinsController POST: When PIN has expired create new PIN and send email")] public void AdminUnconfirmedPinsController_POST_When_PIN_has_expired_create_new_PIN_and_send_email() diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs index 9b5e0f4d2..2a52ed032 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/PasswordReset/PasswordResetControllerTests.cs @@ -10,6 +10,7 @@ using GenderPayGap.WebUI.Models.Account; using GenderPayGap.WebUI.Services; using GenderPayGap.WebUI.Tests.Builders; +using GenderPayGap.WebUI.Tests.TestHelpers; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.PasswordReset @@ -19,6 +20,12 @@ namespace GenderPayGap.WebUI.Tests.Controllers.PasswordReset public class PasswordResetControllerTests { + [SetUp] + public void BeforeEach() + { + UiTestHelper.SetDefaultEncryptionKeys(); + } + [Test] [Description("POST: Password reset email is sent when valid email address is provided")] public void POST_Password_Reset_Email_Is_Sent_When_Valid_Email_Address_Is_Provided() diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs index 92cdd9b1d..3298b68f2 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/Controllers/Scope/ScopeControllerTests.cs @@ -4,6 +4,7 @@ using GenderPayGap.WebUI.Controllers; using GenderPayGap.WebUI.Models.ScopeNew; using GenderPayGap.WebUI.Tests.Builders; +using GenderPayGap.WebUI.Tests.TestHelpers; using NUnit.Framework; namespace GenderPayGap.WebUI.Tests.Controllers.Scope @@ -13,6 +14,12 @@ namespace GenderPayGap.WebUI.Tests.Controllers.Scope public class ScopeControllerTests { + [SetUp] + public void BeforeEach() + { + UiTestHelper.SetDefaultEncryptionKeys(); + } + [Test] [Description("POST: Existing scopes are retired when a new scope is added")] public void POST_Existing_Scopes_Are_Retired_When_New_Scope_Is_Added() diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs index 9678d918c..72c5a8d7c 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs @@ -9,6 +9,7 @@ using GenderPayGap.Core.Classes; using GenderPayGap.Core.Interfaces; using GenderPayGap.Database; +using GenderPayGap.Extensions; using GenderPayGap.Extensions.AspNetCore; using GenderPayGap.Tests.Common.Classes; using GenderPayGap.Tests.Common.TestHelpers; @@ -354,5 +355,10 @@ private static MethodBase FindParentMethodWithTestAttribute(MethodBase callingMe return callingMethod; } + public static void SetDefaultEncryptionKeys() + { + Encryption.SetDefaultEncryptionKey("BA9138B8C0724F168A05482456802405", "45fc394a7f5b29f660bfdf3313224dac"); + } + } } From ad4f79ba91fec5609046592727515d08ce5eac5d Mon Sep 17 00:00:00 2001 From: James Griffiths Date: Fri, 8 Nov 2024 13:17:45 +0000 Subject: [PATCH 35/35] EHD-1411: Reduce code in Core project: Remove / simplify some unused testing code --- .../AutoFacExtensions.cs | 25 ------------------- .../TestHelpers/UiTestHelpers.cs | 8 ++---- 2 files changed, 2 insertions(+), 31 deletions(-) delete mode 100644 GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/AutoFacExtensions.cs diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/AutoFacExtensions.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/AutoFacExtensions.cs deleted file mode 100644 index 871919752..000000000 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/AutoFacExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Autofac; -using GenderPayGap.WebUI.Tests.TestHelpers; -using Moq; - -namespace GenderPayGap.WebUI.Tests -{ - public static class AutoFacExtensions - { - /// - /// Retrieve an instance from the DependencyResolver and returns a mocked instance - /// - /// - /// - public static Mock ResolveAsMock(bool callbase = false) where TInstance : class - { - // get the instance form the Inversion of Control locator - TInstance instance = UiTestHelper.DIContainer.Resolve(); - - // generate and return the mocked instance - var mockedInstance = Mock.Get(instance); - mockedInstance.CallBase = callbase; - return mockedInstance; - } - } -} diff --git a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs index 72c5a8d7c..1bc485b73 100644 --- a/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs +++ b/GenderPayGap.UnitTests/GenderPayGap.WebUI.Tests/TestHelpers/UiTestHelpers.cs @@ -47,16 +47,12 @@ namespace GenderPayGap.WebUI.Tests.TestHelpers public static class UiTestHelper { - private const string Url = "https://localhost/"; - public static IContainer DIContainer; public static Mock MockBackgroundJobsApi; - public static Uri Uri => new Uri(Url, UriKind.Absolute); - public static T GetController(long userId = 0, RouteData routeData = null, params object[] dbObjects) where T : Controller { - DIContainer = BuildContainerIoC(dbObjects); + IContainer DIContainer = BuildContainerIoC(dbObjects); //Create Inversion of Control container Startup.ContainerIoC = DIContainer; @@ -140,7 +136,7 @@ public static T GetController(long userId = 0, RouteData routeData = null, pa responseMock.SetupGet(x => x.Cookies).Returns(responseCookies.Object); //Mock session - var uri = new UriBuilder(Uri); + var uri = new UriBuilder(new Uri("https://localhost/", UriKind.Absolute)); //Mock HttpContext var httpContextMock = new Mock();