Skip to content

Commit 65d36c9

Browse files
ABSinhaakevwhitt-hee
authored andcommitted
TD-4880- Prevent administrators from viewing Activity Delegates for self assessments in a category that doesn't match their own through URL manipulation.
1 parent 170c5e2 commit 65d36c9

File tree

10 files changed

+42
-18
lines changed

10 files changed

+42
-18
lines changed

DigitalLearningSolutions.Data/DataServices/CourseDataService.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ int EnrolOnActivitySelfAssessment(int selfAssessmentId, int candidateId, int sup
136136

137137
public IEnumerable<CourseStatistics> GetDelegateCourseStatisticsAtCentre(string searchString, int centreId, int? categoryId, bool allCentreCourses, bool? hideInLearnerPortal, string isActive, string categoryName, string courseTopic, string hasAdminFields);
138138

139-
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessmentStatisticsAtCentre(string searchString, int centreId, string categoryName, string isActive);
139+
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessmentStatisticsAtCentre(string searchString, int centreId, string categoryName, string isActive, int? categoryId);
140+
140141
bool IsSelfEnrollmentAllowed(int customisationId);
141142
Customisation? GetCourse(int customisationId);
142143
}
@@ -541,9 +542,7 @@ LEFT OUTER JOIN UserCentreDetails AS UCD ON
541542
new { candidateAssessmentId, enrolmentMethodId, completeByDateDynamic }
542543
);
543544
}
544-
545545
if (candidateAssessmentId > 1 && supervisorDelegateId !=0)
546-
547546
{
548547
string sqlQuery = $@"
549548
BEGIN TRANSACTION
@@ -1976,7 +1975,7 @@ AND ap.DefaultContentTypeID <> 4
19761975
return courseStatistics;
19771976
}
19781977

1979-
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessmentStatisticsAtCentre(string searchString, int centreId, string categoryName, string isActive)
1978+
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessmentStatisticsAtCentre(string searchString, int centreId, string categoryName, string isActive, int? categoryId)
19801979
{
19811980
string assessmentStatisticsSelectQuery = $@"SELECT
19821981
sa.Name AS Name,
@@ -2006,11 +2005,12 @@ from CentreSelfAssessments AS csa
20062005
WHERE csa.CentreID= @centreId
20072006
AND sa.[Name] LIKE '%' + @searchString + '%'
20082007
AND ((@categoryName = 'Any') OR (cc.CategoryName = @categoryName))
2008+
AND (ISNULL(@categoryId, 0) = 0 OR sa.CategoryID = @categoryId)
20092009
AND ((@isActive = 'Any') OR (@isActive = 'true' AND sa.ArchivedDate IS NULL) OR (@isActive = 'false' AND sa.ArchivedDate IS NOT NULL))
20102010
";
20112011

20122012
IEnumerable<DelegateAssessmentStatistics> delegateAssessmentStatistics = connection.Query<DelegateAssessmentStatistics>(assessmentStatisticsSelectQuery,
2013-
new { searchString, centreId, categoryName, isActive }, commandTimeout: 3000);
2013+
new { searchString, centreId, categoryName, isActive, categoryId }, commandTimeout: 3000);
20142014
return delegateAssessmentStatistics;
20152015
}
20162016

DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/SelfAssessmentDataService.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ int GetSelfAssessmentActivityDelegatesExportCount(string searchString, string so
172172
bool IsUnsupervisedSelfAssessment(int selfAssessmentId);
173173
bool IsCentreSelfAssessment(int selfAssessmentId, int centreId);
174174
bool HasMinimumOptionalCompetencies(int selfAssessmentId, int delegateUserId);
175+
int GetSelfAssessmentCategoryId(int selfAssessmentId);
175176
}
176177

177178
public partial class SelfAssessmentDataService : ISelfAssessmentDataService
@@ -760,5 +761,13 @@ INNER JOIN SelfAssessments AS SA
760761
new { selfAssessmentId, delegateUserId }
761762
);
762763
}
764+
765+
public int GetSelfAssessmentCategoryId(int selfAssessmentId)
766+
{
767+
return connection.ExecuteScalar<int>(
768+
@"SELECT CategoryID FROM SelfAssessments WHERE ID = @selfAssessmentId",
769+
new { selfAssessmentId }
770+
);
771+
}
763772
}
764773
}

DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/Delegates/CourseDelegatesControllerTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
public class CourseDelegatesControllerTests
2424
{
2525
private const int UserCentreId = 3;
26+
private const int selfAssessmentId = 3;
2627
private ActivityDelegatesController controller = null!;
2728
private ICourseDelegatesDownloadFileService courseDelegatesDownloadFileService = null!;
2829
private ICourseDelegatesService courseDelegatesService = null!;
@@ -123,7 +124,7 @@ public void CourseDelegates_Index_returns_Not_Found_when_service_returns_null()
123124
);
124125

125126
// When
126-
var result = controller.Index(2);
127+
var result = controller.Index(2, selfAssessmentId);
127128

128129
// Then
129130
result.Should().BeNotFoundResult();
@@ -207,7 +208,7 @@ public void Index_should_default_to_Active_filter()
207208
);
208209

209210
// When
210-
var result = courseDelegatesController.Index(customisationId);
211+
var result = courseDelegatesController.Index(customisationId, selfAssessmentId);
211212

212213
// Then
213214
using (new AssertionScope())

DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/Delegates/DelegateCoursesControllerTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ public void Index_calls_expected_methods_and_returns_view()
9999
var delegateCourses = Builder<CourseStatisticsWithAdminFieldResponseCounts>.CreateListOfSize(5).Build();
100100
A.CallTo(() => courseService.GetDelegateCourses(string.Empty, 1, 1, true, true, string.Empty, string.Empty, string.Empty, string.Empty)).Returns(delegateCourses);
101101

102-
A.CallTo(() => courseService.GetDelegateAssessments(A<string>._, A<int>._, A<string>._, A<string>._)).MustHaveHappened();
102+
103+
var delegateSelfAssessments = Builder<DelegateAssessmentStatistics>.CreateListOfSize(5).Build();
104+
A.CallTo(() => courseService.GetDelegateAssessments(A<string>._, A<int>._, A<string>._, A<string>._, A<int>._)).Returns(delegateSelfAssessments);
103105
A.CallTo(
104106
() => paginateService.Paginate(A<IEnumerable<CourseStatistics>>._,
105107
A<int>._,

DigitalLearningSolutions.Web.Tests/Services/CourseServiceTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -982,15 +982,15 @@ public void GetDelegateAssessments_GetDelegateAssessments_ShouldBeInvokedAndRetu
982982
{
983983
// Given
984984
var delegateAssessments = Builder<DelegateAssessmentStatistics>.CreateListOfSize(5).Build();
985-
A.CallTo(() => courseDataService.GetDelegateAssessmentStatisticsAtCentre(string.Empty, 1, string.Empty, string.Empty)).Returns(delegateAssessments);
985+
A.CallTo(() => courseDataService.GetDelegateAssessmentStatisticsAtCentre(string.Empty, 1, string.Empty, string.Empty, 1)).Returns(delegateAssessments);
986986

987987
// When
988-
var result = courseService.GetDelegateAssessments(string.Empty, 1, string.Empty, string.Empty);
988+
var result = courseService.GetDelegateAssessments(string.Empty, 1, string.Empty, string.Empty, 1);
989989

990990
// Then
991991
using (new AssertionScope())
992992
{
993-
A.CallTo(() => courseDataService.GetDelegateAssessmentStatisticsAtCentre(string.Empty, 1, string.Empty, string.Empty))
993+
A.CallTo(() => courseDataService.GetDelegateAssessmentStatisticsAtCentre(string.Empty, 1, string.Empty, string.Empty, 1))
994994
.MustHaveHappenedOnceExactly();
995995
result.Count().Should().BeGreaterOrEqualTo(0);
996996
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ public IActionResult Index(
131131

132132
var centreId = User.GetCentreIdKnownNotNull();
133133
var adminCategoryId = User.GetAdminCategoryId();
134+
var selfAssessmentCategoryId = selfAssessmentService.GetSelfAssessmentCategoryId((int)selfAssessmentId);
135+
136+
if (adminCategoryId > 0 && adminCategoryId != selfAssessmentCategoryId)
137+
{
138+
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
139+
}
134140

135141
bool? isDelegateActive, isProgressLocked, removed, hasCompleted, submitted, signedOff;
136142
isDelegateActive = isProgressLocked = removed = hasCompleted = submitted = signedOff = null;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,13 @@ public IActionResult Index(
156156
{
157157
delegateActivities = courseService.GetDelegateCourses(searchString, centreId, categoryId, true, null, isActive, categoryName, courseTopic, hasAdminFields).ToList();
158158
if (courseTopic == "Any" && hasAdminFields == "Any")
159-
delegateAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive);
159+
delegateAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive, categoryId);
160160
}
161161

162162
if (isCourse == "true")
163163
delegateActivities = courseService.GetDelegateCourses(searchString ?? string.Empty, centreId, categoryId, true, null, isActive, categoryName, courseTopic, hasAdminFields).ToList();
164164
if (isSelfAssessment == "true" && courseTopic == "Any" && hasAdminFields == "Any")
165-
delegateAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive);
165+
delegateAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive, categoryId);
166166

167167
delegateAssessments = UpdateCompletedCount(delegateAssessments);
168168

DigitalLearningSolutions.Web/Services/CourseDelegatesDownloadFileService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,12 @@ string sortDirection
227227
{
228228
courses = GetCoursesToExport(centreId, adminCategoryId, searchString, sortBy, filterString, sortDirection);
229229
if (courseTopic == "Any" && hasAdminFields == "Any")
230-
selfAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive);
230+
selfAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive, adminCategoryId);
231231
}
232232
if (isCourse == "true")
233233
courses = GetCoursesToExport(centreId, adminCategoryId, searchString, sortBy, filterString, sortDirection);
234234
if (isSelfAssessment == "true" && courseTopic == "Any" && hasAdminFields == "Any")
235-
selfAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive);
235+
selfAssessments = courseService.GetDelegateAssessments(searchString, centreId, categoryName, isActive, adminCategoryId);
236236

237237
if (selfAssessments.Any())
238238
{

DigitalLearningSolutions.Web/Services/CourseService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ int diagCompletionThreshold
120120
string isActive, string categoryName, string courseTopic, string hasAdminFields);
121121

122122
public IEnumerable<CourseStatisticsWithAdminFieldResponseCounts> GetDelegateCourses(string searchString, int centreId, int? categoryId, bool allCentreCourses, bool? hideInLearnerPortal, string isActive, string categoryName, string courseTopic, string hasAdminFields);
123-
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessments(string searchString, int centreId, string categoryName, string isActive);
123+
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessments(string searchString, int centreId, string categoryName, string isActive, int? categoryId);
124124
IEnumerable<AvailableCourse> GetAvailableCourses(int delegateId, int? centreId, int categoryId);
125125
bool IsCourseCompleted(int candidateId, int customisationId);
126126
bool IsCourseCompleted(int candidateId, int customisationId, int progressID);
@@ -563,9 +563,9 @@ public IEnumerable<CourseStatisticsWithAdminFieldResponseCounts> GetDelegateCour
563563
);
564564
}
565565

566-
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessments(string searchString, int centreId, string categoryName, string isActive)
566+
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessments(string searchString, int centreId, string categoryName, string isActive, int? categoryId)
567567
{
568-
return courseDataService.GetDelegateAssessmentStatisticsAtCentre(searchString, centreId, categoryName, isActive);
568+
return courseDataService.GetDelegateAssessmentStatisticsAtCentre(searchString, centreId, categoryName, isActive, categoryId);
569569
}
570570

571571
public IEnumerable<AvailableCourse> GetAvailableCourses(int delegateId, int? centreId, int categoryId)

DigitalLearningSolutions.Web/Services/SelfAssessmentService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ public int GetSelfAssessmentActivityDelegatesExportCount(string searchString, st
149149
IEnumerable<CandidateAssessment> GetCandidateAssessments(int delegateUserId, int selfAssessmentId);
150150
bool IsCentreSelfAssessment(int selfAssessmentId, int centreId);
151151
bool HasMinimumOptionalCompetencies(int selfAssessmentId, int delegateUserId);
152+
public int GetSelfAssessmentCategoryId(int selfAssessmentId);
152153

153154
}
154155

@@ -557,5 +558,10 @@ public bool HasMinimumOptionalCompetencies(int selfAssessmentId, int delegateUse
557558
{
558559
return selfAssessmentDataService.HasMinimumOptionalCompetencies(selfAssessmentId, delegateUserId);
559560
}
561+
562+
public int GetSelfAssessmentCategoryId(int selfAssessmentId)
563+
{
564+
return selfAssessmentDataService.GetSelfAssessmentCategoryId(selfAssessmentId);
565+
}
560566
}
561567
}

0 commit comments

Comments
 (0)