Skip to content

Commit e2bb943

Browse files
committed
API Fixes for Role Permissions
1 parent e3bf5be commit e2bb943

File tree

9 files changed

+87
-42
lines changed

9 files changed

+87
-42
lines changed

backend/src/Contact.Api/Controllers/RolePermissionMappingController.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
using Contact.Api.Core.Attributes;
22
using Contact.Application.Interfaces;
33
using Contact.Application.UseCases.RolePermissions;
4-
using Microsoft.AspNetCore.Authorization;
54
using Microsoft.AspNetCore.Mvc;
6-
using System.Security.Claims;
75

86
namespace Contact.Api.Controllers;
9-
10-
[Route("api/role-permission-mapping")]
7+
[Route("api/[controller]")]
118
[ApiController]
12-
[Authorize(Roles = "Administrator")]
139
public class RolePermissionMappingController : ControllerBase
1410
{
1511
private readonly IRolePermissionService _rolePermissionService;
@@ -82,10 +78,10 @@ public async Task<IActionResult> SaveRolePermissionMapping([FromBody] RolePermis
8278

8379
try
8480
{
85-
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
81+
var userId = User.FindFirst("Id")?.Value;
8682
if (userId == null)
8783
{
88-
return Unauthorized("User ID not found in token");
84+
return Unauthorized(new { message = "User ID not found in token" });
8985
}
9086

9187
await _rolePermissionService.SaveRolePermissionMappingAsync(request, Guid.Parse(userId));

backend/src/Contact.Application/Mappings/RolePermissionMappingProfile.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
using AutoMapper;
21
using Contact.Application.UseCases.RolePermissions;
32
using Contact.Domain.Entities;
3+
using Contact.Domain.Mappings;
44
using Microsoft.AspNetCore.Http;
55
using Microsoft.Extensions.DependencyInjection;
66

@@ -12,10 +12,15 @@ public RolePermissionMappingProfile(IHttpContextAccessor httpContextAccessor)
1212
: base(httpContextAccessor)
1313
{
1414
CreateMap<RolePermission, RolePermissionResponse>();
15+
CreateMap<RolePermissionMappingResponse, PermissionsByRoleMappings>();
1516
CreateMap<CreateRolePermission, RolePermission>()
1617
.AfterMap((src, dest) => SetAuditFields(src, dest));
1718
CreateMap<UpdateRolePermission, RolePermission>()
1819
.AfterMap((src, dest) => SetAuditFields(src, dest, false));
20+
// Configure the mapping between PermissionsByRoleMappings and RolePermissionMappingResponse
21+
CreateMap<PermissionsByRoleMappings, RolePermissionMappingResponse>();
22+
CreateMap<PageOperationMappings, PageOperationResponse>();
23+
CreateMap<OperationMappings, OperationResponse>();
1924
}
2025

2126
public RolePermissionMappingProfile()
@@ -31,4 +36,5 @@ private static IHttpContextAccessor ResolveHttpContextAccessor()
3136

3237
return serviceProvider.GetRequiredService<IHttpContextAccessor>();
3338
}
34-
}
39+
}
40+

backend/src/Contact.Application/Services/RolePermissionService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ public async Task<RolePermissionMappingResponse> GetRolePermissionMappingByRoleI
8585
// Get the role
8686
using var transaction = _unitOfWork.BeginTransaction();
8787
var result = await _rolePermissionRepository.GetRolePermissionMappingByRoleIdAsync(roleId, transaction);
88-
return null;
88+
await _unitOfWork.CommitAsync();
89+
return _mapper.Map<RolePermissionMappingResponse>(result);
8990
}
9091

9192
public async Task SaveRolePermissionMappingAsync(RolePermissionMappingRequest request, Guid userId)

backend/src/Contact.Application/UseCases/RolePermissions/RolePermissionMappingResponse.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ public class RolePermissionMappingResponse
44
{
55
public Guid RoleId { get; set; }
66
public string RoleName { get; set; }
7-
public List<PageOperationResponse> Pages { get; set; } = new();
7+
public List<PageOperationResponse> Pages { get; set; }
88
}
99

1010
public class PageOperationResponse
1111
{
1212
public Guid PageId { get; set; }
1313
public string PageName { get; set; }
14-
public List<OperationResponse> Operations { get; set; } = new();
14+
public List<OperationResponse> Operations { get; set; }
1515
}
1616

1717
public class OperationResponse

backend/src/Contact.Domain/Entities/RolePermissionMapping.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
public class RolePermissionMapping
44
{
5+
public Guid Id { get; set; }
56
public Guid RoleId { get; set; }
67
public string RoleName { get; set; }
78
public Guid PageId { get; set; }
89
public string PageName { get; set; }
10+
public string PageUrl { get; set; }
911
public Guid OperationId { get; set; }
1012
public string OperationName { get; set; }
1113
public Guid PermissionId { get; set; }

backend/src/Contact.Domain/Interfaces/IUserRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public interface IUserRepository : IGenericRepository<User>
77
{
88
Task<User> AddUser(User item);
99
Task<User> FindByUserName(string userName);
10-
Task<List<Role>> FindRolesById(Guid id);
10+
Task<IEnumerable<Role>> FindRolesById(Guid id);
1111
Task<IEnumerable<User>> CheckUniqueUsers(string email, string username);
1212
Task<User> UpdatePassword(User item, IDbTransaction? transaction = null);
1313
Task<IEnumerable<UserRole>> GetUserRoles(Guid userId, IDbTransaction? transaction = null);

backend/src/Contact.Domain/Mappings/PermissionsByRoleMapping.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ public class PermissionsByRoleMappings
44
{
55
public Guid RoleId { get; set; }
66
public string RoleName { get; set; }
7-
public List<PageOperationMappings> Pages { get; set; } = new();
7+
public List<PageOperationMappings> Pages { get; set; }
88
}
99

1010
public class PageOperationMappings
1111
{
1212
public Guid PageId { get; set; }
1313
public string PageName { get; set; }
14-
public List<OperationMappings> Operations { get; set; } = new();
14+
public List<OperationMappings> Operations { get; set; }
1515
}
1616

1717
public class OperationMappings

backend/src/Contact.Infrastructure/Persistence/Repositories/RolePermissionRepository.cs

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,60 @@ public RolePermissionRepository(IDapperHelper dapperHelper) : base(dapperHelper,
1515

1616
public async Task<IEnumerable<RolePermissionMapping>> GetRolePermissionMappingsAsync()
1717
{
18-
var dbPara = new DynamicParameters();
1918
var sql = @"
20-
SELECT
19+
WITH page_operations AS (
20+
-- All possible page-operation combinations
21+
SELECT
22+
p.""Id"" as ""PageId"",
23+
p.""Name"" as ""PageName"",
24+
p.""Url"" as ""PageUrl"",
25+
o.""Id"" as ""OperationId"",
26+
o.""Name"" as ""OperationName"",
27+
perm.""Id"" as ""PermissionId""
28+
FROM ""Pages"" p
29+
CROSS JOIN ""Operations"" o
30+
LEFT JOIN ""Permissions"" perm ON p.""Id"" = perm.""PageId"" AND o.""Id"" = perm.""OperationId""
31+
-- Removed the WHERE clause to include ALL combinations
32+
),
33+
role_permissions AS (
34+
-- Get permissions assigned to roles
35+
SELECT
36+
r.""Id"" as ""RoleId"",
37+
r.""Name"" as ""RoleName"",
38+
po.""PageId"",
39+
po.""PageName"",
40+
po.""PageUrl"",
41+
po.""OperationId"",
42+
po.""OperationName"",
43+
po.""PermissionId"",
44+
-- Only mark as selected if both permission exists AND role has it assigned
45+
CASE
46+
WHEN po.""PermissionId"" IS NOT NULL AND rp.""Id"" IS NOT NULL THEN TRUE
47+
ELSE FALSE
48+
END as ""IsSelected"",
49+
rp.""Id""
50+
FROM ""Roles"" r
51+
CROSS JOIN page_operations po
52+
-- Modified LEFT JOIN to handle NULL permission IDs
53+
LEFT JOIN ""RolePermissions"" rp ON po.""PermissionId"" = rp.""PermissionId"" AND rp.""RoleId"" = r.""Id"" AND po.""PermissionId"" IS NOT NULL
54+
)
55+
56+
-- Final result
57+
SELECT
2158
rp.""Id"",
22-
r.""Name"" AS RoleName,
23-
r.""Id"" AS RoleId,
24-
perm.""Id"" AS PermissionId,
25-
p.""Name"" AS PageName,
26-
p.""Url"" as PageUrl,
27-
o.""Name"" AS OperationName
28-
FROM ""RolePermissions"" rp
29-
INNER JOIN ""Roles"" r ON rp.""RoleId"" = r.""Id""
30-
INNER JOIN ""Permissions"" perm ON rp.""PermissionId"" = perm.""Id""
31-
INNER JOIN ""Pages"" p ON perm.""PageId"" = p.""Id""
32-
INNER JOIN ""Operations"" o ON perm.""OperationId"" = o.""Id""
33-
ORDER BY r.""Name"", p.""Name"", o.""Name"";";
34-
return await _dapperHelper.GetAll<RolePermissionMapping>(sql, dbPara);
59+
rp.""RoleId"",
60+
rp.""RoleName"",
61+
rp.""PageId"",
62+
rp.""PageName"",
63+
rp.""PageUrl"",
64+
rp.""OperationId"",
65+
rp.""OperationName"",
66+
rp.""PermissionId"",
67+
rp.""IsSelected""
68+
FROM role_permissions rp
69+
ORDER BY rp.""RoleName"", rp.""PageName"", rp.""OperationName""";
70+
71+
return await _dapperHelper.GetAll<RolePermissionMapping>(sql, new DynamicParameters());
3572
}
3673

3774
public async Task<IEnumerable<RolePermissionMapping>> GetRolePermissionMappingsAsync(Guid userId)
@@ -40,13 +77,15 @@ public async Task<IEnumerable<RolePermissionMapping>> GetRolePermissionMappingsA
4077
dbPara.Add("@UserId", userId);
4178
var sql = @"
4279
SELECT
80+
rp.""Id"" as Id,
4381
r.""Id"" as RoleId,
4482
r.""Name"" AS RoleName,
4583
p.""Id"" as PageId,
4684
p.""Name"" AS PageName,
4785
p.""Url"" as PageUrl,
4886
o.""Id"" as OperationId,
49-
o.""Name"" AS OperationName
87+
o.""Name"" AS OperationName,
88+
perm.""Id"" as PermissionId
5089
FROM ""UserRoles"" ur
5190
INNER JOIN ""Roles"" r ON ur.""RoleId"" = r.""Id""
5291
INNER JOIN ""RolePermissions"" rp ON r.""Id"" = rp.""RoleId""
@@ -106,6 +145,7 @@ page_operations AS (
106145
FROM ""Pages"" p
107146
CROSS JOIN ""Operations"" o
108147
LEFT JOIN ""Permissions"" perm ON p.""Id"" = perm.""PageId"" AND o.""Id"" = perm.""OperationId""
148+
-- Removed the WHERE clause to include ALL combinations
109149
),
110150
role_permissions AS (
111151
-- Get permissions assigned to the role
@@ -114,13 +154,14 @@ role_permissions AS (
114154
po.""PageName"",
115155
po.""OperationId"",
116156
po.""OperationName"",
157+
-- Only mark as selected if both permission exists AND role has it assigned
117158
CASE
118-
WHEN rp.""Id"" IS NOT NULL THEN TRUE
159+
WHEN po.""PermissionId"" IS NOT NULL AND rp.""Id"" IS NOT NULL THEN TRUE
119160
ELSE FALSE
120161
END as ""IsSelected""
121162
FROM page_operations po
122-
LEFT JOIN ""RolePermissions"" rp ON po.""PermissionId"" = rp.""PermissionId"" AND rp.""RoleId"" = @RoleId
123-
WHERE po.""PermissionId"" IS NOT NULL -- Only include valid permission combinations
163+
-- Modified LEFT JOIN to handle NULL permission IDs
164+
LEFT JOIN ""RolePermissions"" rp ON po.""PermissionId"" = rp.""PermissionId"" AND rp.""RoleId"" = @RoleId AND po.""PermissionId"" IS NOT NULL
124165
)
125166
126167
-- Final result combining role info with permissions
@@ -142,10 +183,6 @@ CROSS JOIN role_permissions rp
142183
// Dictionary to hold the pages already added to the response
143184
var pagesDict = new Dictionary<Guid, PageOperationMappings>();
144185

145-
// Role information values
146-
Guid? responseRoleId = null;
147-
string? responseRoleName = null;
148-
149186
// Create the response using Dapper's multi-mapping capabilities
150187
var response = await _dapperHelper.GetAll<dynamic>(query, parameters, CommandType.Text, transaction);
151188

@@ -221,7 +258,8 @@ private async Task<List<PageOperationMappings>> GetAllPagesWithOperations(IDbTra
221258
false as ""IsSelected""
222259
FROM ""Pages"" p
223260
CROSS JOIN ""Operations"" o
224-
INNER JOIN ""Permissions"" perm ON p.""Id"" = perm.""PageId"" AND o.""Id"" = perm.""OperationId""
261+
LEFT JOIN ""Permissions"" perm ON p.""Id"" = perm.""PageId"" AND o.""Id"" = perm.""OperationId""
262+
-- Removed INNER JOIN to include all combinations
225263
ORDER BY p.""Name"", o.""Name""";
226264

227265
var result = await _dapperHelper.GetAll<dynamic>(query, dbTransaction);

backend/src/Contact.Infrastructure/Persistence/Repositories/UserRepository.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,19 @@ public async Task<IEnumerable<User>> CheckUniqueUsers(string email, string usern
5151
dbPara);
5252
}
5353

54-
public async Task<List<Role>> FindRolesById(Guid id)
54+
public async Task<IEnumerable<Role>> FindRolesById(Guid id)
5555
{
5656
var dbPara = new DynamicParameters();
5757
dbPara.Add("UserId", id);
5858
var sql = @"
59-
SELECT r.""*""
59+
SELECT r.""Id"",
60+
r.""Name"",
61+
r.""Description""
6062
FROM ""UserRoles"" ur
6163
INNER JOIN ""Roles"" r ON ur.""RoleId"" = r.""Id""
6264
INNER JOIN ""Users"" u ON u.""Id"" = ur.""UserId""
6365
WHERE ur.""UserId"" = @UserId";
64-
return (List<Role>)await _dapperHelper.GetAll<string>(sql, dbPara);
66+
return await _dapperHelper.GetAll<Role>(sql, dbPara);
6567
}
6668

6769
public async Task<User> FindByUserName(string userName)

0 commit comments

Comments
 (0)