diff --git a/web/Areas/RAPS/Controllers/RAPSController.cs b/web/Areas/RAPS/Controllers/RAPSController.cs index 8a64334..c572b42 100644 --- a/web/Areas/RAPS/Controllers/RAPSController.cs +++ b/web/Areas/RAPS/Controllers/RAPSController.cs @@ -8,6 +8,7 @@ using Viper.Classes; using System.Runtime.Versioning; using Microsoft.AspNetCore.Mvc.Filters; +using System.Data; namespace Viper.Areas.RAPS.Controllers { @@ -119,7 +120,11 @@ public async Task Nav(int? roleId, int? permissionId, string? memberId, } nav.Add(new NavMenuItem() { MenuItemText = "Roles", IsHeader = true }); nav.Add(new NavMenuItem() { MenuItemText = "Role List", MenuItemURL = "Rolelist" }); - if(_securityService.IsAllowedTo("ViewRoles", instance)) + if (_securityService.IsAllowedTo("EditRoleMembership", instance)) + { + nav.Add(new NavMenuItem() { MenuItemText = "Role Comparison", MenuItemURL = "RolePermissionsComparison" }); + } + if (_securityService.IsAllowedTo("ViewRoles", instance)) { nav.Add(new NavMenuItem() { MenuItemText = "Role Templates", MenuItemURL = "RoleTemplateList" }); } @@ -353,6 +358,23 @@ public async Task RolePermissions(int roleId) return await Task.Run(() => View("~/Areas/RAPS/Views/Roles/Permissions.cshtml")); } + /// + /// Compare permissions for two roles + /// + /// + [Route("/[area]/{Instance}/[action]")] + public async Task RolePermissionsComparison(string instance) + { + if (_securityService.IsAllowedTo("EditRoleMembership", instance)) + { + return await Task.Run(() => View("~/Areas/RAPS/Views/Roles/PermissionComparison.cshtml")); + } + else + { + return await Task.Run(() => View("~/Views/Home/403.cshtml")); + } + } + /// /// List members of a permission /// diff --git a/web/Areas/RAPS/Controllers/RolePermissionsController.cs b/web/Areas/RAPS/Controllers/RolePermissionsController.cs index d62fb94..2f2fad6 100644 --- a/web/Areas/RAPS/Controllers/RolePermissionsController.cs +++ b/web/Areas/RAPS/Controllers/RolePermissionsController.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Microsoft.Identity.Client; using System.Data; using Viper.Areas.RAPS.Models; using Viper.Areas.RAPS.Services; @@ -99,6 +100,41 @@ public async Task>> GetTblRolePermissions(s return tblRolePermissions; } + + [HttpGet("Roles/{role1Id}/{role2Id}/PermissionComparison")] + [Permission(Allow = "RAPS.Admin,RAPS.EditRoleMembership")] + public async Task> CompareRolePermissions(string instance, int role1Id, int role2Id) + { + TblRole? role1 = _securityService.GetRoleInInstance(instance, role1Id); + TblRole? role2 = _securityService.GetRoleInInstance(instance, role2Id); + if(role1 == null || role2 == null) + { + return NotFound(); + } + + if (!_securityService.IsAllowedTo("EditRoleMembership", instance) || + !_securityService.IsAllowedTo("ViewRolePermissions", instance, role1) || + !_securityService.IsAllowedTo("ViewRolePermissions", instance, role2)) + { + return Forbid(); + } + + List role1Permissions = await _context.TblRolePermissions + .Include(rp => rp.Permission) + .Where(rp => rp.RoleId == role1Id) + .OrderBy(rp => rp.Permission.Permission) + .ToListAsync(); + List role2Permissions = await _context.TblRolePermissions + .Include(rp => rp.Permission) + .Where(rp => rp.RoleId == role2Id) + .OrderBy(rp => rp.Permission.Permission) + .ToListAsync(); + + + RolePermissionComparison result = new(role1Permissions, role2Permissions); + return result; + } + // POST Roles/5/Permissions // POST Permissions/5/Roles [HttpPost("Roles/{roleId}/Permissions")] diff --git a/web/Areas/RAPS/Models/RolePermissionComparison.cs b/web/Areas/RAPS/Models/RolePermissionComparison.cs new file mode 100644 index 0000000..c34998d --- /dev/null +++ b/web/Areas/RAPS/Models/RolePermissionComparison.cs @@ -0,0 +1,45 @@ +using Viper.Models.RAPS; + +namespace Viper.Areas.RAPS.Models +{ + public class RolePermissionComparison + { + public List Role1Permissions { get; set; } = new List(); + public List Role2Permissions { get; set; } = new List(); + + public RolePermissionComparison() + { + + } + + public RolePermissionComparison(List role1Permissions, List role2Permissions) + { + foreach(var p in role1Permissions) + { + Role1Permissions.Add(new RolePermission() + { + PermissionId = p.PermissionId, + Name = p.Permission.Permission, + IsInOtherList = role2Permissions.FindIndex(p2 => p2.PermissionId == p.PermissionId) >= 0 + }); + } + + foreach (var p in role2Permissions) + { + Role2Permissions.Add(new RolePermission() + { + PermissionId = p.PermissionId, + Name = p.Permission.Permission, + IsInOtherList = role1Permissions.FindIndex(p1 => p1.PermissionId == p.PermissionId) >= 0 + }); + } + } + + public class RolePermission + { + public int PermissionId { get; set; } + public string Name { get; set; } = string.Empty; + public bool IsInOtherList { get; set; } + } + } +} diff --git a/web/Areas/RAPS/Views/Members/List.cshtml b/web/Areas/RAPS/Views/Members/List.cshtml index 83a5ec8..ac3188b 100644 --- a/web/Areas/RAPS/Views/Members/List.cshtml +++ b/web/Areas/RAPS/Views/Members/List.cshtml @@ -1,16 +1,23 @@ 

Search for a user

- - +
+ + + + +
+ @section Scripts { @@ -55,13 +67,14 @@ data() { return { userSearch: "", + includeInactive: false, members: new quasarTable({ keys: ["memberId"], urlBase: "Members", columns: [ { name: "links", label: "", field: "", align: "left", style: "width:100px;" }, { name: "member", label: "Member", field: "", align: "left", sortable: true }, - { name: "active", label: "Active", field: "current", align: "left", sortable: true, format: v => (v == 1 ? "Y" : "N") }, + { name: "active", label: "Active", field: "current", align: "left", sortable: true }, { name: "countRoles", label: "Count Roles", field: "countRoles", align: "left", sortable: true }, { name: "countPermissions", label: "Count Permissions", field: "countPermissions", align: "left", sortable: true } ], @@ -71,7 +84,7 @@ }, methods: { findUsers: async function () { - this.members.urlBase = "Members?search=" + this.userSearch + this.members.urlBase = "Members?search=" + this.userSearch + "&active=" + (this.includeInactive ? "all" : "active") if (this.userSearch.length >= 3) { this.members.load(this) } @@ -79,6 +92,10 @@ }, mounted() { this.members.loading = false + var includeInactive = getItemFromStorage("RAPS_userSearch_includeInactive") + if(includeInactive) { + this.includeInactive = includeInactive + } var userSearch = getItemFromStorage("RAPS_userSearch_userSearch") if(userSearch) { this.userSearch = userSearch @@ -92,6 +109,12 @@ this.findUsers() }, deep: true + }, + includeInactive: { + handler(v) { + putItemInStorage("RAPS_userSearch_includeInactive", v) + this.findUsers() + } } } }) diff --git a/web/Areas/RAPS/Views/Members/Roles.cshtml b/web/Areas/RAPS/Views/Members/Roles.cshtml index cafabd7..17ac59e 100644 --- a/web/Areas/RAPS/Views/Members/Roles.cshtml +++ b/web/Areas/RAPS/Views/Members/Roles.cshtml @@ -42,7 +42,7 @@
-
+
@@ -223,7 +223,7 @@ addRolesThenPushToVMACS: async function() { await this.addRoles() this.loadTables() - this.pushToVMACS(true) + this.pushToVMACS(false) }, loadTables: async function () { await this.memberRolesTable.load(this) @@ -234,6 +234,7 @@ this.member = await viperFetch(this, "members/" + this.memberId) }, pushToVMACS: async function (skipToggleCheck) { + console.log(skipToggleCheck, this.updateVMACS) if (skipToggleCheck || this.updateVMACS) { Quasar.Loading.show({ message: "Updating VMACS" }) await viperFetch(this, "Members/" + this.memberId + "/Roles/VMACSExport", { method: "POST" }) diff --git a/web/Areas/RAPS/Views/Roles/Members.cshtml b/web/Areas/RAPS/Views/Roles/Members.cshtml index cc3bbbd..b17b1dc 100644 --- a/web/Areas/RAPS/Views/Roles/Members.cshtml +++ b/web/Areas/RAPS/Views/Roles/Members.cshtml @@ -193,6 +193,7 @@ this.membersTable.load() await this.loadRole() this.showVMACSPush = this.role.instance.indexOf("VMACS") == 0 + console.log(this.role, this.showVMACSPush) } }) diff --git a/web/Areas/RAPS/Views/Roles/PermissionComparison.cshtml b/web/Areas/RAPS/Views/Roles/PermissionComparison.cshtml new file mode 100644 index 0000000..da8e8db --- /dev/null +++ b/web/Areas/RAPS/Views/Roles/PermissionComparison.cshtml @@ -0,0 +1,105 @@ +

Compare permissions for two roles

+ +
+ + + + + +
+
+ +
+ + +
{{role1.label}}
+
+ + + + + + + + + + + + + +
In BothPermission
+ + {{permission.name}}
+
+ + +
{{role2.label}}
+
+ + + + + + + + + + + + + +
In BothPermission
+ + {{permission.name}}
+
+
+ + +@section Scripts { + +} \ No newline at end of file