Skip to content

Commit 1dc6b01

Browse files
authored
Merge pull request #2855 from TechnologyEnhancedLearning/Develop/Fixes/TD-4702-Downloadself-assessmentcertificatelinkURLcanbemanipulatedandabletodownloadotheruservalidcertificates
TD-4702 Resolving the route issue
2 parents a498a5c + c23d0b2 commit 1dc6b01

File tree

5 files changed

+126
-22
lines changed

5 files changed

+126
-22
lines changed

DigitalLearningSolutions.Web.Tests/Controllers/SupervisorController/SupervisorControllerTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class SupervisorControllerTests
3131
private IEmailService emailService = null!;
3232
private IClockUtility clockUtility = null!;
3333
private ICandidateAssessmentDownloadFileService candidateAssessmentDownloadFileService = null!;
34+
private IPdfService pdfService = null!;
3435

3536
[SetUp]
3637
public void Setup()
@@ -53,7 +54,7 @@ public void Setup()
5354
emailService = A.Fake<IEmailService>();
5455
clockUtility = A.Fake<IClockUtility>();
5556
candidateAssessmentDownloadFileService = A.Fake<ICandidateAssessmentDownloadFileService>();
56-
57+
pdfService = A.Fake<IPdfService>();
5758
A.CallTo(() => candidateAssessmentDownloadFileService.GetCandidateAssessmentDownloadFileForCentre(A<int>._, A<int>._, A<bool>._))
5859
.Returns(new byte[] { });
5960
}
@@ -81,7 +82,8 @@ public void ExportCandidateAssessment_should_return_file_object_with_file_name_i
8182
emailGenerationService,
8283
emailService,
8384
candidateAssessmentDownloadFileService,
84-
clockUtility
85+
clockUtility,
86+
pdfService
8587
);
8688
string expectedFileName = $"{((selfAssessmentName.Length > 30) ? selfAssessmentName.Substring(0, 30) : selfAssessmentName)} - {delegateName} - {clockUtility.UtcNow:yyyy-MM-dd}.xlsx";
8789

DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,29 +1727,19 @@ public IActionResult CompetencySelfAssessmentCertificate(int CandidateAssessment
17271727
return View("SelfAssessments/CompetencySelfAssessmentCertificate", model);
17281728
}
17291729

1730-
[Route("/LearningPortal/selfAssessments/{CandidateAssessmentId:int}/{vocabulary}/DownloadCertificate")]
1731-
public async Task<IActionResult> DownloadCertificate(int candidateAssessmentId, string vocabulary)
1730+
[Route("/LearningPortal/selfAssessments/{CandidateAssessmentId:int}/Proficiencies/DownloadCertificate")]
1731+
public async Task<IActionResult> DownloadCertificate(int candidateAssessmentId)
17321732
{
17331733
PdfReportStatusResponse pdfReportStatusResponse = new PdfReportStatusResponse();
17341734
var delegateId = User.GetCandidateIdKnownNotNull();
1735+
var userId = User.GetUserIdKnownNotNull();
1736+
17351737
var competencymaindata = selfAssessmentService.GetCompetencySelfAssessmentCertificate(candidateAssessmentId);
1736-
if (competencymaindata == null || candidateAssessmentId == 0)
1738+
if (competencymaindata == null || candidateAssessmentId == 0 || userId == 0)
17371739
{
17381740
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
17391741
}
1740-
if (vocabulary == "Proficiencies")
1741-
{
1742-
var userId = User.GetUserIdKnownNotNull();
17431742
if (userId != competencymaindata.LearnerId) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
1744-
1745-
}
1746-
if (vocabulary == "ProfileAssessment")
1747-
{
1748-
var adminId = User.GetAdminId();
1749-
var supervisorDelegateDetails = supervisorService.GetSupervisorDelegateDetailsForAdminId(adminId.Value);
1750-
var checkSupervisorDelegate = supervisorDelegateDetails.Where(x => x.DelegateUserID == competencymaindata.LearnerId).FirstOrDefault();
1751-
if (checkSupervisorDelegate == null) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
1752-
}
17531743
var delegateUserId = competencymaindata.LearnerId;
17541744
var competencycount = selfAssessmentService.GetCompetencyCountSelfAssessmentCertificate(candidateAssessmentId);
17551745
var accessors = selfAssessmentService.GetAccessor(competencymaindata.SelfAssessmentID, competencymaindata.LearnerId);
@@ -1790,7 +1780,7 @@ public async Task<IActionResult> DownloadCertificate(int candidateAssessmentId,
17901780
return View("SelfAssessments/CompetencySelfAssessmentCertificate", model);
17911781
}
17921782

1793-
public static string RenderRazorViewToString(Controller controller, string viewName, object model = null)
1783+
private static string RenderRazorViewToString(Controller controller, string viewName, object model = null)
17941784
{
17951785
controller.ViewData.Model = model;
17961786
using (var sw = new StringWriter())

DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using DigitalLearningSolutions.Data.Enums;
44
using DigitalLearningSolutions.Data.Helpers;
55
using DigitalLearningSolutions.Data.Models;
6+
using DigitalLearningSolutions.Data.Models.Common;
67
using DigitalLearningSolutions.Data.Models.SearchSortFilterPaginate;
78
using DigitalLearningSolutions.Data.Models.SelfAssessments;
89
using DigitalLearningSolutions.Data.Models.SessionData.Supervisor;
@@ -11,13 +12,19 @@
1112
using DigitalLearningSolutions.Web.Extensions;
1213
using DigitalLearningSolutions.Web.Helpers;
1314
using DigitalLearningSolutions.Web.ServiceFilter;
15+
using DigitalLearningSolutions.Web.Services;
1416
using DigitalLearningSolutions.Web.ViewModels.Common.SearchablePage;
1517
using DigitalLearningSolutions.Web.ViewModels.Supervisor;
1618
using GDS.MultiPageFormData.Enums;
1719
using Microsoft.AspNetCore.Mvc;
20+
using Microsoft.AspNetCore.Mvc.Rendering;
21+
using Microsoft.AspNetCore.Mvc.ViewEngines;
22+
using Microsoft.AspNetCore.Mvc.ViewFeatures;
1823
using System;
1924
using System.Collections.Generic;
25+
using System.IO;
2026
using System.Linq;
27+
using System.Threading.Tasks;
2128

2229
public partial class SupervisorController
2330
{
@@ -1401,5 +1408,109 @@ public IActionResult CompetencySelfAssessmentCertificatesupervisor(int candidate
14011408
var model = new ViewModels.LearningPortal.SelfAssessments.CompetencySelfAssessmentCertificateViewModel(competencymaindata, competencycount, "ProfileAssessment", accessors, activitySummaryCompetencySelfAssesment, sumQuestions, sumVerifiedCount, supervisorDelegateId);
14021409
return View("SelfAssessments/CompetencySelfAssessmentCertificate", model);
14031410
}
1411+
[Route("/Supervisor/Staff/{CandidateAssessmentId:int}/ProfileAssessment/DownloadCertificate")]
1412+
public async Task<IActionResult> DownloadCertificate(int candidateAssessmentId)
1413+
{
1414+
PdfReportStatusResponse pdfReportStatusResponse = new PdfReportStatusResponse();
1415+
var delegateId = User.GetCandidateIdKnownNotNull();
1416+
var adminId = User.GetAdminId();
1417+
var competencymaindata = selfAssessmentService.GetCompetencySelfAssessmentCertificate(candidateAssessmentId);
1418+
if (competencymaindata == null || candidateAssessmentId == 0 || adminId == 0)
1419+
{
1420+
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
1421+
}
1422+
var supervisorDelegateDetails = supervisorService.GetSupervisorDelegateDetailsForAdminId(adminId.Value);
1423+
var checkSupervisorDelegate = supervisorDelegateDetails.Where(x => x.DelegateUserID == competencymaindata.LearnerId).FirstOrDefault();
1424+
if (checkSupervisorDelegate == null) return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
1425+
var delegateUserId = competencymaindata.LearnerId;
1426+
var competencycount = selfAssessmentService.GetCompetencyCountSelfAssessmentCertificate(candidateAssessmentId);
1427+
var accessors = selfAssessmentService.GetAccessor(competencymaindata.SelfAssessmentID, competencymaindata.LearnerId);
1428+
var activitySummaryCompetencySelfAssesment = selfAssessmentService.GetActivitySummaryCompetencySelfAssesment(competencymaindata.Id);
1429+
var assessment = selfAssessmentService.GetSelfAssessmentForCandidateById(delegateUserId, competencymaindata.SelfAssessmentID);
1430+
var recentResults = selfAssessmentService.GetMostRecentResults(competencymaindata.SelfAssessmentID, competencymaindata.LearnerDelegateAccountId).ToList();
1431+
var competencyIds = recentResults.Select(c => c.Id).ToArray();
1432+
var competencyFlags = frameworkService.GetSelectedCompetencyFlagsByCompetecyIds(competencyIds);
1433+
var competencies = CompetencyFilterHelper.FilterCompetencies(recentResults, competencyFlags, null);
1434+
var supervisorSignOffs = selfAssessmentService.GetSupervisorSignOffsForCandidateAssessment(competencymaindata.SelfAssessmentID, delegateUserId);
1435+
if (!CertificateHelper.CanViewCertificate(recentResults, supervisorSignOffs))
1436+
{
1437+
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 401 });
1438+
}
1439+
foreach (var competency in competencies)
1440+
{
1441+
competency.QuestionLabel = assessment.QuestionLabel;
1442+
foreach (var assessmentQuestion in competency.AssessmentQuestions)
1443+
{
1444+
if (assessmentQuestion.AssessmentQuestionInputTypeID != 2)
1445+
{
1446+
assessmentQuestion.LevelDescriptors = selfAssessmentService
1447+
.GetLevelDescriptorsForAssessmentQuestion(
1448+
assessmentQuestion.Id,
1449+
assessmentQuestion.MinValue,
1450+
assessmentQuestion.MaxValue,
1451+
assessmentQuestion.MinValue == 0
1452+
).ToList();
1453+
}
1454+
}
1455+
}
1456+
1457+
var CompetencyGroups = competencies.GroupBy(competency => competency.CompetencyGroup);
1458+
var competencySummaries = from g in CompetencyGroups
1459+
let questions = g.SelectMany(c => c.AssessmentQuestions).Where(q => q.Required)
1460+
let selfAssessedCount = questions.Count(q => q.Result.HasValue)
1461+
let verifiedCount = questions.Count(q => !((q.Result == null || q.Verified == null || q.SignedOff != true) && q.Required))
1462+
select new
1463+
{
1464+
SelfAssessedCount = selfAssessedCount,
1465+
VerifiedCount = verifiedCount,
1466+
Questions = questions.Count()
1467+
};
1468+
1469+
int sumVerifiedCount = competencySummaries.Sum(item => item.VerifiedCount);
1470+
int sumQuestions = competencySummaries.Sum(item => item.Questions);
1471+
var model = new ViewModels.LearningPortal.SelfAssessments.CompetencySelfAssessmentCertificateViewModel(competencymaindata, competencycount, "Proficiencies", accessors, activitySummaryCompetencySelfAssesment, sumQuestions, sumVerifiedCount, null);
1472+
var renderedViewHTML = RenderRazorViewToString(this, "SelfAssessments/DownloadCompetencySelfAssessmentCertificate", model);
1473+
1474+
var pdfReportResponse = await pdfService.PdfReport(candidateAssessmentId.ToString(), renderedViewHTML, delegateId);
1475+
if (pdfReportResponse != null)
1476+
{
1477+
do
1478+
{
1479+
pdfReportStatusResponse = await pdfService.PdfReportStatus(pdfReportResponse);
1480+
} while (pdfReportStatusResponse.Id == 1);
1481+
1482+
var pdfReportFile = await pdfService.GetPdfReportFile(pdfReportResponse);
1483+
if (pdfReportFile != null)
1484+
{
1485+
var nameTextLength = string.IsNullOrEmpty(model.CompetencySelfAssessmentCertificates.LearnerName) ? 0 : model.CompetencySelfAssessmentCertificates.LearnerName.Length;
1486+
var isPrnExist = !string.IsNullOrEmpty(model.CompetencySelfAssessmentCertificates.LearnerPRN);
1487+
var fileName = $"Competency Certificate - {model.CompetencySelfAssessmentCertificates.LearnerName.Substring(0, nameTextLength >= 15 ? 15 : nameTextLength)}" + (isPrnExist ? $" - {model.CompetencySelfAssessmentCertificates.LearnerPRN}.pdf" : ".pdf");
1488+
return File(pdfReportFile, FileHelper.GetContentTypeFromFileName(fileName), fileName);
1489+
}
1490+
}
1491+
return View("SelfAssessments/CompetencySelfAssessmentCertificate", model);
1492+
}
1493+
private static string RenderRazorViewToString(Controller controller, string viewName, object model = null)
1494+
{
1495+
controller.ViewData.Model = model;
1496+
using (var sw = new StringWriter())
1497+
{
1498+
IViewEngine viewEngine =
1499+
controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as
1500+
ICompositeViewEngine;
1501+
ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, false);
1502+
1503+
ViewContext viewContext = new ViewContext(
1504+
controller.ControllerContext,
1505+
viewResult.View,
1506+
controller.ViewData,
1507+
controller.TempData,
1508+
sw,
1509+
new HtmlHelperOptions()
1510+
);
1511+
viewResult.View.RenderAsync(viewContext);
1512+
return sw.GetStringBuilder().ToString();
1513+
}
1514+
}
14041515
}
14051516
}

DigitalLearningSolutions.Web/Controllers/SupervisorController/SupervisorController.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public partial class SupervisorController : Controller
2626
private readonly IEmailService emailService;
2727
private readonly ICandidateAssessmentDownloadFileService candidateAssessmentDownloadFileService;
2828
private readonly IClockUtility clockUtility;
29+
private readonly IPdfService pdfService;
2930

3031
public SupervisorController(
3132
ISupervisorService supervisorService,
@@ -45,7 +46,8 @@ public SupervisorController(
4546
IEmailGenerationService emailGenerationService,
4647
IEmailService emailService,
4748
ICandidateAssessmentDownloadFileService candidateAssessmentDownloadFileService,
48-
IClockUtility clockUtility
49+
IClockUtility clockUtility,
50+
IPdfService pdfService
4951
)
5052
{
5153
this.supervisorService = supervisorService;
@@ -62,6 +64,7 @@ IClockUtility clockUtility
6264
this.emailService = emailService;
6365
this.candidateAssessmentDownloadFileService = candidateAssessmentDownloadFileService;
6466
this.clockUtility = clockUtility;
67+
this.pdfService = pdfService;
6568
}
6669

6770
private int GetCentreId()

DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@
8181
<a class="nhsuk-button "
8282
asp-controller="LearningPortal"
8383
asp-route-candidateAssessmentId="@Model.CompetencySelfAssessmentCertificates.CandidateAssessmentID"
84-
asp-route-vocabulary="Proficiencies"
8584
asp-action="DownloadCertificate"
8685
role="button">
8786
Download certificate
@@ -90,9 +89,8 @@
9089
@if (Model.Vocabulary == "ProfileAssessment")
9190
{
9291
<a class="nhsuk-button "
93-
asp-controller="LearningPortal"
92+
asp-controller="Supervisor"
9493
asp-route-candidateAssessmentId="@Model.CompetencySelfAssessmentCertificates.CandidateAssessmentID"
95-
asp-route-vocabulary="ProfileAssessment"
9694
asp-action="DownloadCertificate"
9795
role="button">
9896
Download certificate

0 commit comments

Comments
 (0)