Skip to content

Commit 19e62f7

Browse files
committed
TD-4460- action filter applied to verify centre specific self assessment
1 parent 9de2f37 commit 19e62f7

File tree

11 files changed

+107
-17
lines changed

11 files changed

+107
-17
lines changed

DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/CandidateAssessmentsDataService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ public IEnumerable<CandidateAssessment> GetCandidateAssessments(int delegateUser
329329
DelegateUserID,
330330
SelfAssessmentID,
331331
CompletedDate,
332-
RemovedDate
332+
RemovedDate,
333+
CentreId
333334
FROM CandidateAssessments
334335
WHERE SelfAssessmentID = @selfAssessmentId
335336
AND DelegateUserID = @delegateUserId",

DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/SelfAssessmentDataService.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ int GetSelfAssessmentActivityDelegatesExportCount(string searchString, string so
170170
IEnumerable<Accessor> GetAccessor(int selfAssessmentId, int delegateUserID);
171171
ActivitySummaryCompetencySelfAssesment? GetActivitySummaryCompetencySelfAssesment(int CandidateAssessmentSupervisorVerificationsId);
172172
bool IsUnsupervisedSelfAssessment(int selfAssessmentId);
173+
bool IsCentreSelfAssessment(int selfAssessmentId, int centreId);
173174
}
174175

175176
public partial class SelfAssessmentDataService : ISelfAssessmentDataService
@@ -719,5 +720,14 @@ public bool IsUnsupervisedSelfAssessment(int selfAssessmentId)
719720
);
720721
return ResultCount > 0;
721722
}
723+
724+
public bool IsCentreSelfAssessment(int selfAssessmentId, int centreId)
725+
{
726+
var ResultCount = connection.ExecuteScalar<int>(
727+
@"SELECT count(*) FROM CentreSelfAssessments WHERE SelfAssessmentID = @selfAssessmentId and CentreID = @centreId",
728+
new { selfAssessmentId, centreId }
729+
);
730+
return ResultCount > 0;
731+
}
722732
}
723733
}

DigitalLearningSolutions.Data/Models/SelfAssessments/CandidateAssessment.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ public class CandidateAssessment
1313
public DateTime? CompletedDate { get; set; }
1414

1515
public DateTime? RemovedDate { get; set; }
16+
public int CentreId { get; set; }
1617
}
1718
}

DigitalLearningSolutions.Web.Tests/ServiceFilter/VerifyDelegateUserCanAccessSelfAssessmentTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public void Returns_Redirect_to_access_denied_if_delegate_does_not_have_self_ass
3636
{
3737
// Given
3838
var context = GetDefaultContext();
39-
A.CallTo(() => selfAssessmentService.CanDelegateAccessSelfAssessment(A<int>._, A<int>._)).Returns(false);
39+
A.CallTo(() => selfAssessmentService.CanDelegateAccessSelfAssessment(A<int>._, A<int>._, A<int>._)).Returns(false);
4040

4141
// When
4242
new VerifyDelegateUserCanAccessSelfAssessment(selfAssessmentService, logger).OnActionExecuting(context);
@@ -54,7 +54,7 @@ public void Does_not_return_access_denied_if_delegate_has_self_assessment()
5454
{
5555
// Given
5656
var context = GetDefaultContext();
57-
A.CallTo(() => selfAssessmentService.CanDelegateAccessSelfAssessment(A<int>._, A<int>._)).Returns(true);
57+
A.CallTo(() => selfAssessmentService.CanDelegateAccessSelfAssessment(A<int>._, A<int>._, A<int>._)).Returns(true);
5858

5959
// When
6060
new VerifyDelegateUserCanAccessSelfAssessment(selfAssessmentService, logger).OnActionExecuting(context);

DigitalLearningSolutions.Web.Tests/Services/SelfAssessmentServiceTests.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ public void CanDelegateAccessSelfAssessment_returns_true_with_no_completed_or_re
3131
.With(ca => ca.CompletedDate = null)
3232
.With(ca => ca.RemovedDate = null)
3333
.Build().ToList();
34+
A.CallTo(() => selfAssessmentDataService.IsCentreSelfAssessment(A<int>._, A<int>._)).Returns(true);
3435
A.CallTo(() => selfAssessmentDataService.GetCandidateAssessments(A<int>._, A<int>._))
3536
.Returns(candidateAssessments);
3637

3738
// When
38-
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1);
39+
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1, 1);
3940

4041
// Then
4142
result.Should().BeTrue();
@@ -54,11 +55,13 @@ public void CanDelegateAccessSelfAssessment_returns_true_with_at_least_one_valid
5455
.With(ca => ca.CompletedDate = null)
5556
.With(ca => ca.RemovedDate = null)
5657
.Build().ToList();
58+
59+
A.CallTo(() => selfAssessmentDataService.IsCentreSelfAssessment(A<int>._, A<int>._)).Returns(true);
5760
A.CallTo(() => selfAssessmentDataService.GetCandidateAssessments(A<int>._, A<int>._))
5861
.Returns(candidateAssessments);
5962

6063
// When
61-
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1);
64+
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1, 1);
6265

6366
// Then
6467
result.Should().BeTrue();
@@ -78,7 +81,7 @@ public void CanDelegateAccessSelfAssessment_returns_false_with_only_completed_or
7881
.Returns(candidateAssessments);
7982

8083
// When
81-
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1);
84+
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1, 1);
8285

8386
// Then
8487
result.Should().BeFalse();
@@ -92,7 +95,7 @@ public void CanDelegateAccessSelfAssessment_returns_false_no_assessments()
9295
.Returns(new List<CandidateAssessment>());
9396

9497
// When
95-
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1);
98+
var result = selfAssessmentService.CanDelegateAccessSelfAssessment(1, 1, 1);
9699

97100
// Then
98101
result.Should().BeFalse();

DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ from assessmentQuestion in competency.AssessmentQuestions
5151
}
5252

5353
[NoCaching]
54+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
5455
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}")]
5556
public IActionResult SelfAssessment(int selfAssessmentId)
5657
{
@@ -76,6 +77,7 @@ public IActionResult SelfAssessment(int selfAssessmentId)
7677
return View("SelfAssessments/SelfAssessmentDescription", model);
7778
}
7879

80+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
7981
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{competencyNumber:int}")]
8082
public IActionResult SelfAssessmentCompetency(int selfAssessmentId, int competencyNumber)
8183
{
@@ -145,6 +147,7 @@ public IActionResult SelfAssessmentCompetency(int selfAssessmentId, int competen
145147
}
146148

147149
[HttpPost]
150+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
148151
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{competencyNumber:int}")]
149152
public IActionResult SelfAssessmentCompetency(
150153
int selfAssessmentId,
@@ -187,9 +190,8 @@ public IActionResult SelfAssessmentCompetency(
187190
return SubmitSelfAssessment(assessment, selfAssessmentId, competencyNumber, competencyId, competencyGroupId, updatedAssessmentQuestions, delegateUserId, delegateId);
188191
}
189192

190-
[Route(
191-
"/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{competencyNumber:int}/confirm"
192-
)]
193+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
194+
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{competencyNumber:int}/confirm")]
193195
[HttpGet]
194196
public IActionResult ConfirmOverwriteSelfAssessment(
195197
int selfAssessmentId, int competencyNumber
@@ -224,6 +226,7 @@ public IActionResult ConfirmOverwriteSelfAssessment(
224226
"/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{competencyNumber:int}/confirm"
225227
)]
226228
[HttpPost]
229+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
227230
public IActionResult ConfirmOverwriteSelfAssessment(int selfAssessmentId,
228231
int competencyNumber,
229232
int competencyId,
@@ -309,6 +312,7 @@ IActionResult SubmitSelfAssessment(CurrentSelfAssessment assessment, int selfAss
309312
);
310313
}
311314

315+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
312316
[Route(
313317
"/LearningPortal/SelfAssessment/{selfAssessmentId:int}/Proficiencies/{competencyNumber:int}/{resultId:int}/ViewNotes"
314318
)]
@@ -416,6 +420,8 @@ public IActionResult AddSelfAssessmentOverviewFilter(SearchSelfAssessmentOvervie
416420
);
417421
return RedirectToAction("FilteredSelfAssessmentGroups", model);
418422
}
423+
424+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
419425
[Route("LearningPortal/SelfAssessment/{selfAssessmentId}/{vocabulary}/{competencyGroupId}")]
420426
[Route("LearningPortal/SelfAssessment/{selfAssessmentId}/{vocabulary}")]
421427
public IActionResult SelfAssessmentOverview(int selfAssessmentId, string vocabulary, int? competencyGroupId = null, SearchSelfAssessmentOverviewViewModel searchModel = null)
@@ -485,6 +491,7 @@ public IActionResult SelfAssessmentOverview(int selfAssessmentId, string vocabul
485491
return View("SelfAssessments/SelfAssessmentOverview", model);
486492
}
487493
[HttpPost]
494+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
488495
[SetDlsSubApplication(nameof(DlsSubApplication.LearningPortal))]
489496
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/CompleteBy")]
490497
public IActionResult SetSelfAssessmentCompleteByDate(int selfAssessmentId, EditCompleteByDateFormData formData)
@@ -521,6 +528,7 @@ public IActionResult SetSelfAssessmentCompleteByDate(int selfAssessmentId, EditC
521528
return RedirectToAction("Current");
522529
}
523530

531+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
524532
[SetDlsSubApplication(nameof(DlsSubApplication.LearningPortal))]
525533
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/CompleteBy")]
526534
public IActionResult SetSelfAssessmentCompleteByDate(int selfAssessmentId, ReturnPageQuery returnPageQuery)
@@ -549,6 +557,7 @@ public IActionResult SetSelfAssessmentCompleteByDate(int selfAssessmentId, Retur
549557
return View("Current/SetCompleteByDate", model);
550558
}
551559
[NoCaching]
560+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
552561
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/Supervisors")]
553562
public IActionResult ManageSupervisors(int selfAssessmentId)
554563
{
@@ -612,6 +621,7 @@ public IActionResult QuickAddSupervisor(int selfAssessmentId, int supervisorDele
612621
return RedirectToAction("ManageSupervisors", new { selfAssessmentId });
613622
}
614623

624+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
615625
public IActionResult StartAddNewSupervisor(int selfAssessmentId)
616626
{
617627
TempData.Clear();
@@ -650,6 +660,7 @@ public IActionResult StartAddNewSupervisor(int selfAssessmentId)
650660
return RedirectToAction("AddNewSupervisor", new { selfAssessmentId });
651661
}
652662

663+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
653664
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/Supervisors/Add/{page=1:int}")]
654665
public IActionResult AddNewSupervisor(int selfAssessmentId,
655666
string? searchString = null,
@@ -799,6 +810,7 @@ public IActionResult SetSupervisorName(AddSupervisorViewModel model)
799810
return RedirectToAction("AddSupervisorSummary", new { model.SelfAssessmentID });
800811
}
801812

813+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
802814
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/Supervisors/Centre")]
803815
public IActionResult SelectSupervisorCentre(int selfAssessmentId)
804816
{
@@ -882,6 +894,7 @@ public IActionResult SelectSupervisorCentre(SupervisorCentresViewModel model)
882894
return RedirectToAction("AddNewSupervisor", new { model.SelfAssessmentID });
883895
}
884896

897+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
885898
[Route(
886899
"/LearningPortal/SelfAssessment/{selfAssessmentId:int}/Supervisors/QuickAdd/{supervisorDelegateId}/Role"
887900
)]
@@ -989,6 +1002,7 @@ public IActionResult SetSupervisorRole(SetSupervisorRoleViewModel model)
9891002
return RedirectToAction("ManageSupervisors", new { model.SelfAssessmentID });
9901003
}
9911004

1005+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
9921006
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/Supervisors/Add/Summary")]
9931007
[ResponseCache(CacheProfileName = "Never")]
9941008
public IActionResult AddSupervisorSummary(int selfAssessmentId)
@@ -1093,6 +1107,7 @@ public IActionResult SendSupervisorReminder(int selfAssessmentId, int supervisor
10931107
return RedirectToAction("ManageSupervisors", new { selfAssessmentId });
10941108
}
10951109

1110+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
10961111
public IActionResult StartRequestVerification(int selfAssessmentId)
10971112
{
10981113
TempData.Clear();
@@ -1120,6 +1135,7 @@ public IActionResult StartRequestVerification(int selfAssessmentId)
11201135
return RedirectToAction("VerificationPickSupervisor", new { selfAssessmentId });
11211136
}
11221137

1138+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
11231139
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/ConfirmationRequests")]
11241140
public IActionResult ReviewConfirmationRequests(int selfAssessmentId)
11251141
{
@@ -1144,6 +1160,7 @@ public IActionResult ReviewConfirmationRequests(int selfAssessmentId)
11441160
return View("SelfAssessments/ReviewConfirmationRequests", model);
11451161
}
11461162

1163+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
11471164
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/ConfirmationRequests/New/ChooseSupervisor")]
11481165
[ResponseCache(CacheProfileName = "Never")]
11491166
[TypeFilter(
@@ -1216,10 +1233,11 @@ public IActionResult VerificationPickSupervisor(VerificationPickSupervisorViewMo
12161233
);
12171234
return RedirectToAction("VerificationPickResults", new { sessionRequestVerification.SelfAssessmentID });
12181235
}
1236+
1237+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
12191238
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/ConfirmationRequests/New/PickResults")]
12201239
[ResponseCache(CacheProfileName = "Never")]
1221-
[TypeFilter(
1222-
typeof(RedirectToErrorEmptySessionData),
1240+
[TypeFilter(typeof(RedirectToErrorEmptySessionData),
12231241
Arguments = new object[] { nameof(MultiPageFormDataFeature.AddSelfAssessmentRequestVerification) }
12241242
)]
12251243
public IActionResult VerificationPickResults(int selfAssessmentId)
@@ -1286,6 +1304,7 @@ public IActionResult VerificationPickResults(VerificationPickResultsViewModel mo
12861304
return RedirectToAction("VerificationSummary", new { sessionRequestVerification.SelfAssessmentID });
12871305
}
12881306

1307+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
12891308
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/ConfirmationRequests/New/Summary")]
12901309
[ResponseCache(CacheProfileName = "Never")]
12911310
[TypeFilter(
@@ -1414,6 +1433,7 @@ public IActionResult SubmitVerification()
14141433
);
14151434
}
14161435

1436+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
14171437
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{vocabulary}/Optional")]
14181438
public IActionResult ManageOptionalCompetencies(int selfAssessmentId)
14191439
{
@@ -1468,6 +1488,7 @@ ManageOptionalCompetenciesViewModel model
14681488
return RedirectToAction("SelfAssessmentOverview", new { selfAssessmentId, vocabulary });
14691489
}
14701490

1491+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
14711492
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{vocabulary}/RequestSignOff")]
14721493
public IActionResult RequestSignOff(int selfAssessmentId)
14731494
{
@@ -1484,6 +1505,7 @@ public IActionResult RequestSignOff(int selfAssessmentId)
14841505
}
14851506

14861507
[HttpPost]
1508+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
14871509
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{vocabulary}/RequestSignOff")]
14881510
public IActionResult RequestSignOff(int selfAssessmentId, string vocabulary, RequestSignOffViewModel model)
14891511
{
@@ -1532,6 +1554,7 @@ string vocabulary
15321554
return RedirectToAction("SelfAssessmentOverview", new { selfAssessmentId, vocabulary });
15331555
}
15341556

1557+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
15351558
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{vocabulary}/SignOffHistory")]
15361559
public IActionResult SignOffHistory(int selfAssessmentId, string vocabulary)
15371560
{

DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/ActivityDelegatesController.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ public IActionResult RemoveDelegateSelfAssessment(DelegateSelfAssessmenteViewMod
503503
}
504504

505505
[HttpGet]
506+
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
506507
[Route("{selfAssessmentId:int}/EditCompleteByDate")]
507508
public IActionResult EditCompleteByDate(
508509
int delegateUserId,
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace DigitalLearningSolutions.Web.ServiceFilter
2+
{
3+
using Microsoft.AspNetCore.Mvc;
4+
using Microsoft.AspNetCore.Mvc.Filters;
5+
using DigitalLearningSolutions.Web.Helpers;
6+
using DigitalLearningSolutions.Web.Services;
7+
using Microsoft.Extensions.Logging;
8+
9+
public class IsCentreAuthorizedSelfAssessment : IActionFilter
10+
{
11+
private readonly ISelfAssessmentService selfAssessmentService;
12+
private readonly ILogger<IsCentreAuthorizedSelfAssessment> logger;
13+
14+
public IsCentreAuthorizedSelfAssessment(ISelfAssessmentService selfAssessmentService,
15+
ILogger<IsCentreAuthorizedSelfAssessment> logger)
16+
{
17+
this.selfAssessmentService = selfAssessmentService;
18+
this.logger = logger;
19+
}
20+
21+
public void OnActionExecuted(ActionExecutedContext context) { }
22+
23+
public void OnActionExecuting(ActionExecutingContext context)
24+
{
25+
if (!(context.Controller is Controller controller))
26+
{
27+
return;
28+
}
29+
var centreId = controller.User.GetCentreIdKnownNotNull();
30+
var selfAssessmentId = int.Parse(context.ActionArguments["selfAssessmentId"].ToString()!);
31+
32+
if (centreId > 0 && selfAssessmentId > 0)
33+
{
34+
if (!selfAssessmentService.IsCentreSelfAssessment(selfAssessmentId, centreId))
35+
{
36+
logger.LogWarning($"Attempt to access restricted self assessment {selfAssessmentId} by user {controller.User.GetUserIdKnownNotNull()}");
37+
context.Result = new RedirectToActionResult("AccessDenied", "LearningSolutions", new { code = 403 });
38+
}
39+
}
40+
}
41+
}
42+
}

DigitalLearningSolutions.Web/ServiceFilter/VerifyDelegateUserCanAccessSelfAssessment.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ public void OnActionExecuting(ActionExecutingContext context)
3131

3232
var selfAssessmentId = int.Parse(context.RouteData.Values["selfAssessmentId"].ToString()!);
3333
var delegateUserId = controller.User.GetUserIdKnownNotNull();
34+
var centreId = controller.User.GetCentreIdKnownNotNull();
3435
var canAccessSelfAssessment =
35-
selfAssessmentService.CanDelegateAccessSelfAssessment(delegateUserId, selfAssessmentId);
36+
selfAssessmentService.CanDelegateAccessSelfAssessment(delegateUserId, selfAssessmentId, centreId);
3637

3738
if (!canAccessSelfAssessment)
3839
{

0 commit comments

Comments
 (0)