From 55acd9f689385a1c99b548bd9a10d94507ba1bc8 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Mon, 16 Jun 2025 15:59:11 +0100 Subject: [PATCH 1/6] TD-5665-Adding resources to the community catalogue is suspended --- .../Interfaces/IUserGroupService.cs | 6 ++++++ .../Services/NavigationPermissionService.cs | 13 +++++++++---- .../Services/UserGroupService.cs | 17 ++++++++++++++++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs b/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs index a333e0c89..c91c2e0b2 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs @@ -22,6 +22,12 @@ public interface IUserGroupService /// The . Task> GetRoleUserGroupDetailForUserAsync(int userId); + /// + /// The GetRoleUserGroupDetailAsync. + /// + /// The . + Task UserHasCatalogueContributionPermission(); + /// /// Check if user has given permission. /// diff --git a/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs b/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs index 95e74022e..e381b0403 100644 --- a/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs +++ b/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs @@ -11,14 +11,19 @@ public class NavigationPermissionService : INavigationPermissionService { private readonly IResourceService resourceService; + private readonly IUserGroupService userGroupService; /// /// Initializes a new instance of the class. /// /// Resource service. - public NavigationPermissionService(IResourceService resourceService) + /// UserGroup service. + public NavigationPermissionService( + IResourceService resourceService, + IUserGroupService userGroupService) { this.resourceService = resourceService; + this.userGroupService = userGroupService; } /// @@ -52,7 +57,7 @@ public async Task GetNavigationModelAsync(IPrincipal user, bool } else if (user.IsInRole("BlueUser")) { - return this.AuthenticatedBlueUser(controllerName); + return await this.AuthenticatedBlueUser(controllerName); } else { @@ -114,11 +119,11 @@ private NavigationModel AuthenticatedAdministrator(string controllerName) /// /// The controller name. /// The . - private NavigationModel AuthenticatedBlueUser(string controllerName) + private async Task AuthenticatedBlueUser(string controllerName) { return new NavigationModel() { - ShowMyContributions = true, + ShowMyContributions = await this.userGroupService.UserHasCatalogueContributionPermission(), ShowMyLearning = true, ShowMyBookmarks = true, ShowSearch = controllerName != "search" && controllerName != string.Empty, diff --git a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs index 6790a3143..be77f6531 100644 --- a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs +++ b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs @@ -46,7 +46,10 @@ public UserGroupService( public async Task> GetRoleUserGroupDetailAsync() { var cacheKey = $"{this.contextAccessor.HttpContext.User.Identity.GetCurrentUserId()}:AllRolesWithPermissions"; - return await this.cacheService.GetOrFetchAsync(cacheKey, () => this.FetchRoleUserGroupDetailAsync()); + cacheKey = null; + ////return await this.cacheService.GetOrFetchAsync(cacheKey, () => this.FetchRoleUserGroupDetailAsync()); + + return await this.FetchRoleUserGroupDetailAsync(); } /// @@ -56,6 +59,18 @@ public async Task> GetRoleUserGroupDetailForUserAsy return await this.cacheService.GetOrFetchAsync(cacheKey, () => this.FetchRoleUserGroupDetailForUserAsync(userId)); } + /// + public async Task UserHasCatalogueContributionPermission() + { + var userRoleGroups = await this.GetRoleUserGroupDetailAsync(); + if (userRoleGroups != null && userRoleGroups.Any(r => r.RoleName == "Local Admin" || r.RoleName == "Editor")) + { + return true; + } + + return false; + } + /// public async Task UserHasPermissionAsync(string permissionCode) { From 0bd9e91b7a1562101830f238bff12b6e35bfbbd4 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Mon, 16 Jun 2025 16:59:56 +0100 Subject: [PATCH 2/6] Td-5664: Implement a business rule tieing 'Contribute a resource' and a Catalogue permission/group --- .gitignore | 3 +++ AdminUI/LearningHub.Nhs.AdminUI/web.config | 21 --------------------- LearningHub.Nhs.WebUI/web.config | 21 --------------------- WebAPI/LearningHub.Nhs.API/web.config | 21 --------------------- 4 files changed, 3 insertions(+), 63 deletions(-) delete mode 100644 AdminUI/LearningHub.Nhs.AdminUI/web.config delete mode 100644 LearningHub.Nhs.WebUI/web.config delete mode 100644 WebAPI/LearningHub.Nhs.API/web.config diff --git a/.gitignore b/.gitignore index fcd06e014..8cc7d8bbe 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ obj /AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj.user /WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj.user /ReportAPI/LearningHub.Nhs.ReportApi/web.config +/AdminUI/LearningHub.Nhs.AdminUI/web.config +/LearningHub.Nhs.WebUI/web.config +/WebAPI/LearningHub.Nhs.API/web.config diff --git a/AdminUI/LearningHub.Nhs.AdminUI/web.config b/AdminUI/LearningHub.Nhs.AdminUI/web.config deleted file mode 100644 index 6bcb74972..000000000 --- a/AdminUI/LearningHub.Nhs.AdminUI/web.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/web.config b/LearningHub.Nhs.WebUI/web.config deleted file mode 100644 index 837247997..000000000 --- a/LearningHub.Nhs.WebUI/web.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/WebAPI/LearningHub.Nhs.API/web.config b/WebAPI/LearningHub.Nhs.API/web.config deleted file mode 100644 index 62efcf17d..000000000 --- a/WebAPI/LearningHub.Nhs.API/web.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 4ec4010ce9ad18ef671129196990299e7ab24ff3 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Mon, 16 Jun 2025 17:00:18 +0100 Subject: [PATCH 3/6] TD-5664: Implement a business rule tieing 'Contribute a resource' and a Catalogue permission/group --- .../Hierarchy/CatalogueNodeVersionRepository.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs b/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs index 38f77a37f..d12f1b730 100644 --- a/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs +++ b/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs @@ -81,10 +81,10 @@ public async Task> GetPublishedCatalogues() /// The . public IQueryable GetPublishedCataloguesForUserAsync(int userId) { - var communityCatalogue = this.DbContext.CatalogueNodeVersion.AsNoTracking() - .Include(cnv => cnv.NodeVersion.Node) - .Where(cnv => cnv.NodeVersion.VersionStatusEnum == VersionStatusEnum.Published - && cnv.NodeVersion.NodeId == 1 /* Community Catalogue */); + ////var communityCatalogue = this.DbContext.CatalogueNodeVersion.AsNoTracking() + //// .Include(cnv => cnv.NodeVersion.Node) + //// .Where(cnv => cnv.NodeVersion.VersionStatusEnum == VersionStatusEnum.Published + //// && cnv.NodeVersion.NodeId == 1 /* Community Catalogue */); var cataloguesForUser = from cnv in this.DbContext.CatalogueNodeVersion.Include(cnv => cnv.NodeVersion.Node).AsNoTracking() join nv in this.DbContext.NodeVersion.Where(cnv => cnv.VersionStatusEnum == VersionStatusEnum.Published && !cnv.Deleted) // .Include(nv => nv.Node) @@ -99,7 +99,7 @@ join n in this.DbContext.Node.Where(x => !x.Deleted) on nv.Id equals n.CurrentNodeVersionId select cnv; - var returnedCatalogues = communityCatalogue.Union(cataloguesForUser).Distinct() + var returnedCatalogues = cataloguesForUser.Distinct() .OrderBy(cnv => cnv.NodeVersion.NodeId != 1) .ThenBy(cnv => cnv.Name); From 4e100304432fa253bfcb6a96c44fa30da5d56667 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Mon, 16 Jun 2025 17:07:20 +0100 Subject: [PATCH 4/6] Removed commented lines --- .../Hierarchy/CatalogueNodeVersionRepository.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs b/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs index d12f1b730..5ae373e42 100644 --- a/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs +++ b/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs @@ -81,11 +81,6 @@ public async Task> GetPublishedCatalogues() /// The . public IQueryable GetPublishedCataloguesForUserAsync(int userId) { - ////var communityCatalogue = this.DbContext.CatalogueNodeVersion.AsNoTracking() - //// .Include(cnv => cnv.NodeVersion.Node) - //// .Where(cnv => cnv.NodeVersion.VersionStatusEnum == VersionStatusEnum.Published - //// && cnv.NodeVersion.NodeId == 1 /* Community Catalogue */); - var cataloguesForUser = from cnv in this.DbContext.CatalogueNodeVersion.Include(cnv => cnv.NodeVersion.Node).AsNoTracking() join nv in this.DbContext.NodeVersion.Where(cnv => cnv.VersionStatusEnum == VersionStatusEnum.Published && !cnv.Deleted) // .Include(nv => nv.Node) on cnv.NodeVersionId equals nv.Id From 7d8e96ee0845a289b44c06783dd9d8bda90f7c53 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Tue, 17 Jun 2025 11:11:17 +0100 Subject: [PATCH 5/6] Removed the commented lines --- LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs | 2 +- LearningHub.Nhs.WebUI/Services/UserGroupService.cs | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs b/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs index c91c2e0b2..eadae3363 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/IUserGroupService.cs @@ -23,7 +23,7 @@ public interface IUserGroupService Task> GetRoleUserGroupDetailForUserAsync(int userId); /// - /// The GetRoleUserGroupDetailAsync. + /// The UserHasCatalogueContributionPermission. /// /// The . Task UserHasCatalogueContributionPermission(); diff --git a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs index be77f6531..826aa07a0 100644 --- a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs +++ b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs @@ -45,11 +45,8 @@ public UserGroupService( /// public async Task> GetRoleUserGroupDetailAsync() { - var cacheKey = $"{this.contextAccessor.HttpContext.User.Identity.GetCurrentUserId()}:AllRolesWithPermissions"; - cacheKey = null; - ////return await this.cacheService.GetOrFetchAsync(cacheKey, () => this.FetchRoleUserGroupDetailAsync()); - - return await this.FetchRoleUserGroupDetailAsync(); + var cacheKey = $"{this.contextAccessor.HttpContext.User.Identity.GetCurrentUserId()}:AllRolesWithPermissions"; + return await this.cacheService.GetOrFetchAsync(cacheKey, () => this.FetchRoleUserGroupDetailAsync()); } /// From 4e1d0657aa04f1176ae77c46f6c3306b32d2f3ae Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Tue, 17 Jun 2025 12:02:01 +0100 Subject: [PATCH 6/6] TD-5663: Post log in dashboard - remove banner promoting contribute a resource --- LearningHub.Nhs.WebUI/Controllers/HomeController.cs | 10 ++++++++-- LearningHub.Nhs.WebUI/Services/UserGroupService.cs | 5 +++-- LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml | 10 +++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs index 7f40afe15..18e3b82fe 100644 --- a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs @@ -40,6 +40,7 @@ public class HomeController : BaseController private readonly IDashboardService dashboardService; private readonly IContentService contentService; private readonly IFeatureManager featureManager; + private readonly IUserGroupService userGroupService; private readonly Microsoft.Extensions.Configuration.IConfiguration configuration; /// @@ -55,6 +56,7 @@ public class HomeController : BaseController /// Dashboard service. /// Content service. /// featureManager. + /// userGroupService. /// config. public HomeController( IHttpClientFactory httpClientFactory, @@ -67,6 +69,7 @@ public HomeController( IDashboardService dashboardService, IContentService contentService, IFeatureManager featureManager, + IUserGroupService userGroupService, Microsoft.Extensions.Configuration.IConfiguration configuration) : base(hostingEnvironment, httpClientFactory, logger, settings.Value) { @@ -76,6 +79,7 @@ public HomeController( this.dashboardService = dashboardService; this.contentService = contentService; this.featureManager = featureManager; + this.userGroupService = userGroupService; this.configuration = configuration; } @@ -212,6 +216,7 @@ public async Task Index(string myLearningDashboard = "my-in-progr var learningTask = this.dashboardService.GetMyAccessLearningsAsync(myLearningDashboard, 1); var resourcesTask = this.dashboardService.GetResourcesAsync(resourceDashboard, 1); var cataloguesTask = this.dashboardService.GetCataloguesAsync(catalogueDashboard, 1); + var userGroupsTask = this.userGroupService.UserHasCatalogueContributionPermission(); var enrolledCoursesTask = Task.FromResult(new List()); var enableMoodle = Task.Run(() => this.featureManager.IsEnabledAsync(FeatureFlags.EnableMoodle)).Result; @@ -222,7 +227,7 @@ public async Task Index(string myLearningDashboard = "my-in-progr enrolledCoursesTask = this.dashboardService.GetEnrolledCoursesFromMoodleAsync(this.CurrentMoodleUserId, 1); } - await Task.WhenAll(learningTask, resourcesTask, cataloguesTask); + await Task.WhenAll(learningTask, resourcesTask, cataloguesTask, userGroupsTask); var model = new DashboardViewModel() { @@ -231,7 +236,8 @@ public async Task Index(string myLearningDashboard = "my-in-progr Catalogues = await cataloguesTask, EnrolledCourses = await enrolledCoursesTask, }; - + var userHasContributePermission = await userGroupsTask; + this.ViewBag.userHasContributePermission = userHasContributePermission; if (!string.IsNullOrEmpty(this.Request.Query["preview"]) && Convert.ToBoolean(this.Request.Query["preview"])) { return this.View("LandingPage", await this.GetLandingPageContent(Convert.ToBoolean(this.Request.Query["preview"]))); diff --git a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs index 826aa07a0..6a4f62966 100644 --- a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs +++ b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using LearningHub.Nhs.Caching; + using LearningHub.Nhs.Models.Enums; using LearningHub.Nhs.Models.Extensions; using LearningHub.Nhs.Models.User; using LearningHub.Nhs.WebUI.Interfaces; @@ -45,7 +46,7 @@ public UserGroupService( /// public async Task> GetRoleUserGroupDetailAsync() { - var cacheKey = $"{this.contextAccessor.HttpContext.User.Identity.GetCurrentUserId()}:AllRolesWithPermissions"; + var cacheKey = $"{this.contextAccessor.HttpContext.User.Identity.GetCurrentUserId()}:AllRolesWithPermissions"; return await this.cacheService.GetOrFetchAsync(cacheKey, () => this.FetchRoleUserGroupDetailAsync()); } @@ -60,7 +61,7 @@ public async Task> GetRoleUserGroupDetailForUserAsy public async Task UserHasCatalogueContributionPermission() { var userRoleGroups = await this.GetRoleUserGroupDetailAsync(); - if (userRoleGroups != null && userRoleGroups.Any(r => r.RoleName == "Local Admin" || r.RoleName == "Editor")) + if (userRoleGroups != null && userRoleGroups.Any(r => r.RoleEnum == RoleEnum.LocalAdmin || r.RoleEnum == RoleEnum.Editor)) { return true; } diff --git a/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml b/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml index 4a7b55c08..e8481a4c7 100644 --- a/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml @@ -5,7 +5,15 @@ @{ ViewData["Title"] = "Learning Hub - Home"; - var isReadOnly = User.IsInRole("ReadOnly") || User.IsInRole("BasicUser"); + var isReadOnly = false; + if (User.IsInRole("ReadOnly") || User.IsInRole("BasicUser")) + { + isReadOnly = true; + } + else if (User.IsInRole("BlueUser") && !this.ViewBag.userHasContributePermission) + { + isReadOnly = true; + } } @section styles {