33using Microsoft . EntityFrameworkCore ;
44using Microsoft . Extensions . Options ;
55using Microsoft . IdentityModel . Tokens ;
6+ using SharedLibrary . Cache ;
67using System . IdentityModel . Tokens . Jwt ;
78using System . Security . Claims ;
89using System . Text ;
1112using UserManagementApi . Contracts . Models ;
1213using UserManagementApi . Data ;
1314using UserManagementApi . DTO . Auth ;
15+ using static System . Net . WebRequestMethods ;
1416
1517
1618namespace UserManagementApi . Controllers
@@ -20,14 +22,12 @@ namespace UserManagementApi.Controllers
2022 [ Route ( "api/users" ) ]
2123 public class UsersController : ControllerBase
2224 {
25+ private readonly ICacheAccessProvider _cache ;
2326 private readonly AppDbContext _db ;
2427 private readonly JwtOptions _jwt ;
2528
26- public UsersController ( AppDbContext db , IOptions < JwtOptions > jwtOptions )
27- {
28- _db = db ;
29- _jwt = jwtOptions . Value ;
30- }
29+ public UsersController ( ICacheAccessProvider cache , AppDbContext db , IOptions < JwtOptions > jwtOptions ) => ( _cache , _db , _jwt ) = ( cache , db , jwtOptions . Value ) ;
30+
3131 // --------- NEW: POST /api/users/authenticate ----------
3232 [ HttpPost ( "authenticate" ) ]
3333 [ ProducesResponseType ( typeof ( AuthResponse ) , StatusCodes . Status200OK ) ]
@@ -70,15 +70,58 @@ public async Task<ActionResult<AuthResponse>> Authenticate([FromBody] LoginReque
7070 var dto = await BuildPermissionsForUser ( user . Id ) ;
7171
7272 var token = GenerateJwt ( user , out var expiresAtUtc ) ;
73-
74- return Ok ( new AuthResponse ( user . Id , user . UserName , token , expiresAtUtc , dto . Categories ) ) ;
73+
74+ var role = user ? . UserRoles . Select ( ur => ur . Role . Name ) . FirstOrDefault ( ) ;
75+
76+ return Ok ( new AuthResponse ( user . Id , user . UserName , token , role , expiresAtUtc , dto . Categories ) ) ;
77+ }
78+
79+ [ HttpPost ( "updatepermissions" ) ]
80+ [ ProducesResponseType ( typeof ( AuthResponse ) , StatusCodes . Status200OK ) ]
81+ public async Task < ActionResult < AuthResponse > > UpdatePermissions ( [ FromBody ] UpdatePermissionsRequest operation )
82+ {
83+ var admin = await _db . Roles . Where ( r => r . Name == "Admin" ) . FirstOrDefaultAsync ( ) ;
84+ var webfunction = await _db . Functions . Where ( r => r . Code == "Logs.View" ) . FirstOrDefaultAsync ( ) ;
85+ var apifunction = await _db . Functions . Where ( r => r . Code == "Api.Logs.View" ) . FirstOrDefaultAsync ( ) ;
86+
87+ bool hasWebAccess = _db . RoleFunctions . Any ( rf => rf . FunctionId == webfunction . Id && rf . RoleId == admin . Id ) ;
88+ bool hasApiAccess = _db . RoleFunctions . Any ( rf => rf . FunctionId == apifunction . Id && rf . RoleId == admin . Id ) ;
89+
90+ if ( operation . Op == "grant-webapp" && ! hasWebAccess )
91+ {
92+ await _db . RoleFunctions . AddAsync ( new RoleFunction ( ) { RoleId = admin . Id , FunctionId = webfunction . Id } ) ;
93+ }
94+ if ( operation . Op == "grant-api" && ! hasApiAccess )
95+ {
96+ await _db . RoleFunctions . AddAsync ( new RoleFunction ( ) { RoleId = admin . Id , FunctionId = apifunction . Id } ) ;
97+ }
98+ if ( operation . Op == "revoke-api" && hasApiAccess )
99+ {
100+ _db . RoleFunctions . Remove ( new RoleFunction ( ) { RoleId = admin . Id , FunctionId = apifunction . Id } ) ;
101+ }
102+ if ( operation . Op == "revoke-both" )
103+ {
104+ if ( hasWebAccess )
105+ _db . RoleFunctions . Remove ( new RoleFunction ( ) { RoleId = admin . Id , FunctionId = webfunction . Id } ) ;
106+ if ( hasApiAccess )
107+ _db . RoleFunctions . Remove ( new RoleFunction ( ) { RoleId = admin . Id , FunctionId = apifunction . Id } ) ;
108+ }
109+ // save once (only if something changed)
110+ if ( _db . ChangeTracker . HasChanges ( ) )
111+ {
112+ var affected = await _db . SaveChangesAsync ( ) ;
113+ }
114+
115+ long cacheresult = await _cache . InvalidatePermissionsForRoleAsync ( "Admin" ) ;
116+
117+ return Ok ( new { Message = $ "Permissions updated with operation: { operation . Op } " } ) ;
75118 }
76119
77120 // --------- (Existing) GET /api/users/{userId}/permissions ----------
78121 // Now protected by JWT; call with Bearer token returned by /authenticate
79122 [ Authorize ]
80123 [ HttpGet ( "{userId:int}/permissions" ) ]
81- public async Task < ActionResult < UserPermissionsDto > > GetPermissions ( int userId )
124+ public async Task < ActionResult > GetPermissions ( int userId )
82125 {
83126 // Optional: you can enforce that a user can only view their own permissions
84127 // by comparing userId with the token's sub, if desired.
@@ -90,6 +133,24 @@ public async Task<ActionResult<UserPermissionsDto>> GetPermissions(int userId)
90133 return Ok ( dto ) ;
91134 }
92135
136+ [ Authorize ]
137+ [ HttpGet ( "{userId:int}/getstate" ) ]
138+ public async Task < object > GetStateAsync ( int userId )
139+ {
140+ var admin = await _db . Roles . Where ( r => r . Name == "Admin" ) . FirstOrDefaultAsync ( ) ;
141+ var webfunction = await _db . Functions . Where ( r => r . Code == "Logs.View" ) . FirstOrDefaultAsync ( ) ;
142+ var apifunction = await _db . Functions . Where ( r => r . Code == "Api.Logs.View" ) . FirstOrDefaultAsync ( ) ;
143+
144+ bool hasWebAccess = _db . RoleFunctions . Any ( rf => rf . FunctionId == webfunction . Id && rf . RoleId == admin . Id ) ;
145+ bool hasApiAccess = _db . RoleFunctions . Any ( rf => rf . FunctionId == apifunction . Id && rf . RoleId == admin . Id ) ;
146+
147+ return new
148+ {
149+ webapp = hasWebAccess ,
150+ api = hasApiAccess
151+ } ;
152+ }
153+
93154 // ----- helpers -----
94155
95156 protected virtual async Task < UserPermissionsDto > BuildPermissionsForUser ( int userId )
@@ -159,11 +220,11 @@ protected virtual string GenerateJwt(AppUser user, out DateTime expiresAtUtc)
159220
160221 var key = new SymmetricSecurityKey ( Encoding . UTF8 . GetBytes ( keyPlain ) ) ;
161222 var creds = new SigningCredentials ( key , SecurityAlgorithms . HmacSha256 ) ;
162-
223+
163224 var claims = new List < Claim >
164225 {
165226 new ( JwtRegisteredClaimNames . Sub , user . Id . ToString ( ) ) ,
166- new ( JwtRegisteredClaimNames . UniqueName , user . UserName )
227+ new ( JwtRegisteredClaimNames . UniqueName , user . UserName )
167228 } ;
168229
169230 var now = DateTime . UtcNow ;
@@ -179,5 +240,7 @@ protected virtual string GenerateJwt(AppUser user, out DateTime expiresAtUtc)
179240
180241 return new JwtSecurityTokenHandler ( ) . WriteToken ( token ) ;
181242 }
243+
244+
182245 }
183246}
0 commit comments