diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs index 7a7b6c0194..fbdcd33553 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/AssessmentQuestions.cs @@ -9,6 +9,7 @@ using DigitalLearningSolutions.Data.Models.SessionData.Frameworks; using System.Collections.Generic; using DigitalLearningSolutions.Data.Enums; + using DigitalLearningSolutions.Web.Helpers; public partial class FrameworksController { @@ -430,7 +431,8 @@ public IActionResult EditAssessmentQuestionOptions(AssessmentQuestionDetail asse if (!ModelState.IsValid) { return RedirectToAction("EditAssessmentQuestionOptions", "Frameworks", new { frameworkId, assessmentQuestionId, frameworkCompetencyId }); - } + } + assessmentQuestionDetail.ScoringInstructions = SanitizerHelper.SanitizeHtmlData(assessmentQuestionDetail.ScoringInstructions); SessionAssessmentQuestion sessionAssessmentQuestion = multiPageFormService.GetMultiPageFormData( MultiPageFormDataFeature.EditAssessmentQuestion, TempData diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs index 95eaebc72b..2fa74c231c 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Competencies.cs @@ -1,40 +1,42 @@ -using DigitalLearningSolutions.Data.Models.Frameworks; +using DigitalLearningSolutions.Data.Models.Frameworks; using DigitalLearningSolutions.Data.Models.SearchSortFilterPaginate; -using DigitalLearningSolutions.Data.Models.SelfAssessments; -using DigitalLearningSolutions.Web.ViewModels.Frameworks; -using DigitalLearningSolutions.Web.ViewModels.LearningPortal.SelfAssessments; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.Extensions.Logging; -using System.Linq; +using DigitalLearningSolutions.Data.Models.SelfAssessments; +using DigitalLearningSolutions.Web.Helpers; +using DigitalLearningSolutions.Web.ViewModels.Frameworks; +using DigitalLearningSolutions.Web.ViewModels.LearningPortal.SelfAssessments; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.Extensions.Logging; +using System.Linq; +using System.Web; using System.Net; -namespace DigitalLearningSolutions.Web.Controllers.FrameworksController -{ - public partial class FrameworksController - { - [Route("/Frameworks/{frameworkId}/CompetencyGroup/{frameworkCompetencyGroupId}")] - [Route("/Frameworks/{frameworkId}/CompetencyGroup")] - public IActionResult AddEditFrameworkCompetencyGroup(int frameworkId, int frameworkCompetencyGroupId = 0) - { - var detailFramework = frameworkService.GetDetailFrameworkByFrameworkId(frameworkId, GetAdminId()); - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); - if (userRole < 2) return StatusCode(403); - var competencyGroupBase = new CompetencyGroupBase(); - if (frameworkCompetencyGroupId > 0) competencyGroupBase = frameworkService.GetCompetencyGroupBaseById(frameworkCompetencyGroupId); - if (detailFramework == null || competencyGroupBase == null) return StatusCode(404); - var model = new CompetencyGroupViewModel() - { - DetailFramework = detailFramework, - CompetencyGroupBase = competencyGroupBase, - }; - return View("Developer/CompetencyGroup", model); - } - [HttpPost] - [Route("/Frameworks/{frameworkId}/CompetencyGroup/{frameworkCompetencyGroupId}")] - [Route("/Frameworks/{frameworkId}/CompetencyGroup")] - public IActionResult AddEditFrameworkCompetencyGroup(int frameworkId, CompetencyGroupBase competencyGroupBase, int frameworkCompetencyGroupId = 0) - { +namespace DigitalLearningSolutions.Web.Controllers.FrameworksController +{ + public partial class FrameworksController + { + [Route("/Frameworks/{frameworkId}/CompetencyGroup/{frameworkCompetencyGroupId}")] + [Route("/Frameworks/{frameworkId}/CompetencyGroup")] + public IActionResult AddEditFrameworkCompetencyGroup(int frameworkId, int frameworkCompetencyGroupId = 0) + { + var detailFramework = frameworkService.GetDetailFrameworkByFrameworkId(frameworkId, GetAdminId()); + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); + if (userRole < 2) return StatusCode(403); + var competencyGroupBase = new CompetencyGroupBase(); + if (frameworkCompetencyGroupId > 0) competencyGroupBase = frameworkService.GetCompetencyGroupBaseById(frameworkCompetencyGroupId); + if (detailFramework == null || competencyGroupBase == null) return StatusCode(404); + var model = new CompetencyGroupViewModel() + { + DetailFramework = detailFramework, + CompetencyGroupBase = competencyGroupBase, + }; + return View("Developer/CompetencyGroup", model); + } + [HttpPost] + [Route("/Frameworks/{frameworkId}/CompetencyGroup/{frameworkCompetencyGroupId}")] + [Route("/Frameworks/{frameworkId}/CompetencyGroup")] + public IActionResult AddEditFrameworkCompetencyGroup(int frameworkId, CompetencyGroupBase competencyGroupBase, int frameworkCompetencyGroupId = 0) + { if (!ModelState.IsValid) { if (ModelState["Name"].ValidationState == ModelValidationState.Invalid) @@ -48,40 +50,41 @@ public IActionResult AddEditFrameworkCompetencyGroup(int frameworkId, Competency ModelState.Remove(nameof(CompetencyGroupBase.Description)); ModelState.AddModelError(nameof(CompetencyGroupBase.Description), "Please enter a valid competency group description (between 0 and 1000 characters)"); } - - // do something - var detailFramework = frameworkService.GetDetailFrameworkByFrameworkId(frameworkId, GetAdminId()); - if (detailFramework == null) return StatusCode(404); - var model = new CompetencyGroupViewModel() - { - DetailFramework = detailFramework, - CompetencyGroupBase = competencyGroupBase - }; - return View("Developer/CompetencyGroup", model); - } - var adminId = GetAdminId(); - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(adminId, frameworkId); - if (userRole < 2) return StatusCode(403); - if (competencyGroupBase.ID > 0) - { - frameworkService.UpdateFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupBase.CompetencyGroupID, competencyGroupBase.Name, competencyGroupBase.Description, adminId); - return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()); - } - var newCompetencyGroupId = frameworkService.InsertCompetencyGroup(competencyGroupBase.Name, competencyGroupBase.Description, adminId); - if (newCompetencyGroupId > 0) - { - var newFrameworkCompetencyGroupId = frameworkService.InsertFrameworkCompetencyGroup(newCompetencyGroupId, frameworkId, adminId); - return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId = newFrameworkCompetencyGroupId }) + "#fcgroup-" + newFrameworkCompetencyGroupId.ToString()); - } - logger.LogWarning($"Attempt to add framework competency group failed for admin {adminId}."); - return StatusCode(403); - } - public IActionResult MoveFrameworkCompetencyGroup(int frameworkId, int frameworkCompetencyGroupId, bool step, string direction) - { - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); - if (userRole < 2) return StatusCode(403); - frameworkService.MoveFrameworkCompetencyGroup(frameworkCompetencyGroupId, step, direction); - return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()); + + // do something + var detailFramework = frameworkService.GetDetailFrameworkByFrameworkId(frameworkId, GetAdminId()); + if (detailFramework == null) return StatusCode(404); + var model = new CompetencyGroupViewModel() + { + DetailFramework = detailFramework, + CompetencyGroupBase = competencyGroupBase + }; + return View("Developer/CompetencyGroup", model); + } + var adminId = GetAdminId(); + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(adminId, frameworkId); + if (userRole < 2) return StatusCode(403); + if (competencyGroupBase.ID > 0) + { + frameworkService.UpdateFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupBase.CompetencyGroupID, competencyGroupBase.Name, SanitizerHelper.SanitizeHtmlData + (competencyGroupBase.Description), adminId); + return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()); + } + var newCompetencyGroupId = frameworkService.InsertCompetencyGroup(competencyGroupBase.Name, SanitizerHelper.SanitizeHtmlData(competencyGroupBase.Description), adminId); + if (newCompetencyGroupId > 0) + { + var newFrameworkCompetencyGroupId = frameworkService.InsertFrameworkCompetencyGroup(newCompetencyGroupId, frameworkId, adminId); + return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId = newFrameworkCompetencyGroupId }) + "#fcgroup-" + newFrameworkCompetencyGroupId.ToString()); + } + logger.LogWarning($"Attempt to add framework competency group failed for admin {adminId}."); + return StatusCode(403); + } + public IActionResult MoveFrameworkCompetencyGroup(int frameworkId, int frameworkCompetencyGroupId, bool step, string direction) + { + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); + if (userRole < 2) return StatusCode(403); + frameworkService.MoveFrameworkCompetencyGroup(frameworkCompetencyGroupId, step, direction); + return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()); } [Route("/Frameworks/{frameworkId}/CompetencyGroup/{frameworkCompetencyGroupId}/{competencyGroupId}/Remove/{competencyCount}/Confirm")] public IActionResult CompetencyGroupRemoveConfirm(int frameworkId, int frameworkCompetencyGroupId, int competencyGroupId, int competencyCount) @@ -89,125 +92,126 @@ public IActionResult CompetencyGroupRemoveConfirm(int frameworkId, int framework var model = new CompetencyGroupRemoveConfirmViewModel(frameworkId, frameworkCompetencyGroupId, competencyGroupId, competencyCount); return View("Developer/CompetencyGroupRemoveConfirm", model); - } - - public IActionResult DeleteFrameworkCompetencyGroup(int frameworkId, int competencyGroupId, int frameworkCompetencyGroupId) - { - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); + } + + public IActionResult DeleteFrameworkCompetencyGroup(int frameworkId, int competencyGroupId, int frameworkCompetencyGroupId) + { + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); if (userRole < 2) return StatusCode(403); var adminId = GetAdminId(); frameworkService.DeleteFrameworkCompetencyGroup(frameworkCompetencyGroupId, competencyGroupId, adminId); - return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId })); - } - [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}/{frameworkCompetencyId}")] - [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}")] - [Route("/Frameworks/{frameworkId}/Competency/")] - public IActionResult AddEditFrameworkCompetency(int frameworkId, int? frameworkCompetencyGroupId, int frameworkCompetencyId = 0) - { - var adminId = GetAdminId(); - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(adminId, frameworkId); - if (userRole < 2) return StatusCode(403); - var frameworkCompetency = new FrameworkCompetency(); - if (frameworkCompetencyId > 0) - { - frameworkCompetency = frameworkService.GetFrameworkCompetencyById(frameworkCompetencyId); - } + return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId })); + } + [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}/{frameworkCompetencyId}")] + [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}")] + [Route("/Frameworks/{frameworkId}/Competency/")] + public IActionResult AddEditFrameworkCompetency(int frameworkId, int? frameworkCompetencyGroupId, int frameworkCompetencyId = 0) + { + var adminId = GetAdminId(); + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(adminId, frameworkId); + if (userRole < 2) return StatusCode(403); + var frameworkCompetency = new FrameworkCompetency(); + if (frameworkCompetencyId > 0) + { + frameworkCompetency = frameworkService.GetFrameworkCompetencyById(frameworkCompetencyId); + } var detailFramework = frameworkService.GetDetailFrameworkByFrameworkId(frameworkId, adminId); - var competencyFlags = frameworkService.GetCompetencyFlagsByFrameworkId(frameworkId, frameworkCompetency?.CompetencyID); - if (detailFramework == null || frameworkCompetency == null) return StatusCode(404); - var model = new FrameworkCompetencyViewModel() - { - DetailFramework = detailFramework, - FrameworkCompetencyGroupId = frameworkCompetencyGroupId, + var competencyFlags = frameworkService.GetCompetencyFlagsByFrameworkId(frameworkId, frameworkCompetency?.CompetencyID); + if (detailFramework == null || frameworkCompetency == null) return StatusCode(404); + var model = new FrameworkCompetencyViewModel() + { + DetailFramework = detailFramework, + FrameworkCompetencyGroupId = frameworkCompetencyGroupId, FrameworkCompetency = frameworkCompetency, - CompetencyFlags = competencyFlags - }; - return View("Developer/Competency", model); - } - [HttpPost] - [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}/{frameworkCompetencyId}")] - [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}")] - [Route("/Frameworks/{frameworkId}/Competency/")] - public IActionResult AddEditFrameworkCompetency(int frameworkId, FrameworkCompetency frameworkCompetency, int? frameworkCompetencyGroupId, int frameworkCompetencyId = 0, int[] selectedFlagIds = null) - { - if (!ModelState.IsValid) - { - ModelState.Remove(nameof(FrameworkCompetency.Name)); - ModelState.AddModelError(nameof(FrameworkCompetency.Name), "Please enter a valid competency statement (between 3 and 500 characters)"); + CompetencyFlags = competencyFlags + }; + return View("Developer/Competency", model); + } + [HttpPost] + [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}/{frameworkCompetencyId}")] + [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}")] + [Route("/Frameworks/{frameworkId}/Competency/")] + public IActionResult AddEditFrameworkCompetency(int frameworkId, FrameworkCompetency frameworkCompetency, int? frameworkCompetencyGroupId, int frameworkCompetencyId = 0, int[] selectedFlagIds = null) + { + frameworkCompetency.Description = SanitizerHelper.SanitizeHtmlData(frameworkCompetency.Description); + if (!ModelState.IsValid) + { + ModelState.Remove(nameof(FrameworkCompetency.Name)); + ModelState.AddModelError(nameof(FrameworkCompetency.Name), "Please enter a valid competency statement (between 3 and 500 characters)"); var detailFramework = frameworkService.GetDetailFrameworkByFrameworkId(frameworkId, GetAdminId()); var competencyFlags = frameworkService.GetCompetencyFlagsByFrameworkId(frameworkId, frameworkCompetency?.CompetencyID).ToList(); if(competencyFlags != null) - competencyFlags.ForEach(f => f.Selected = selectedFlagIds.Contains(f.FlagId)); + competencyFlags.ForEach(f => f.Selected = selectedFlagIds.Contains(f.FlagId)); if (detailFramework == null) - return StatusCode((int)HttpStatusCode.NotFound); - var model = new FrameworkCompetencyViewModel() - { - DetailFramework = detailFramework, - FrameworkCompetencyGroupId = frameworkCompetencyId, + return StatusCode((int)HttpStatusCode.NotFound); + var model = new FrameworkCompetencyViewModel() + { + DetailFramework = detailFramework, + FrameworkCompetencyGroupId = frameworkCompetencyId, FrameworkCompetency = frameworkCompetency, CompetencyFlags = competencyFlags - }; - return View("Developer/Competency", model); - } - var adminId = GetAdminId(); - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(adminId, frameworkId); - if (userRole < 2) return StatusCode((int)HttpStatusCode.Forbidden); - if (frameworkCompetency.Id > 0) - { + }; + return View("Developer/Competency", model); + } + var adminId = GetAdminId(); + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(adminId, frameworkId); + if (userRole < 2) return StatusCode((int)HttpStatusCode.Forbidden); + if (frameworkCompetency.Id > 0) + { frameworkService.UpdateFrameworkCompetency(frameworkCompetencyId, frameworkCompetency.Name, frameworkCompetency.Description, adminId); - frameworkService.UpdateCompetencyFlags(frameworkId, frameworkCompetency.CompetencyID, selectedFlagIds); - return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId, frameworkCompetencyId }) + "#fc-" + frameworkCompetencyId.ToString()); - } - var newCompetencyId = frameworkService.InsertCompetency(frameworkCompetency.Name, frameworkCompetency.Description, adminId); - if (newCompetencyId > 0) - { + frameworkService.UpdateCompetencyFlags(frameworkId, frameworkCompetency.CompetencyID, selectedFlagIds); + return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId, frameworkCompetencyId }) + "#fc-" + frameworkCompetencyId.ToString()); + } + var newCompetencyId = frameworkService.InsertCompetency(frameworkCompetency.Name, frameworkCompetency.Description, adminId); + if (newCompetencyId > 0) + { var newFrameworkCompetencyId = frameworkService.InsertFrameworkCompetency(newCompetencyId, frameworkCompetencyGroupId, adminId, frameworkId); frameworkService.UpdateCompetencyFlags(frameworkId, newCompetencyId, selectedFlagIds); - return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId, frameworkCompetencyId }) + "#fc-" + newFrameworkCompetencyId.ToString()); - } - logger.LogWarning($"Attempt to add framework competency failed for admin {adminId}."); - return StatusCode((int)HttpStatusCode.Forbidden); - } - public IActionResult MoveFrameworkCompetency(int frameworkId, int frameworkCompetencyGroupId, int frameworkCompetencyId, bool step, string direction) - { - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); - if (userRole < 2) return StatusCode(403); - frameworkService.MoveFrameworkCompetency(frameworkCompetencyId, step, direction); - return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId, frameworkCompetencyId }) + "#fc-" + frameworkCompetencyId.ToString()); - } - public IActionResult DeleteFrameworkCompetency(int frameworkId, int frameworkCompetencyId, int? frameworkCompetencyGroupId) - { - var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); - if (userRole < 2) return StatusCode(403); - frameworkService.DeleteFrameworkCompetency(frameworkCompetencyId, GetAdminId()); - return frameworkCompetencyGroupId != null ? new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()) : new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fc-ungrouped"); - } - [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}/{frameworkCompetencyId}/Preview/")] - public IActionResult PreviewCompetency(int frameworkId, int frameworkCompetencyGroupId, int frameworkCompetencyId) - { - var adminId = GetAdminId(); - var assessment = new CurrentSelfAssessment() - { - LaunchCount = 0, - UnprocessedUpdates = false, - }; - var competency = frameworkService.GetFrameworkCompetencyForPreview(frameworkCompetencyId); - if (competency != null) - { - foreach (var assessmentQuestion in competency.AssessmentQuestions) - { - assessmentQuestion.LevelDescriptors = frameworkService.GetLevelDescriptorsForAssessmentQuestionId(assessmentQuestion.Id, adminId, assessmentQuestion.MinValue, assessmentQuestion.MaxValue, assessmentQuestion.MinValue == 0).ToList(); + return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId, frameworkCompetencyId }) + "#fc-" + newFrameworkCompetencyId.ToString()); + } + logger.LogWarning($"Attempt to add framework competency failed for admin {adminId}."); + return StatusCode((int)HttpStatusCode.Forbidden); + } + public IActionResult MoveFrameworkCompetency(int frameworkId, int frameworkCompetencyGroupId, int frameworkCompetencyId, bool step, string direction) + { + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); + if (userRole < 2) return StatusCode(403); + frameworkService.MoveFrameworkCompetency(frameworkCompetencyId, step, direction); + return new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId, frameworkCompetencyId }) + "#fc-" + frameworkCompetencyId.ToString()); + } + public IActionResult DeleteFrameworkCompetency(int frameworkId, int frameworkCompetencyId, int? frameworkCompetencyGroupId) + { + var userRole = frameworkService.GetAdminUserRoleForFrameworkId(GetAdminId(), frameworkId); + if (userRole < 2) return StatusCode(403); + frameworkService.DeleteFrameworkCompetency(frameworkCompetencyId, GetAdminId()); + return frameworkCompetencyGroupId != null ? new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId, frameworkCompetencyGroupId }) + "#fcgroup-" + frameworkCompetencyGroupId.ToString()) : new RedirectResult(Url.Action("ViewFramework", new { tabname = "Structure", frameworkId }) + "#fc-ungrouped"); + } + [Route("/Frameworks/{frameworkId}/Competency/{frameworkCompetencyGroupId}/{frameworkCompetencyId}/Preview/")] + public IActionResult PreviewCompetency(int frameworkId, int frameworkCompetencyGroupId, int frameworkCompetencyId) + { + var adminId = GetAdminId(); + var assessment = new CurrentSelfAssessment() + { + LaunchCount = 0, + UnprocessedUpdates = false, + }; + var competency = frameworkService.GetFrameworkCompetencyForPreview(frameworkCompetencyId); + if (competency != null) + { + foreach (var assessmentQuestion in competency.AssessmentQuestions) + { + assessmentQuestion.LevelDescriptors = frameworkService.GetLevelDescriptorsForAssessmentQuestionId(assessmentQuestion.Id, adminId, assessmentQuestion.MinValue, assessmentQuestion.MaxValue, assessmentQuestion.MinValue == 0).ToList(); } var model = new SelfAssessmentCompetencyViewModel(assessment, competency, 1, 1); - competency.CompetencyFlags = frameworkService.GetCompetencyFlagsByFrameworkId(frameworkId, competency.Id, selected: true); - return View("Developer/CompetencyPreview", model); - } - logger.LogWarning($"Attempt to preview competency failed for frameworkCompetencyId {frameworkCompetencyId}."); - return StatusCode(500); - } - } -} + competency.CompetencyFlags = frameworkService.GetCompetencyFlagsByFrameworkId(frameworkId, competency.Id, selected: true); + return View("Developer/CompetencyPreview", model); + } + logger.LogWarning($"Attempt to preview competency failed for frameworkCompetencyId {frameworkCompetencyId}."); + return StatusCode(500); + } + } +} diff --git a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs index c0ce5b3504..12d37c4902 100644 --- a/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs +++ b/DigitalLearningSolutions.Web/Controllers/FrameworksController/Frameworks.cs @@ -14,6 +14,7 @@ namespace DigitalLearningSolutions.Web.Controllers.FrameworksController using DigitalLearningSolutions.Data.Helpers; using DigitalLearningSolutions.Data.Models.SearchSortFilterPaginate; using DigitalLearningSolutions.Web.Attributes; + using DigitalLearningSolutions.Web.Helpers; using DigitalLearningSolutions.Web.Models.Enums; using DigitalLearningSolutions.Web.ViewModels.Common; using System.Net; @@ -335,6 +336,7 @@ public IActionResult FrameworkDescription(DetailFramework detailFramework, strin } return RedirectToAction("FrameworkType", "Frameworks", new { actionname }); } + detailFramework.Description = SanitizerHelper.SanitizeHtmlData(detailFramework.Description); frameworkService.UpdateFrameworkDescription(frameworkId, GetAdminId(), detailFramework.Description); return RedirectToAction("ViewFramework", new { tabname = "Details", frameworkId }); @@ -739,6 +741,7 @@ public IActionResult InsertFramework() logger.LogWarning($"Failed to create framework: adminId: {adminId}"); return StatusCode(500); } + detailFramework.Description = SanitizerHelper.SanitizeHtmlData(detailFramework.Description); var newFramework = frameworkService.CreateFramework(detailFramework, adminId); TempData.Clear(); return RedirectToAction("AddCollaborators", "Frameworks", new { actionname = "New", frameworkId = newFramework.ID }); diff --git a/DigitalLearningSolutions.Web/DigitalLearningSolutions.Web.csproj b/DigitalLearningSolutions.Web/DigitalLearningSolutions.Web.csproj index 30c8ba7087..9689a7747e 100644 --- a/DigitalLearningSolutions.Web/DigitalLearningSolutions.Web.csproj +++ b/DigitalLearningSolutions.Web/DigitalLearningSolutions.Web.csproj @@ -61,6 +61,7 @@ + diff --git a/DigitalLearningSolutions.Web/Helpers/SanitizerHelper.cs b/DigitalLearningSolutions.Web/Helpers/SanitizerHelper.cs new file mode 100644 index 0000000000..0b6dc1a1a7 --- /dev/null +++ b/DigitalLearningSolutions.Web/Helpers/SanitizerHelper.cs @@ -0,0 +1,15 @@ +namespace DigitalLearningSolutions.Web.Helpers +{ + using Ganss.XSS; + public static class SanitizerHelper + { + public static string SanitizeHtmlData(string htmlData) + { + var sanitizer = new HtmlSanitizer(); + sanitizer.AllowedTags.Remove("iframe"); + sanitizer.AllowedTags.Remove("img"); + var sanitized = sanitizer.Sanitize(htmlData); + return sanitized; + } + } +} diff --git a/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts b/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts index 0caaf6701c..8577474744 100644 --- a/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts +++ b/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts @@ -1,4 +1,5 @@ import { Jodit } from 'jodit'; +import DOMPurify from 'dompurify'; let jodited = false; if (jodited === false) { @@ -65,5 +66,9 @@ if (jodited === false) { if (editor != null) { jodited = true; + editor.e.on('blur', () => { + const clean = DOMPurify.sanitize(editor.editor.innerHTML); + editor.editor.innerHTML = clean; + }); } } diff --git a/DigitalLearningSolutions.Web/package.json b/DigitalLearningSolutions.Web/package.json index 41c84ff800..f7146d8ad3 100644 --- a/DigitalLearningSolutions.Web/package.json +++ b/DigitalLearningSolutions.Web/package.json @@ -38,6 +38,7 @@ "@babel/core": "^7.18.0", "@babel/preset-env": "^7.18.0", "@babel/preset-typescript": "^7.17.12", + "@types/dompurify": "^2.3.3", "@types/jest": "^27.5.1", "@types/js-cookie": "^3.0.2", "@types/js-search": "^1.4.0", diff --git a/DigitalLearningSolutions.Web/yarn.lock b/DigitalLearningSolutions.Web/yarn.lock index d5df3f5c16..10b4d04444 100644 --- a/DigitalLearningSolutions.Web/yarn.lock +++ b/DigitalLearningSolutions.Web/yarn.lock @@ -1434,6 +1434,13 @@ resolved "https://registry.yarnpkg.com/@types/chartist/-/chartist-0.11.1.tgz#3825e6cee87f5f548e8631b2c25e3a7b597b2522" integrity sha512-85eNd7rF+e5sLnpprgcDdeqARgNvczEXaBfnrkw0292TBCE4KF/2HmOPA6dIblyHUWV4OZ2kuQBH2R12F+VwYg== +"@types/dompurify@^2.3.3": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.3.4.tgz#94e997e30338ea24d4c8d08beca91ce4dd17a1b4" + integrity sha512-EXzDatIb5EspL2eb/xPGmaC8pePcTHrkDCONjeisusLFrVfl38Pjea/R0YJGu3k9ZQadSvMqW0WXPI2hEo2Ajg== + dependencies: + "@types/trusted-types" "*" + "@types/eslint-scope@^3.7.3": version "3.7.3" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" @@ -1553,6 +1560,11 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== +"@types/trusted-types@*": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" + integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"