@@ -254,6 +254,80 @@ public IActionResult RemoveMember(string id, [FromBody] RemoveMemberDto dto)
254254 }
255255 }
256256
257+ // 🔹 PUT /api/projects/{id}/member/{userId}/permissions - update a specific member's role/permissions
258+ public class UpdateMemberPermissionsDto
259+ {
260+ public string ? Role { get ; set ; }
261+ }
262+
263+ [ HttpPut ( "{id}/member/{userId}/permissions" ) ]
264+ public IActionResult UpdateMemberPermissions ( string id , string userId , [ FromBody ] UpdateMemberPermissionsDto dto )
265+ {
266+ if ( string . IsNullOrWhiteSpace ( id ) )
267+ return BadRequest ( new { message = "Invalid project id." } ) ;
268+ if ( string . IsNullOrWhiteSpace ( userId ) )
269+ return BadRequest ( new { message = "Invalid user id." } ) ;
270+ if ( dto == null || string . IsNullOrWhiteSpace ( dto . Role ) )
271+ return BadRequest ( new { message = "Role is required." } ) ;
272+
273+ var db = _mongoDbService . GetDatabase ( ) ;
274+ var collection = db . GetCollection < FlowModels . Project > ( "project" ) ;
275+ var project = collection . Find ( p => p . Id == id ) . FirstOrDefault ( ) ;
276+ if ( project == null )
277+ return NotFound ( new { message = "Project not found." } ) ;
278+
279+ var requesterId = GetUserIdFromToken ( ) ;
280+ if ( requesterId == null )
281+ return Unauthorized ( new { message = "Invalid user token." } ) ;
282+
283+ // Only Owner or Admin can update permissions
284+ var isOwner = project . Permissions != null && project . Permissions . TryGetValue ( requesterId , out var requesterRole ) && requesterRole == "Owner" ;
285+ if ( ! isOwner && ! User . IsInRole ( "Admin" ) )
286+ return StatusCode ( 403 , new { message = "Only the project owner or an admin can update member permissions." } ) ;
287+
288+ // Verify the user exists
289+ var usersCollection = db . GetCollection < FlowModels . User > ( "user" ) ;
290+ var userExists = usersCollection . Find ( u => u . Id == userId ) . Any ( ) ;
291+ if ( ! userExists )
292+ return BadRequest ( new { message = "User does not exist." } ) ;
293+
294+ // Ensure user is a team member first
295+ var members = project . TeamMembers ?? new List < string > ( ) ;
296+ if ( ! members . Contains ( userId ) )
297+ {
298+ // Add them to team members if not already
299+ members . Add ( userId ) ;
300+ }
301+
302+ // Update permissions dictionary
303+ var permissions = project . Permissions ?? new Dictionary < string , string > ( ) ;
304+ permissions [ userId ] = dto . Role ;
305+
306+ var updateDefs = new List < UpdateDefinition < FlowModels . Project > >
307+ {
308+ Builders < FlowModels . Project > . Update . Set ( p => p . TeamMembers , members ) ,
309+ Builders < FlowModels . Project > . Update . Set ( p => p . Permissions , permissions )
310+ } ;
311+
312+ try
313+ {
314+ var result = collection . UpdateOne (
315+ Builders < FlowModels . Project > . Filter . Eq ( "_id" , ObjectId . Parse ( id ) ) ,
316+ Builders < FlowModels . Project > . Update . Combine ( updateDefs )
317+ ) ;
318+
319+ if ( result . MatchedCount == 0 )
320+ return NotFound ( new { message = "Project not found." } ) ;
321+
322+ var updatedProject = collection . Find ( p => p . Id == id ) . FirstOrDefault ( ) ;
323+ return Ok ( updatedProject ) ;
324+ }
325+ catch ( Exception ex )
326+ {
327+ return StatusCode ( 500 , new { message = "Failed to update member permissions." , detail = ex . Message } ) ;
328+ }
329+ }
330+
257331 // 🔹 DELETE /api/projects/{id}/leave - remove the current authenticated user from the project
258332 [ HttpDelete ( "{id}/leave" ) ]
259333 public IActionResult LeaveProject ( string id )
0 commit comments