Spaces:
Sleeping
Sleeping
User commited on
Commit ·
8889023
1
Parent(s): c42fd03
add: new role and menu apis for role page
Browse files- TaskTrackingSystem.Shared/Models/Role/AssignPermissionsDto.cs +0 -11
- TaskTrackingSystem.WebApi/Features/Menu/MenuController.cs +8 -5
- TaskTrackingSystem.WebApi/Features/Menu/MenuService.cs +6 -5
- TaskTrackingSystem.WebApi/Features/Role/RoleController.cs +2 -0
- TaskTrackingSystem.WebApp/Components/Pages/Roles.razor +8 -7
TaskTrackingSystem.Shared/Models/Role/AssignPermissionsDto.cs
DELETED
|
@@ -1,11 +0,0 @@
|
|
| 1 |
-
using System.Collections.Generic;
|
| 2 |
-
using System.ComponentModel.DataAnnotations;
|
| 3 |
-
|
| 4 |
-
namespace TaskTrackingSystem.Shared.Models.Role
|
| 5 |
-
{
|
| 6 |
-
public class AssignPermissionsDto
|
| 7 |
-
{
|
| 8 |
-
[Required]
|
| 9 |
-
public List<long> PermissionIds { get; set; } = new List<long>();
|
| 10 |
-
}
|
| 11 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TaskTrackingSystem.WebApi/Features/Menu/MenuController.cs
CHANGED
|
@@ -21,13 +21,14 @@ namespace TaskTrackingSystem.WebApi.Features.Menu
|
|
| 21 |
}
|
| 22 |
|
| 23 |
[HttpGet]
|
| 24 |
-
|
|
|
|
| 25 |
{
|
| 26 |
var roleId = User.GetRoleId();
|
| 27 |
if (roleId > 0)
|
| 28 |
{
|
| 29 |
-
var
|
| 30 |
-
return Ok(
|
| 31 |
}
|
| 32 |
|
| 33 |
var roleName = User.GetRoleName();
|
|
@@ -36,12 +37,13 @@ namespace TaskTrackingSystem.WebApi.Features.Menu
|
|
| 36 |
return Forbid();
|
| 37 |
}
|
| 38 |
|
| 39 |
-
var
|
| 40 |
-
return Ok(
|
| 41 |
}
|
| 42 |
|
| 43 |
[Authorize(Roles = "Admin")]
|
| 44 |
[HttpGet("all")]
|
|
|
|
| 45 |
public async Task<ActionResult<IEnumerable<AccessMenuDto>>> GetAllAccessItems()
|
| 46 |
{
|
| 47 |
var menus = await _menuService.GetAllAccessItemsAsync();
|
|
@@ -64,3 +66,4 @@ namespace TaskTrackingSystem.WebApi.Features.Menu
|
|
| 64 |
}
|
| 65 |
|
| 66 |
|
|
|
|
|
|
| 21 |
}
|
| 22 |
|
| 23 |
[HttpGet]
|
| 24 |
+
[HttpGet("tree")]
|
| 25 |
+
public async Task<ActionResult<IEnumerable<MenuDto>>> GetMenuTree()
|
| 26 |
{
|
| 27 |
var roleId = User.GetRoleId();
|
| 28 |
if (roleId > 0)
|
| 29 |
{
|
| 30 |
+
var menuTree = await _menuService.GetMenuTreeByRoleIdAsync(roleId);
|
| 31 |
+
return Ok(menuTree);
|
| 32 |
}
|
| 33 |
|
| 34 |
var roleName = User.GetRoleName();
|
|
|
|
| 37 |
return Forbid();
|
| 38 |
}
|
| 39 |
|
| 40 |
+
var menuTreeByName = await _menuService.GetMenuTreeByRoleNameAsync(roleName);
|
| 41 |
+
return Ok(menuTreeByName);
|
| 42 |
}
|
| 43 |
|
| 44 |
[Authorize(Roles = "Admin")]
|
| 45 |
[HttpGet("all")]
|
| 46 |
+
[HttpGet("access-items")]
|
| 47 |
public async Task<ActionResult<IEnumerable<AccessMenuDto>>> GetAllAccessItems()
|
| 48 |
{
|
| 49 |
var menus = await _menuService.GetAllAccessItemsAsync();
|
|
|
|
| 66 |
}
|
| 67 |
|
| 68 |
|
| 69 |
+
|
TaskTrackingSystem.WebApi/Features/Menu/MenuService.cs
CHANGED
|
@@ -18,7 +18,7 @@ namespace TaskTrackingSystem.WebApi.Features.Menu
|
|
| 18 |
_db = db;
|
| 19 |
}
|
| 20 |
|
| 21 |
-
public async Task<List<MenuDto>>
|
| 22 |
{
|
| 23 |
var role = await _db.Roles.FirstOrDefaultAsync(r => r.Id == roleId && r.IsDeleted != true);
|
| 24 |
if (role == null)
|
|
@@ -26,10 +26,10 @@ namespace TaskTrackingSystem.WebApi.Features.Menu
|
|
| 26 |
return new List<MenuDto>();
|
| 27 |
}
|
| 28 |
|
| 29 |
-
return await
|
| 30 |
}
|
| 31 |
|
| 32 |
-
public async Task<List<MenuDto>>
|
| 33 |
{
|
| 34 |
if (string.IsNullOrWhiteSpace(roleName))
|
| 35 |
{
|
|
@@ -42,10 +42,10 @@ namespace TaskTrackingSystem.WebApi.Features.Menu
|
|
| 42 |
return new List<MenuDto>();
|
| 43 |
}
|
| 44 |
|
| 45 |
-
return await
|
| 46 |
}
|
| 47 |
|
| 48 |
-
private async Task<List<MenuDto>>
|
| 49 |
{
|
| 50 |
var visibleMenus = await _db.Menus
|
| 51 |
.Where(m => !m.IsDeleted && m.Visible)
|
|
@@ -278,3 +278,4 @@ namespace TaskTrackingSystem.WebApi.Features.Menu
|
|
| 278 |
}
|
| 279 |
|
| 280 |
|
|
|
|
|
|
| 18 |
_db = db;
|
| 19 |
}
|
| 20 |
|
| 21 |
+
public async Task<List<MenuDto>> GetMenuTreeByRoleIdAsync(long roleId)
|
| 22 |
{
|
| 23 |
var role = await _db.Roles.FirstOrDefaultAsync(r => r.Id == roleId && r.IsDeleted != true);
|
| 24 |
if (role == null)
|
|
|
|
| 26 |
return new List<MenuDto>();
|
| 27 |
}
|
| 28 |
|
| 29 |
+
return await GetMenuTreeForRoleAsync(role.Id);
|
| 30 |
}
|
| 31 |
|
| 32 |
+
public async Task<List<MenuDto>> GetMenuTreeByRoleNameAsync(string roleName)
|
| 33 |
{
|
| 34 |
if (string.IsNullOrWhiteSpace(roleName))
|
| 35 |
{
|
|
|
|
| 42 |
return new List<MenuDto>();
|
| 43 |
}
|
| 44 |
|
| 45 |
+
return await GetMenuTreeForRoleAsync(role.Id);
|
| 46 |
}
|
| 47 |
|
| 48 |
+
private async Task<List<MenuDto>> GetMenuTreeForRoleAsync(long roleId)
|
| 49 |
{
|
| 50 |
var visibleMenus = await _db.Menus
|
| 51 |
.Where(m => !m.IsDeleted && m.Visible)
|
|
|
|
| 278 |
}
|
| 279 |
|
| 280 |
|
| 281 |
+
|
TaskTrackingSystem.WebApi/Features/Role/RoleController.cs
CHANGED
|
@@ -60,6 +60,7 @@ namespace TaskTrackingSystem.WebApi.Features.Role
|
|
| 60 |
|
| 61 |
|
| 62 |
[HttpGet("{id}/menus")]
|
|
|
|
| 63 |
public async Task<ActionResult<Result<List<string>>>> GetAssignedMenus(long id)
|
| 64 |
{
|
| 65 |
var result = await _roleService.GetAssignedMenusByRoleIdAsync(id);
|
|
@@ -71,6 +72,7 @@ namespace TaskTrackingSystem.WebApi.Features.Role
|
|
| 71 |
}
|
| 72 |
|
| 73 |
[HttpPost("{id}/menus")]
|
|
|
|
| 74 |
public async Task<IActionResult> AssignAccess(long id, [FromBody] AssignAccessDto dto)
|
| 75 |
{
|
| 76 |
var result = await _roleService.AssignAccessToRoleAsync(id, dto);
|
|
|
|
| 60 |
|
| 61 |
|
| 62 |
[HttpGet("{id}/menus")]
|
| 63 |
+
[HttpGet("{id}/access")]
|
| 64 |
public async Task<ActionResult<Result<List<string>>>> GetAssignedMenus(long id)
|
| 65 |
{
|
| 66 |
var result = await _roleService.GetAssignedMenusByRoleIdAsync(id);
|
|
|
|
| 72 |
}
|
| 73 |
|
| 74 |
[HttpPost("{id}/menus")]
|
| 75 |
+
[HttpPost("{id}/access")]
|
| 76 |
public async Task<IActionResult> AssignAccess(long id, [FromBody] AssignAccessDto dto)
|
| 77 |
{
|
| 78 |
var result = await _roleService.AssignAccessToRoleAsync(id, dto);
|
TaskTrackingSystem.WebApp/Components/Pages/Roles.razor
CHANGED
|
@@ -17,7 +17,7 @@
|
|
| 17 |
<div class="flex items-center justify-between">
|
| 18 |
<div>
|
| 19 |
<h2 class="text-3xl font-bold tracking-tight text-slate-900">Roles & Access</h2>
|
| 20 |
-
<p class="text-slate-500 mt-1">Manage roles, assign
|
| 21 |
</div>
|
| 22 |
<button @onclick="OpenCreateModal" class="inline-flex items-center rounded-lg bg-violet-600 px-4 py-2.5 text-sm font-medium text-white hover:bg-violet-700 transition-colors shadow-sm">
|
| 23 |
<i data-lucide="plus" class="h-4 w-4 mr-2"></i>
|
|
@@ -342,7 +342,7 @@
|
|
| 342 |
</div>
|
| 343 |
<div>
|
| 344 |
<h3 class="text-base font-semibold text-slate-900">Role Access — <span class="text-violet-700">@selectedRoleName</span></h3>
|
| 345 |
-
<p class="text-xs text-slate-500">Configure
|
| 346 |
</div>
|
| 347 |
</div>
|
| 348 |
<button @onclick="CloseAccessModal" class="rounded-lg p-1.5 text-slate-400 hover:bg-white hover:text-slate-600 transition-all">
|
|
@@ -654,7 +654,7 @@
|
|
| 654 |
try
|
| 655 |
{
|
| 656 |
var client = ApiClient.CreateClient();
|
| 657 |
-
formAccessItems = await client.GetFromJsonAsync<List<AccessMenuDto>>("Menu/
|
| 658 |
}
|
| 659 |
catch (Exception ex)
|
| 660 |
{
|
|
@@ -898,7 +898,7 @@
|
|
| 898 |
}
|
| 899 |
}
|
| 900 |
|
| 901 |
-
// =====
|
| 902 |
private async Task OpenAccessModal(RoleDto role)
|
| 903 |
{
|
| 904 |
selectedRoleId = role.Id;
|
|
@@ -913,10 +913,10 @@
|
|
| 913 |
try
|
| 914 |
{
|
| 915 |
// Load all available access items with their nested permissions
|
| 916 |
-
accessItems = await client.GetFromJsonAsync<List<AccessMenuDto>>("Menu/
|
| 917 |
|
| 918 |
// Load currently assigned access items for this role
|
| 919 |
-
var assignedResult = await client.GetFromJsonAsync<Result<List<string>>>($"Role/{role.Id}/
|
| 920 |
selectedAccessCodes = new HashSet<string>(assignedResult?.Value ?? new(), StringComparer.OrdinalIgnoreCase);
|
| 921 |
}
|
| 922 |
catch (Exception ex)
|
|
@@ -970,7 +970,7 @@
|
|
| 970 |
try
|
| 971 |
{
|
| 972 |
var dto = new AssignAccessDto { AccessCodes = selectedAccessCodes.ToList() };
|
| 973 |
-
var response = await client.PostAsJsonAsync($"Role/{selectedRoleId}/
|
| 974 |
if (response.IsSuccessStatusCode)
|
| 975 |
{
|
| 976 |
accessSaveSuccess = $"Access for '{selectedRoleName}' saved successfully!";
|
|
@@ -993,3 +993,4 @@
|
|
| 993 |
}
|
| 994 |
|
| 995 |
|
|
|
|
|
|
| 17 |
<div class="flex items-center justify-between">
|
| 18 |
<div>
|
| 19 |
<h2 class="text-3xl font-bold tracking-tight text-slate-900">Roles & Access</h2>
|
| 20 |
+
<p class="text-slate-500 mt-1">Manage roles, assign access and permissions, and control visibility.</p>
|
| 21 |
</div>
|
| 22 |
<button @onclick="OpenCreateModal" class="inline-flex items-center rounded-lg bg-violet-600 px-4 py-2.5 text-sm font-medium text-white hover:bg-violet-700 transition-colors shadow-sm">
|
| 23 |
<i data-lucide="plus" class="h-4 w-4 mr-2"></i>
|
|
|
|
| 342 |
</div>
|
| 343 |
<div>
|
| 344 |
<h3 class="text-base font-semibold text-slate-900">Role Access — <span class="text-violet-700">@selectedRoleName</span></h3>
|
| 345 |
+
<p class="text-xs text-slate-500">Configure access and permissions</p>
|
| 346 |
</div>
|
| 347 |
</div>
|
| 348 |
<button @onclick="CloseAccessModal" class="rounded-lg p-1.5 text-slate-400 hover:bg-white hover:text-slate-600 transition-all">
|
|
|
|
| 654 |
try
|
| 655 |
{
|
| 656 |
var client = ApiClient.CreateClient();
|
| 657 |
+
formAccessItems = await client.GetFromJsonAsync<List<AccessMenuDto>>("Menu/access-items", Serialization.CaseInsensitive) ?? new();
|
| 658 |
}
|
| 659 |
catch (Exception ex)
|
| 660 |
{
|
|
|
|
| 898 |
}
|
| 899 |
}
|
| 900 |
|
| 901 |
+
// ===== Access Management =====
|
| 902 |
private async Task OpenAccessModal(RoleDto role)
|
| 903 |
{
|
| 904 |
selectedRoleId = role.Id;
|
|
|
|
| 913 |
try
|
| 914 |
{
|
| 915 |
// Load all available access items with their nested permissions
|
| 916 |
+
accessItems = await client.GetFromJsonAsync<List<AccessMenuDto>>("Menu/access-items", Serialization.CaseInsensitive) ?? new();
|
| 917 |
|
| 918 |
// Load currently assigned access items for this role
|
| 919 |
+
var assignedResult = await client.GetFromJsonAsync<Result<List<string>>>($"Role/{role.Id}/access", Serialization.CaseInsensitive);
|
| 920 |
selectedAccessCodes = new HashSet<string>(assignedResult?.Value ?? new(), StringComparer.OrdinalIgnoreCase);
|
| 921 |
}
|
| 922 |
catch (Exception ex)
|
|
|
|
| 970 |
try
|
| 971 |
{
|
| 972 |
var dto = new AssignAccessDto { AccessCodes = selectedAccessCodes.ToList() };
|
| 973 |
+
var response = await client.PostAsJsonAsync($"Role/{selectedRoleId}/access", dto);
|
| 974 |
if (response.IsSuccessStatusCode)
|
| 975 |
{
|
| 976 |
accessSaveSuccess = $"Access for '{selectedRoleName}' saved successfully!";
|
|
|
|
| 993 |
}
|
| 994 |
|
| 995 |
|
| 996 |
+
|