diff --git a/solution/WebApplication/WebApplication/Controllers/TaskGroupDependencyController.cs b/solution/WebApplication/WebApplication/Controllers/TaskGroupDependencyController.cs index 565e0f45..c59f5628 100644 --- a/solution/WebApplication/WebApplication/Controllers/TaskGroupDependencyController.cs +++ b/solution/WebApplication/WebApplication/Controllers/TaskGroupDependencyController.cs @@ -252,7 +252,8 @@ namespace WebApplication.Controllers //filter the list by permitted roles if (!CanPerformCurrentActionGlobally()) { - var requiredRoles = GetPermittedRolesForCurrentAction(); + //TODO: Test that the change from GetPermittedRolesForCurrentAction didnt' break this + var requiredRoles = GetPermittedGroupsForCurrentAction(); var filteredTaskGroups = from tg in _context.TaskGroup diff --git a/solution/WebApplication/WebApplication/Controllers/WizardsController.cs b/solution/WebApplication/WebApplication/Controllers/WizardsController.cs index 7cdeaaa0..02dc7750 100644 --- a/solution/WebApplication/WebApplication/Controllers/WizardsController.cs +++ b/solution/WebApplication/WebApplication/Controllers/WizardsController.cs @@ -23,22 +23,16 @@ namespace WebApplication.Controllers public class WizardsController : BaseController { private readonly AdsGoFastContext _context; - private readonly Services.IMicrosoftGraphService _graphService; - private readonly IEmailService _emailService; - private readonly ProcessingFunctionClient _processingClient; + private readonly IMicrosoftGraphService _graphService; public WizardsController(AdsGoFastContext context, Services.ISecurityAccessProvider securityProvider, Services.IEntityRoleProvider roleProvider, - Services.IMicrosoftGraphService graphService, - Services.IEmailService emailService, - ProcessingFunctionClient processingClient) + IMicrosoftGraphService graphService) : base(securityProvider, roleProvider) { _context = context; _graphService = graphService; - _emailService = emailService; - _processingClient = processingClient; } [HttpGet] @@ -64,7 +58,7 @@ namespace WebApplication.Controllers //ViewBag.PhnZones = new SelectList(new List(phnZones) // .OrderBy(x => x.Name), "Id", "Name"); - var users = await GetPHNUsers(); + var users = await GetUsers(); ViewBag.PHNUsers = new SelectList(users.OrderBy(x => x.DisplayName), "UserId", "DisplayName"); } @@ -162,8 +156,11 @@ namespace WebApplication.Controllers { // notify all phn users whose roles are set throgh the form by email string[] stewards = PIA.DataStewards.Select(ds => ds.UserId).ToArray(); - await _emailService.SendNotificationToPHNUsers(PIA.DataOwner.UserId, PIA.DataCustodian.UserId, stewards); - await _processingClient.QueueSubjectAreaProvisioning(PIA.SubjectAreaId); + + SendNotificationToSubjectAreaUsers(); + + DoProcessingAndAutomationForSubjectArea(); + // Redirect out of wizard and return RedirectToAction("Details", "SubjectArea", new { id = PIA.SubjectAreaId }); } @@ -184,6 +181,17 @@ namespace WebApplication.Controllers return View(nameof(PIAWizard), PIA); } + private void DoProcessingAndAutomationForSubjectArea() + { + // TODO: + // If there are any automation steps like setting up security access / Azure AD security groups etc + } + + private void SendNotificationToSubjectAreaUsers() + { + //TODO: Send emails to PIA.DataOwner.UserId, PIA.DataCustodian.UserId, and stewards + } + private async Task UpdatePIAData(PIAWizardViewModel PIA) { var subjectArea = await _context.SubjectArea.FindAsync(PIA.SubjectAreaId); @@ -223,10 +231,9 @@ namespace WebApplication.Controllers [HttpPost] public async Task AddDataSteward([Bind("DataStewards")] PIAWizardViewModel pia) { - var testData = await GetPHNUsers(); + var users = await GetUsers(); - ViewBag.PHNUsers = new SelectList(testData, - "UserId", "DisplayName"); + ViewBag.PHNUsers = new SelectList(users, "UserId", "DisplayName"); var dataSteward = new UserReference(); @@ -238,9 +245,9 @@ namespace WebApplication.Controllers [HttpPost] public async Task RemoveDataSteward([Bind("DataStewards")] PIAWizardViewModel pia) { - var PHNUsers = await GetPHNUsers(); + var users = await GetUsers(); - ViewBag.PHNUsers = new SelectList(PHNUsers, + ViewBag.PHNUsers = new SelectList(users, "UserId", "DisplayName"); // find better way to do this if (pia.DataStewards.Count > 1) @@ -251,7 +258,7 @@ namespace WebApplication.Controllers return PartialView("_DataStewards", pia); } - private async Task> GetPHNUsers() + private async Task> GetUsers() { var members = await _graphService.GetMembers(); diff --git a/solution/WebApplication/WebApplication/Models/UserReference.cs b/solution/WebApplication/WebApplication/Models/UserReference.cs index 2fd5a768..b328bb3a 100644 --- a/solution/WebApplication/WebApplication/Models/UserReference.cs +++ b/solution/WebApplication/WebApplication/Models/UserReference.cs @@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations; using Newtonsoft.Json; -namespace WebApplication.Models.Forms +namespace WebApplication.Models { public class UserReference { diff --git a/solution/WebApplication/WebApplication/Services/EmailService.cs b/solution/WebApplication/WebApplication/Services/EmailService.cs deleted file mode 100644 index 9ccc4942..00000000 --- a/solution/WebApplication/WebApplication/Services/EmailService.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using SharedZone.Client.Model; - -namespace WebApplication.Services -{ - public class EmailService : IEmailService - { - private readonly IMicrosoftGraphService _graphService; - private readonly ISharedZoneService _sharedZoneService; - - public EmailService(IMicrosoftGraphService graphService, ISharedZoneService sharedZoneService) - { - _graphService = graphService; - _sharedZoneService = sharedZoneService; - } - - public async Task SendDatasetAccessApprovalNotification(string requestor, SubjectArea subjectArea) - { - var sendToEmail = await _graphService.GetUserMailIdentity(requestor); - await _sharedZoneService.PostEmailToQueue(Guid.NewGuid().ToString(), default, sendToEmail, "DataSetAccessRequestAccepted", new - { - RequestorName = sendToEmail.name, - SubjectAreaName = subjectArea.SubjectAreaName, - }); - } - - public async Task SendDatasetAccessRejectionNotification(string requestor, SubjectArea subjectArea) - { - var sendToEmail = await _graphService.GetUserMailIdentity(requestor); - await _sharedZoneService.PostEmailToQueue(Guid.NewGuid().ToString(), default, sendToEmail, "DataSetAccessRequestRejected", new - { - RequestorName = sendToEmail.name, - SubjectAreaName = subjectArea.SubjectAreaName, - }); - } - - public async Task SendDatasetAccessRequestNotification(string recipient, string requestor, SubjectArea subjectArea) - { - var sendToEmail = await _graphService.GetUserMailIdentity(recipient); - var requestingUser = await _graphService.GetUserMailIdentity(requestor); - - await _sharedZoneService.PostEmailToQueue(Guid.NewGuid().ToString(), default, sendToEmail, "DataSetAccessRequestCreated", new - { - RequestorName = requestingUser.name, - RecipientName = sendToEmail.name, - dataSetName = subjectArea.SubjectAreaName - }); - } - - public async Task SendNotificationToPHNUsers(string owner, string custodian, string[] stewards) - { - //todo: this doesnt' do anything, but where it's being called doesn't actually calculate the delta - //we should change this to send out the email when syncing teh AD groups - so if you are added to the AD group you - //get an email. - } - - } -} diff --git a/solution/WebApplication/WebApplication/Services/EntityRoleProvider.cs b/solution/WebApplication/WebApplication/Services/EntityRoleProvider.cs index de713290..c59cf025 100644 --- a/solution/WebApplication/WebApplication/Services/EntityRoleProvider.cs +++ b/solution/WebApplication/WebApplication/Services/EntityRoleProvider.cs @@ -28,8 +28,8 @@ namespace WebApplication.Services return await LoadSubjectAreaRoles(x.SubjectAreaId, groups); case SubjectAreaForm x: return await LoadSubjectAreaFormRoles(x.SubjectAreaFormId, groups); - case TaskGroup x when x.SubjectAreaId.HasValue: - return await LoadSubjectAreaRoles(x.SubjectAreaId.Value, groups); + case TaskGroup x: + return await LoadSubjectAreaRoles(x.SubjectAreaId, groups); case TaskInstance x: return await LoadTaskInstanceRoles(x.TaskInstanceId, groups); case TaskInstanceExecution x: diff --git a/solution/WebApplication/WebApplication/Services/IEmailService.cs b/solution/WebApplication/WebApplication/Services/IEmailService.cs deleted file mode 100644 index b3985b2c..00000000 --- a/solution/WebApplication/WebApplication/Services/IEmailService.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Threading.Tasks; -using SharedZone.Client.Model; - -namespace WebApplication.Services -{ - public interface IEmailService - { - Task SendDatasetAccessRejectionNotification(string requestor, SubjectArea subjectArea); - Task SendDatasetAccessApprovalNotification(string requestor, SubjectArea subjectArea); - Task SendDatasetAccessRequestNotification(string recipient, string requestor, SubjectArea subjectArea); - Task SendNotificationToPHNUsers(string owner, string custodian, string[] stewards); - } -} \ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Services/IMicrosoftGraphService.cs b/solution/WebApplication/WebApplication/Services/IMicrosoftGraphService.cs index 52027bf7..3808585a 100644 --- a/solution/WebApplication/WebApplication/Services/IMicrosoftGraphService.cs +++ b/solution/WebApplication/WebApplication/Services/IMicrosoftGraphService.cs @@ -1,14 +1,11 @@ using System.Collections.Generic; using System.Threading.Tasks; -using WebApplication.Forms.PIAWizard; using WebApplication.Models; -using WebApplication.Models.Forms; namespace WebApplication.Services { public interface IMicrosoftGraphService { Task> GetMembers(); - Task<(string name, string email)> GetUserMailIdentity(string upn); } } \ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Services/MicrosoftGraphService.cs b/solution/WebApplication/WebApplication/Services/MicrosoftGraphService.cs index 75783220..702b4f07 100644 --- a/solution/WebApplication/WebApplication/Services/MicrosoftGraphService.cs +++ b/solution/WebApplication/WebApplication/Services/MicrosoftGraphService.cs @@ -1,16 +1,13 @@ using Microsoft.Extensions.Options; using Microsoft.Graph; -using Microsoft.Graph.Auth; using Microsoft.Identity.Client; using Microsoft.Identity.Web; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using WebApplication.Forms.PIAWizard; using WebApplication.Models; using WebApplication.Models.Options; -using System.Security.Claims; namespace WebApplication.Services { @@ -31,8 +28,9 @@ namespace WebApplication.Services .WithClientSecret(_azureOptions.Value.ClientSecret) .Build(); - ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClient); - _graphServiceClient = new GraphServiceClient(authProvider); + //TODO: Fix the graph serice client auth (we removed the obsolete Graph.Auth package dependency + //ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClient); + //_graphServiceClient = new GraphServiceClient(); } public async Task> GetMembers() diff --git a/solution/WebApplication/WebApplication/Services/ProcessingFunctionClient.cs b/solution/WebApplication/WebApplication/Services/ProcessingFunctionClient.cs deleted file mode 100644 index 874d58a7..00000000 --- a/solution/WebApplication/WebApplication/Services/ProcessingFunctionClient.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Net; -using System.Net.Http; -using System.Net.Http.Json; -using System.Threading.Tasks; -using Azure.Storage.Queues; -using Azure.Storage.Queues.Specialized; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; -using WebApplication.Models.Options; - -namespace WebApplication.Services -{ - public class ProcessingFunctionClient - { - private readonly IConfiguration _config; - private readonly string QueueName = "subjectareaprocessing"; - - public ProcessingFunctionClient(HttpClient httpClient, IConfiguration config) - { - _config = config; - - } - - public async Task QueueSubjectAreaProvisioning(int subjectAreaId) - { - var connectionString = GetConnectionStringOrSetting(_config, "AzureWebJobsStorage"); - QueueClient queue = new QueueClient(connectionString, QueueName, new QueueClientOptions() - { - MessageEncoding = QueueMessageEncoding.Base64, - }); - - await queue.CreateIfNotExistsAsync(); - await queue.SendMessageAsync(subjectAreaId.ToString()); - } - - - //todo: figure out where this acctually lives it should be an extension method... - string GetConnectionStringOrSetting(IConfiguration configuration, string connectionName) => - configuration.GetConnectionString(connectionName) ?? configuration[connectionName]; - } - - -} diff --git a/solution/WebApplication/WebApplication/Services/SecurityAccessProvider.cs b/solution/WebApplication/WebApplication/Services/SecurityAccessProvider.cs index ee44c713..33337b0f 100644 --- a/solution/WebApplication/WebApplication/Services/SecurityAccessProvider.cs +++ b/solution/WebApplication/WebApplication/Services/SecurityAccessProvider.cs @@ -110,9 +110,9 @@ namespace WebApplication.Services //Next Get Role based on App Roles roles = GetUserRoles(identity); } - + if (roles.Any() && !roles.Contains("Reader")) - roles.Add("Reader"); + roles = roles.Append("Reader").ToArray(); return roles; } diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataBreachImpactManagement.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataBreachImpactManagement.cshtml new file mode 100644 index 00000000..56a3c208 --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataBreachImpactManagement.cshtml @@ -0,0 +1,15 @@ +@model WebApplication.Models.InputSelectionOptionsFor +
+ @for (int i = 0; i < Model.Options.Count; i++) + { +
+ + + +
+
+ } + +
\ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataBreachPlan.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataBreachPlan.cshtml new file mode 100644 index 00000000..4ecb8c5a --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataBreachPlan.cshtml @@ -0,0 +1,15 @@ +@model WebApplication.Models.InputSelectionOptionsFor +
+ @for (int i = 0; i < Model.Options.Count; i++) + { +
+ + + +
+
+ } + +
\ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataModification.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataModification.cshtml new file mode 100644 index 00000000..9c6b9262 --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForDataModification.cshtml @@ -0,0 +1,15 @@ +@model WebApplication.Models.InputSelectionOptionsFor +
+ @for (int i = 0; i < Model.Options.Count; i++) + { +
+ + + +
+
+ } + +
\ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForEnvironmentReconfigurations.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForEnvironmentReconfigurations.cshtml new file mode 100644 index 00000000..ed25a4bd --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForEnvironmentReconfigurations.cshtml @@ -0,0 +1,15 @@ +@model WebApplication.Models.InputSelectionOptionsFor +
+ @for (int i = 0; i < Model.Options.Count; i++) + { +
+ + + +
+
+ } + +
\ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForProperties.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForProperties.cshtml new file mode 100644 index 00000000..d4f2bfbb --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForProperties.cshtml @@ -0,0 +1,15 @@ +@model WebApplication.Models.InputSelectionOptionsFor +
+ @for (int i = 0; i < Model.Options.Count; i++) + { +
+ + + +
+
+ } + +
\ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForSpecifications.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForSpecifications.cshtml new file mode 100644 index 00000000..253ee510 --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForSpecifications.cshtml @@ -0,0 +1,16 @@ +@model WebApplication.Models.InputSelectionOptionsFor + +
+ @for (int i = 0; i < Model.Options.Count; i++) + { +
+ + + +
+
+ } + +
\ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForStakeholderAssuranceProtection.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForStakeholderAssuranceProtection.cshtml new file mode 100644 index 00000000..5cf793b1 --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/EditorForStakeholderAssuranceProtection.cshtml @@ -0,0 +1,15 @@ +@model WebApplication.Models.InputSelectionOptionsFor +
+ @for (int i = 0; i < Model.Options.Count; i++) + { +
+ + + +
+
+ } + +
\ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/ExternalUsers.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/ExternalUsers.cshtml new file mode 100644 index 00000000..8d75ec23 --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/ExternalUsers.cshtml @@ -0,0 +1,6 @@ +@model IList +@for (int i = 0; i < Model.Count(); i++) +{ + @Html.HiddenFor(m => Model[i].UserId) + @Html.HiddenFor(m => Model[i].DisplayName) +} \ No newline at end of file diff --git a/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/UserReference.cshtml b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/UserReference.cshtml new file mode 100644 index 00000000..76e51e5a --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/EditorTemplates/UserReference.cshtml @@ -0,0 +1,5 @@ +@model UserReference; +
+ @Html.DropDownListFor(model => model.UserId, ViewBag.PHNUsers as SelectList, "Select User", new { @class = "form-control", @id = "nameDroplist", @onchange = "setDisplayName(this)", @required = "required" }) + @Html.HiddenFor(model => model.DisplayName) +
diff --git a/solution/WebApplication/WebApplication/Views/Shared/_DataStewards.cshtml b/solution/WebApplication/WebApplication/Views/Shared/_DataStewards.cshtml new file mode 100644 index 00000000..179d8887 --- /dev/null +++ b/solution/WebApplication/WebApplication/Views/Shared/_DataStewards.cshtml @@ -0,0 +1,2 @@ +@model WebApplication.Models.Wizards.PIAWizardViewModel; +@Html.EditorFor(model => model.DataStewards, new { @class = "form-control" }) diff --git a/solution/WebApplication/WebApplication/Views/SubjectArea/Edit.cshtml b/solution/WebApplication/WebApplication/Views/SubjectArea/Edit.cshtml index 8136dc46..b1d059fa 100644 --- a/solution/WebApplication/WebApplication/Views/SubjectArea/Edit.cshtml +++ b/solution/WebApplication/WebApplication/Views/SubjectArea/Edit.cshtml @@ -1,4 +1,5 @@ @using Humanizer; +@using WebApplication.Controllers @model WebApplication.Models.SubjectArea @{ diff --git a/solution/WebApplication/WebApplication/Views/Wizards/ExternalFileUpload.cshtml b/solution/WebApplication/WebApplication/Views/Wizards/ExternalFileUpload.cshtml index 83d465af..36752d0e 100644 --- a/solution/WebApplication/WebApplication/Views/Wizards/ExternalFileUpload.cshtml +++ b/solution/WebApplication/WebApplication/Views/Wizards/ExternalFileUpload.cshtml @@ -164,7 +164,9 @@

- + + @*TODO: Fix this + *@
diff --git a/solution/WebApplication/WebApplication/Views/Wizards/_PIAWizardStep1.cshtml b/solution/WebApplication/WebApplication/Views/Wizards/_PIAWizardStep1.cshtml index 03136f31..72eaafb3 100644 --- a/solution/WebApplication/WebApplication/Views/Wizards/_PIAWizardStep1.cshtml +++ b/solution/WebApplication/WebApplication/Views/Wizards/_PIAWizardStep1.cshtml @@ -105,8 +105,8 @@
- @Html.DropDownListFor(model => model.PhnZone.Id, ViewBag.PhnZones as SelectList, "Select Your PHN Zone", new { @class = "form-control", @id = "dsSelection" }) - @Html.HiddenFor(model => model.PhnZone.Name, new { @id = "hiddenPhnName"}) + @Html.DropDownListFor(model => model.Site.Id, ViewBag.PhnZones as SelectList, "Select Your PHN Zone", new { @class = "form-control", @id = "dsSelection" }) + @Html.HiddenFor(model => model.Site.Name, new { @id = "hiddenPhnName"})
diff --git a/solution/WebApplication/WebApplication/WebApplication.csproj b/solution/WebApplication/WebApplication/WebApplication.csproj index 06c7d765..c17432f3 100644 --- a/solution/WebApplication/WebApplication/WebApplication.csproj +++ b/solution/WebApplication/WebApplication/WebApplication.csproj @@ -60,6 +60,7 @@ + @@ -72,6 +73,18 @@ + + + + + + + + + + + +