diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserDataService.cs index 8b1266362a..ca48e7e67b 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserDataService.cs @@ -389,7 +389,15 @@ public void DeactivateDelegateUser(int delegateId) new { delegateId } ); } - + public void DeactivateAdminAccount(int userId ,int centreId) + { + connection.Execute( + @"UPDATE AdminAccounts + SET Active =0 + WHERE UserID = @userId AND CentreID = @centreId", + new { userId, centreId } + ); + } public void ActivateDelegateUser(int delegateId) { connection.Execute( @@ -419,7 +427,15 @@ FROM Candidates new { delegateId } ).Single(); } - + public int? CheckDelegateIsActive(int delegateId) + { + return connection.Query( + @"SELECT CandidateID + FROM Candidates + WHERE CandidateID = @delegateId AND Active =1", + new { delegateId } + ).FirstOrDefault(); + } public void SetDelegateUserLearningHubAuthId(int delegateId, int learningHubAuthId) { connection.Execute( diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs index 978364ce77..aba887ccf5 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs @@ -291,6 +291,8 @@ int centreId public bool PrimaryEmailInUseAtCentres(string email); public int? GetUserIdFromLearningHubAuthId(int learningHubAuthId); + void DeactivateAdminAccount(int userId, int centreId); + int? CheckDelegateIsActive(int delegateId); } public partial class UserDataService : IUserDataService diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/DeactivateDelegateController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/DeactivateDelegateController.cs new file mode 100644 index 0000000000..42e1e231ae --- /dev/null +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/DeactivateDelegateController.cs @@ -0,0 +1,95 @@ + + +namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Delegates +{ + using System.Collections.Generic; + using System.Linq; + using DigitalLearningSolutions.Data.Enums; + using DigitalLearningSolutions.Data.Models.User; + using DigitalLearningSolutions.Web.Attributes; + using DigitalLearningSolutions.Web.Helpers; + using DigitalLearningSolutions.Web.Models.Enums; + using DigitalLearningSolutions.Web.ServiceFilter; + using DigitalLearningSolutions.Web.Services; + using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates.DeactivateDelegate; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + using Microsoft.FeatureManagement.Mvc; + + + [FeatureGate(FeatureFlags.RefactoredTrackingSystem)] + [Authorize(Policy = CustomPolicies.UserCentreAdmin)] + [ServiceFilter(typeof(VerifyAdminUserCanAccessDelegateUser))] + [Route("TrackingSystem/Delegates/{delegateId:int}/Deactivate")] + [SetDlsSubApplication(nameof(DlsSubApplication.TrackingSystem))] + [SetSelectedTab(nameof(NavMenuTab.Delegates))] + public class DeactivateDelegateController : Controller + { + private readonly IUserService userService; + public DeactivateDelegateController( + IUserService userService + ) + { + this.userService = userService; + } + [HttpGet] + public IActionResult Index(int delegateId) + { + var checkDelegate = userService.CheckDelegateIsActive(delegateId); + if (checkDelegate != delegateId) + { + return RedirectToAction("StatusCode", "LearningSolutions", new { code = 410 }); + } + var centreId = User.GetCentreId(); + var delegateEntity = userService.GetDelegateById(delegateId)!; + var userEntity = userService.GetUserById(delegateEntity.DelegateAccount.UserId); + var adminAccount = userEntity!.GetCentreAccountSet(centreId)?.AdminAccount; + var roles = GetRoles(adminAccount, userEntity); + var model = new DeactivateDelegateAccountViewModel + { + DelegateId = delegateId, + Name = delegateEntity.UserAccount.FirstName + " " + delegateEntity.UserAccount.LastName, + Roles = roles, + Email = delegateEntity.UserAccount.PrimaryEmail, + UserId = delegateEntity.UserAccount.Id + }; + return View(model); + } + + [HttpPost] + public IActionResult Index(DeactivateDelegateAccountViewModel deactivateDelegateAccountViewModel) + { + var centreId = User.GetCentreId(); + if (!ModelState.IsValid) + { + var delegateEntity = userService.GetDelegateById(deactivateDelegateAccountViewModel.DelegateId)!; + var userEntity = userService.GetUserById(delegateEntity.DelegateAccount.UserId); + var adminAccount = userEntity!.GetCentreAccountSet(centreId)?.AdminAccount; + var roles = GetRoles(adminAccount, userEntity); + deactivateDelegateAccountViewModel.Roles = roles; + return View(deactivateDelegateAccountViewModel); + } + + if (deactivateDelegateAccountViewModel.Deactivate == true ) + { + userService.DeactivateDelegateUser(deactivateDelegateAccountViewModel.DelegateId); + return RedirectToAction("Index", "ViewDelegate", new { deactivateDelegateAccountViewModel.DelegateId }); + } + userService.DeactivateDelegateUser(deactivateDelegateAccountViewModel.DelegateId); + userService.DeactivateAdminAccount(deactivateDelegateAccountViewModel.UserId, centreId.Value); + return RedirectToAction("Index", "ViewDelegate", new { deactivateDelegateAccountViewModel.DelegateId }); + + } + private List? GetRoles(AdminAccount? adminAccount, UserEntity userEntity) + { + var roles = new List(); + if (adminAccount != null) + { + var adminentity = new AdminEntity(adminAccount, userEntity.UserAccount, null); + roles = FilterableTagHelper.GetCurrentTagsForAdmin(adminentity).Where(s => s.Hidden == false) + .Select(d => d.DisplayText).ToList(); + } + return roles; + } + } +} diff --git a/DigitalLearningSolutions.Web/Services/UserService.cs b/DigitalLearningSolutions.Web/Services/UserService.cs index f950362d2c..6465b9a2c4 100644 --- a/DigitalLearningSolutions.Web/Services/UserService.cs +++ b/DigitalLearningSolutions.Web/Services/UserService.cs @@ -194,6 +194,8 @@ bool isWorkforceManager string search, int offset, int rows, int jobGroupId, string userStatus, string emailStatus, int userId, int failedLoginThreshold ); void UpdateUserDetailsAccount(string firstName, string lastName, string primaryEmail, int jobGroupId, string? prnNumber, DateTime? emailVerified, int userId); + void DeactivateAdminAccount(int userId, int centreId); + int? CheckDelegateIsActive(int delegateId); } public class UserService : IUserService @@ -956,5 +958,13 @@ public void UpdateUserDetailsAccount(string firstName, string lastName, string p { userDataService.UpdateUserDetailsAccount(firstName, lastName, primaryEmail, jobGroupId, prnNumber, emailVerified, userId); } + public void DeactivateAdminAccount(int userId, int centreId) + { + userDataService.DeactivateAdminAccount(userId, centreId); + } + public int? CheckDelegateIsActive(int delegateId) + { + return userDataService.CheckDelegateIsActive(delegateId); + } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DeactivateDelegate/DeactivateDelegateAccountViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DeactivateDelegate/DeactivateDelegateAccountViewModel.cs new file mode 100644 index 0000000000..c6a3a5f1f3 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DeactivateDelegate/DeactivateDelegateAccountViewModel.cs @@ -0,0 +1,17 @@ +using FluentMigrator.Infrastructure; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates.DeactivateDelegate +{ + public class DeactivateDelegateAccountViewModel + { + public int DelegateId { get; set; } + public int UserId { get; set; } + public string Name { get; set; } + public string Email { get; set; } + public List Roles { get; set; } + [Required(ErrorMessage = "Please select an account you want to deactivate.")] + public bool? Deactivate { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DeactivateDelegate/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DeactivateDelegate/Index.cshtml new file mode 100644 index 0000000000..535158413d --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DeactivateDelegate/Index.cshtml @@ -0,0 +1,84 @@ +@using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates.DeactivateDelegate +@model DeactivateDelegateAccountViewModel + + +@{ + var errorHasOccurred = !ViewData.ModelState.IsValid; + ViewData["Title"] = errorHasOccurred ? "Error: Deactivate account" : "Deactivate account"; +} +
+
+ @if (errorHasOccurred) + { + + } + +

Deactivate account - @Model.Name (@Model.Email)

+
+
+ @Model.Name has an active admin account at your centre with following admin roles: +
+
+
+
+
    + @foreach (var role in Model.Roles) + { +
  • @role
  • + } +
+
+
+ +
+
+ +

+ Which accounts would you like deactivate? +

+
+ + +
+
+ + +
+ The user will still be able to login to your centre with the above admin roles +
+
+
+ + +
+ The user will no longer be able to login to your centre +
+
+ +
+
+
+ + + + + + +
+ +
+
diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/ViewDelegate/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/ViewDelegate/Index.cshtml index 5310d64c0a..861adb1911 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/ViewDelegate/Index.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/ViewDelegate/Index.cshtml @@ -103,28 +103,28 @@ @if (Model.DelegateInfo.IsActive) { + role="button" + asp-controller="EditDelegate" + asp-action="Index" + asp-route-delegateId="@Model.DelegateInfo.Id"> Edit details + role="button" + asp-controller="SetDelegatePassword" + asp-action="Index" + asp-route-delegateId="@Model.DelegateInfo.Id" + asp-route-isFromViewDelegatePage="true"> Set password @if (User.HasCentreManagerPermissions() && !Model.DelegateInfo.IsAdmin && !string.IsNullOrWhiteSpace(Model.DelegateInfo.Email) && !string.IsNullOrWhiteSpace(Model.DelegateInfo.Name)) { + role="button" + asp-controller="PromoteToAdmin" + asp-action="Index" + asp-route-delegateId="@Model.DelegateInfo.Id"> Promote to admin } @@ -132,19 +132,31 @@ {
} else { -
- - +
+ } + else + { +
+ +
+ } } } else @@ -153,7 +165,7 @@ {
@@ -186,7 +198,7 @@ if (delegateCourseInfoViewModel.ProgressId != null) { - } + } } @foreach (var delegateSelfAssessmentInfoViewModel in Model.SelfAssessments) { @@ -199,12 +211,12 @@ @if (Model.DelegateInfo.IsActive && !string.IsNullOrEmpty(Model.DelegateInfo.Email)) { + role="button" + asp-controller="Enrol" + asp-action="StartEnrolProcess" + asp-route-delegateId="@Model.DelegateInfo.Id" + asp-route-delegateUserId="@Model.DelegateInfo.UserId" + asp-route-delegateName="@Model.DelegateInfo.Name"> Enrol on activity }