diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/LearningPortal/SelfAssessmentTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/LearningPortal/SelfAssessmentTests.cs index e725347d28..475f7f4a1f 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/LearningPortal/SelfAssessmentTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/LearningPortal/SelfAssessmentTests.cs @@ -871,28 +871,6 @@ public void SelfAssessmentOverview_Should_Return_View_With_Optional_Filter_Appli result.Should().BeViewResult().ModelAs().CompetencyGroups.ToList()[0].Count().Should().Be(1); } - [Test] - public void SelfAssessment_should_return_process_agreement_view_when_not_agreed_and_supervised() - { - // Given - var selfAssessment = SelfAssessmentTestHelper.CreateDefaultSelfAssessment(); - selfAssessment.IsSupervised = true; - selfAssessment.SelfAssessmentProcessAgreed = false; - A.CallTo(() => selfAssessmentService.GetSelfAssessmentForCandidateById(DelegateUserId, SelfAssessmentId)) - .Returns(selfAssessment); - A.CallTo(() => selfAssessmentService.GetAllSupervisorsForSelfAssessmentId(SelfAssessmentId, DelegateUserId)) - .Returns(new List()); - - // When - var result = controller.SelfAssessment(SelfAssessmentId); - - // Then - result.Should().BeViewResult() - .WithViewName("SelfAssessments/AgreeSelfAssessmentProcess") - .Model.Should().BeOfType() - .Which.SelfAssessmentID.Should().Be(SelfAssessmentId); - } - [Test] public void SelfAssessment_should_return_description_view_when_process_agreed_or_not_supervised() { @@ -931,25 +909,25 @@ public void ProcessAgreed_should_return_agree_view_when_modelstate_invalid() } [Test] - public void ProcessAgreed_should_mark_progress_and_return_description_view() + public void ProcessAgreed_should_mark_progress_and_redirect_to_self_assessment() { // Given var selfAssessment = SelfAssessmentTestHelper.CreateDefaultSelfAssessment(); - var supervisors = new List(); var model = new SelfAssessmentProcessViewModel { SelfAssessmentID = SelfAssessmentId }; A.CallTo(() => selfAssessmentService.GetSelfAssessmentForCandidateById(DelegateUserId, SelfAssessmentId)) .Returns(selfAssessment); - A.CallTo(() => selfAssessmentService.GetAllSupervisorsForSelfAssessmentId(SelfAssessmentId, DelegateUserId)) - .Returns(supervisors); // When var result = controller.ProcessAgreed(model); // Then - A.CallTo(() => selfAssessmentService.MarkProgressAgreed(SelfAssessmentId, DelegateUserId)).MustHaveHappened(); - result.Should().BeViewResult() - .WithViewName("SelfAssessments/SelfAssessmentDescription") - .Model.Should().BeEquivalentTo(new SelfAssessmentDescriptionViewModel(selfAssessment, supervisors)); + A.CallTo(() => selfAssessmentService.MarkProgressAgreed(SelfAssessmentId, DelegateUserId)) + .MustHaveHappenedOnceExactly(); + + result.Should().BeRedirectToActionResult() + .WithActionName("SelfAssessment") + .WithRouteValue("selfAssessmentId", SelfAssessmentId); } + } } diff --git a/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs b/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs index 4e9fe31021..aa3153c81d 100644 --- a/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs +++ b/DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs @@ -28,7 +28,7 @@ using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.ViewFeatures; using System.IO; - + [ServiceFilter(typeof(RequireProcessAgreementFilter))] public partial class LearningPortalController { private const string CookieName = "DLSSelfAssessmentService"; @@ -68,17 +68,6 @@ public IActionResult SelfAssessment(int selfAssessmentId) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); } - if (!selfAssessment.SelfAssessmentProcessAgreed && selfAssessment.IsSupervised) - { - var processmodel = new SelfAssessmentProcessViewModel() - { - SelfAssessmentID = selfAssessmentId, - Vocabulary = selfAssessment.Vocabulary, - VocabPlural = FrameworkVocabularyHelper.VocabularyPlural(selfAssessment.Vocabulary) - }; - return View("SelfAssessments/AgreeSelfAssessmentProcess", processmodel); - } - selfAssessmentService.IncrementLaunchCount(selfAssessmentId, delegateUserId); selfAssessmentService.UpdateLastAccessed(selfAssessmentId, delegateUserId); var supervisors = selfAssessmentService.GetAllSupervisorsForSelfAssessmentId( @@ -90,7 +79,30 @@ public IActionResult SelfAssessment(int selfAssessmentId) return View("SelfAssessments/SelfAssessmentDescription", model); } - [HttpPost] + [Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/AgreeProcess")] + public IActionResult AgreeSelfAssessmentProcess(int selfAssessmentId) + { + var delegateUserId = User.GetUserIdKnownNotNull(); + var selfAssessment = selfAssessmentService.GetSelfAssessmentForCandidateById(delegateUserId, selfAssessmentId); + + if (selfAssessment == null) + { + logger.LogWarning( + $"Attempt to display self assessment process for user {delegateUserId} with no self assessment" + ); + return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); + } + + var processmodel = new SelfAssessmentProcessViewModel() + { + SelfAssessmentID = selfAssessmentId, + Vocabulary = selfAssessment.Vocabulary, + VocabPlural = FrameworkVocabularyHelper.VocabularyPlural(selfAssessment.Vocabulary) + }; + return View("SelfAssessments/AgreeSelfAssessmentProcess", processmodel); + } + + [HttpPost("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/AgreeProcess")] public IActionResult ProcessAgreed(SelfAssessmentProcessViewModel model) { if (!ModelState.IsValid) @@ -107,13 +119,9 @@ public IActionResult ProcessAgreed(SelfAssessmentProcessViewModel model) ); return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 }); } - var supervisors = selfAssessmentService.GetAllSupervisorsForSelfAssessmentId( - selfAssessmentId, - delegateUserId - ).ToList(); - var selfAssessmentDescriptionViewModel = new SelfAssessmentDescriptionViewModel(selfAssessment, supervisors); + selfAssessmentService.MarkProgressAgreed(selfAssessmentId, delegateUserId); - return View("SelfAssessments/SelfAssessmentDescription", selfAssessmentDescriptionViewModel); + return RedirectToAction("SelfAssessment", new { selfAssessmentId }); } diff --git a/DigitalLearningSolutions.Web/ServiceFilter/RequireProcessAgreementFilter .cs b/DigitalLearningSolutions.Web/ServiceFilter/RequireProcessAgreementFilter .cs new file mode 100644 index 0000000000..2328fab15f --- /dev/null +++ b/DigitalLearningSolutions.Web/ServiceFilter/RequireProcessAgreementFilter .cs @@ -0,0 +1,71 @@ +namespace DigitalLearningSolutions.Web.ServiceFilter +{ + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Filters; + using DigitalLearningSolutions.Web.Services; + using DigitalLearningSolutions.Web.Helpers; + using Microsoft.Extensions.Logging; + + public class RequireProcessAgreementFilter : IActionFilter + { + private readonly ISelfAssessmentService selfAssessmentService; + private readonly ILogger logger; + + public RequireProcessAgreementFilter( + ISelfAssessmentService selfAssessmentService, + ILogger logger + ) + { + this.selfAssessmentService = selfAssessmentService; + this.logger = logger; + } + + public void OnActionExecuted(ActionExecutedContext context) { } + + public void OnActionExecuting(ActionExecutingContext context) + { + if (!(context.Controller is Controller controller)) + { + return; + } + + if (!context.ActionArguments.ContainsKey("selfAssessmentId")) + { + return; + } + + var selfAssessmentId = int.Parse(context.ActionArguments["selfAssessmentId"].ToString()!); + var delegateUserId = controller.User.GetUserIdKnownNotNull(); + + var selfAssessment = selfAssessmentService.GetSelfAssessmentForCandidateById(delegateUserId, selfAssessmentId); + + if (selfAssessment == null) + { + logger.LogWarning( + $"Attempt to access self assessment {selfAssessmentId} by user {delegateUserId}, but no such assessment found" + ); + context.Result = new RedirectToActionResult("StatusCode", "LearningSolutions", new { code = 403 }); + return; + } + + var actionName = context.RouteData.Values["action"]?.ToString(); + if (actionName == "AgreeSelfAssessmentProcess" || actionName == "ProcessAgreed") + { + return; + } + + if (!selfAssessment.SelfAssessmentProcessAgreed && selfAssessment.IsSupervised) + { + logger.LogInformation( + $"Redirecting user {delegateUserId} to agree process page for self assessment {selfAssessmentId}" + ); + + context.Result = new RedirectToActionResult( + "AgreeSelfAssessmentProcess", + "LearningPortal", + new { selfAssessmentId } + ); + } + } + } +} diff --git a/DigitalLearningSolutions.Web/Startup.cs b/DigitalLearningSolutions.Web/Startup.cs index bf86444202..53451b05bd 100644 --- a/DigitalLearningSolutions.Web/Startup.cs +++ b/DigitalLearningSolutions.Web/Startup.cs @@ -582,6 +582,7 @@ private static void RegisterWebServiceFilters(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); } diff --git a/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/AgreeSelfAssessmentProcess.cshtml b/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/AgreeSelfAssessmentProcess.cshtml index 02fef29335..b3f460f4e1 100644 --- a/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/AgreeSelfAssessmentProcess.cshtml +++ b/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/AgreeSelfAssessmentProcess.cshtml @@ -31,7 +31,7 @@
  • If you don’t fully meet the requirements, you can still document your progress and next steps for future assessment.
  • -
    +