Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,12 @@ ManageOptionalCompetenciesViewModel model
public IActionResult RequestSignOff(int selfAssessmentId)
{
var delegateUserId = User.GetUserIdKnownNotNull();
var delegateId = User.GetCandidateIdKnownNotNull();
var recentResults = selfAssessmentService.GetMostRecentResults(selfAssessmentId, delegateId).ToList();
var competencySummaries = CertificateHelper.CompetencySummation(recentResults);

if (competencySummaries.QuestionsCount != competencySummaries.VerifiedCount) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });

var assessment = selfAssessmentService.GetSelfAssessmentForCandidateById(delegateUserId, selfAssessmentId);
var supervisors =
selfAssessmentService.GetSignOffSupervisorsForSelfAssessmentId(selfAssessmentId, delegateUserId);
Expand All @@ -1568,6 +1574,8 @@ public IActionResult RequestSignOff(int selfAssessmentId)
Supervisors = supervisors,
NumberOfSelfAssessedOptionalCompetencies = optionalCompetencies.Count(x => x.IncludedInSelfAssessment)
};
if (model.NumberOfSelfAssessedOptionalCompetencies < model.SelfAssessment.MinimumOptionalCompetencies) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });

return View("SelfAssessments/RequestSignOff", model);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ public IActionResult Index(

sortBy ??= DefaultSortByOptions.Name.PropertyName;
sortDirection ??= GenericSortingHelper.Ascending;
existingFilterString = FilteringHelper.GetFilterString(
existingFilterString,
newFilterToAdd,
clearFilters,
Request,
filterCookieName,
CourseDelegateAccountStatusFilterOptions.Active.FilterValue
);
existingFilterString = FilteringHelper.GetFilterString(
existingFilterString,
newFilterToAdd,
clearFilters,
Request,
filterCookieName,
CourseDelegateAccountStatusFilterOptions.Active.FilterValue
);

if (isCourseDelegate)
{
Expand Down Expand Up @@ -227,7 +227,7 @@ public IActionResult Index(
page = 1; offSet = 0;
(selfAssessmentDelegatesData, resultCount) = selfAssessmentService.GetSelfAssessmentDelegatesPerPage(searchString ?? string.Empty, offSet, itemsPerPage ?? 0, sortBy, sortDirection,
selfAssessmentId, centreId, isDelegateActive, removed, submitted, signedOff, adminCategoryId);
}
}

var adminId = User.GetCustomClaimAsRequiredInt(CustomClaimTypes.UserAdminId);

Expand Down Expand Up @@ -259,7 +259,7 @@ public IActionResult Index(
: selfAssessmentService.GetSelfAssessmentNameById((int)selfAssessmentId);
if (!string.IsNullOrEmpty(existingFilterString))
{
existingFilterString = FilteringHelper.GetValidFilters( existingFilterString, newFilterToAdd, availableFilters, Request, filterCookieName);
existingFilterString = FilteringHelper.GetValidFilters(existingFilterString, newFilterToAdd, availableFilters, Request, filterCookieName);
}
if (isCourseDelegate)
{
Expand Down Expand Up @@ -375,7 +375,9 @@ public IActionResult DownloadCurrent(
fileName
);
}

[Route("DownloadActivityDelegates/{selfAssessmentId:int}")]
[ServiceFilter(typeof(VerifyAdminUserCanAccessSelfAssessment))]
public IActionResult DownloadActivityDelegates(
int selfAssessmentId,
string? searchString = null,
Expand All @@ -388,7 +390,6 @@ public IActionResult DownloadActivityDelegates(
sortBy ??= DefaultSortByOptions.Name.PropertyName;
sortDirection ??= GenericSortingHelper.Ascending;


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

Expand Down Expand Up @@ -456,6 +457,7 @@ public IActionResult DownloadActivityDelegates(
fileName
);
}

[Route("TrackingSystem/Delegates/ActivityDelegates/{candidateAssessmentsId}/Remove")]
[HttpGet]
public IActionResult RemoveDelegateSelfAssessment(int candidateAssessmentsId)
Expand All @@ -466,12 +468,21 @@ public IActionResult RemoveDelegateSelfAssessment(int candidateAssessmentsId)
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 410 });
}
var selfAssessmentDelegate = selfAssessmentService.GetDelegateSelfAssessmentByCandidateAssessmentsId(candidateAssessmentsId);
if (selfAssessmentDelegate == null)
if (selfAssessmentDelegate != null)
{
var adminCategoryId = User.GetAdminCategoryId();
var selfAssessmentCategoryId = selfAssessmentService.GetSelfAssessmentCategoryId(selfAssessmentDelegate.SelfAssessmentID);
if (adminCategoryId > 0 && adminCategoryId != selfAssessmentCategoryId)
{
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
}
var model = new DelegateSelfAssessmenteViewModel(selfAssessmentDelegate);
return View(model);
}
else
{
return new NotFoundResult();
}
var model = new DelegateSelfAssessmenteViewModel(selfAssessmentDelegate);
return View(model);
}

[Route("TrackingSystem/Delegates/ActivityDelegates/{candidateAssessmentsId}/Remove")]
Expand Down Expand Up @@ -502,6 +513,7 @@ public IActionResult RemoveDelegateSelfAssessment(DelegateSelfAssessmenteViewMod

[HttpGet]
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
[ServiceFilter(typeof(VerifyAdminUserCanAccessSelfAssessment))]
[Route("{selfAssessmentId:int}/EditCompleteByDate")]
public IActionResult EditCompleteByDate(
int delegateUserId,
Expand Down
20 changes: 20 additions & 0 deletions DigitalLearningSolutions.Web/Helpers/CertificateHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,25 @@ public static CompetencySummary CanViewCertificate(List<Competency> reviewedComp
};
return model;
}
public static CompetencySummary CompetencySummation(List<Competency> reviewedCompetencies)
{
var CompetencyGroups = reviewedCompetencies.GroupBy(competency => competency.CompetencyGroup);
var competencySummaries = CompetencyGroups.Select(g =>
{
var questions = g.SelectMany(c => c.AssessmentQuestions).Where(q => q.Required);
var verifiedCount = questions.Count(q => !((q.Result == null || q.Verified == null || q.SignedOff != true) && q.Required));
return new
{
QuestionsCount = questions.Count(),
VerifiedCount = verifiedCount
};
});
var model = new CompetencySummary()
{
VerifiedCount = competencySummaries.Sum(item => item.VerifiedCount),
QuestionsCount = competencySummaries.Sum(item => item.QuestionsCount),
};
return model;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace DigitalLearningSolutions.Web.ServiceFilter
{
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using DigitalLearningSolutions.Web.Helpers;
using DigitalLearningSolutions.Web.Services;
using Microsoft.Extensions.Logging;

public class VerifyAdminUserCanAccessSelfAssessment : IActionFilter
{
private readonly ISelfAssessmentService selfAssessmentService;
private readonly ILogger<VerifyAdminUserCanAccessSelfAssessment> logger;

public VerifyAdminUserCanAccessSelfAssessment(ISelfAssessmentService selfAssessmentService,
ILogger<VerifyAdminUserCanAccessSelfAssessment> logger)
{
this.selfAssessmentService = selfAssessmentService;
this.logger = logger;
}

public void OnActionExecuted(ActionExecutedContext context) { }

public void OnActionExecuting(ActionExecutingContext context)
{
if (!(context.Controller is Controller controller))
{
return;
}
var adminCategoryId = controller.User.GetAdminCategoryId();
var selfAssessmentId = int.Parse(context.ActionArguments["selfAssessmentId"].ToString()!);
var selfAssessmentCategoryId = selfAssessmentService.GetSelfAssessmentCategoryId((selfAssessmentId));
if (adminCategoryId > 0 && adminCategoryId != selfAssessmentCategoryId)
{
logger.LogWarning($"Attempt to access restricted self assessment {selfAssessmentId} by user {controller.User.GetUserIdKnownNotNull()}");
context.Result = new RedirectToActionResult("StatusCode", "LearningSolutions", new { code = 403 });
}
}
}
}
2 changes: 1 addition & 1 deletion DigitalLearningSolutions.Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ namespace DigitalLearningSolutions.Web
using static DigitalLearningSolutions.Web.Services.ICentreApplicationsService;
using static DigitalLearningSolutions.Web.Services.ICentreSelfAssessmentsService;
using System;
using IsolationLevel = System.Transactions.IsolationLevel;
using Serilog;

public class Startup
Expand Down Expand Up @@ -581,6 +580,7 @@ private static void RegisterWebServiceFilters(IServiceCollection services)
services.AddScoped<VerifyUserHasVerifiedPrimaryEmail>();
services.AddScoped<VerifyAdminAndDelegateUserCentre>();
services.AddScoped<IsCentreAuthorizedSelfAssessment>();
services.AddScoped<VerifyAdminUserCanAccessSelfAssessment>();
}

public void Configure(IApplicationBuilder app, IMigrationRunner migrationRunner, IFeatureManager featureManager)
Expand Down
Loading