Skip to content

Commit 44990b4

Browse files
committed
Refactor project permissions checks to use team membership; enhance project deletion to remove associated tasks and categories
1 parent 7b63c35 commit 44990b4

2 files changed

Lines changed: 56 additions & 8 deletions

File tree

Controllers/CategoryController.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,15 @@ public CategoryController(MongoDbService mongoDbService)
3434
return string.IsNullOrWhiteSpace(userId) ? null : userId;
3535
}
3636

37-
private bool HasProjectEditPermission(string projectId, string userId)
37+
private bool IsProjectTeamMember(string projectId, string userId)
3838
{
3939
if (string.IsNullOrWhiteSpace(projectId) || string.IsNullOrWhiteSpace(userId)) return false;
4040
var db = _mongoDbService.GetDatabase();
4141
var projects = db.GetCollection<FlowModels.Project>("project");
4242
var proj = projects.Find(p => p.Id == projectId).FirstOrDefault();
4343
if (proj == null) return false;
44-
if (proj.Permissions == null) return false;
45-
if (!proj.Permissions.TryGetValue(userId, out var role)) return false;
46-
return role == "Owner" || role == "Editor" || User.IsInRole("Admin");
44+
if (proj.TeamMembers == null) return false;
45+
return proj.TeamMembers.Contains(userId);
4746
}
4847

4948
// GET /api/categories?projectId=<id>&includeTasks=true
@@ -115,7 +114,7 @@ public IActionResult Create([FromBody] FlowModels.Category category)
115114

116115
var requesterId = GetUserIdFromToken();
117116
if (requesterId == null) return Unauthorized(new { message = "Invalid user token." });
118-
if (!HasProjectEditPermission(category.ProjectId!, requesterId)) return Forbid("You do not have permission to create a category for this project.");
117+
if (!IsProjectTeamMember(category.ProjectId!, requesterId)) return StatusCode(403, new { message = "You must be a team member of the project to create a category." });
119118

120119
var db = _mongoDbService.GetDatabase();
121120
var categoriesCollection = db.GetCollection<FlowModels.Category>("categories");
@@ -139,7 +138,7 @@ public IActionResult Update(string id, [FromBody] FlowModels.Category updated)
139138

140139
var requesterId = GetUserIdFromToken();
141140
if (requesterId == null) return Unauthorized(new { message = "Invalid user token." });
142-
if (!HasProjectEditPermission(existing.ProjectId!, requesterId)) return Forbid("You do not have permission to update this category.");
141+
if (!IsProjectTeamMember(existing.ProjectId!, requesterId)) return StatusCode(403, new { message = "You must be a team member of the project to update a category." });
143142

144143
// Update fields
145144
if (!string.IsNullOrWhiteSpace(updated.CategoryName))
@@ -170,6 +169,15 @@ public IActionResult Delete(string id)
170169
// Deletion allowed if user has project edit permission
171170
// if (!HasProjectEditPermission(existing.ProjectId!, requesterId)) return Forbid("You do not have permission to delete this category.");
172171

172+
// Remove category reference from all subtasks in this project
173+
var subTasksCollection = db.GetCollection<FlowModels.SubTask>("subtasks");
174+
var updateDefinition = Builders<FlowModels.SubTask>.Update
175+
.Set(t => t.Category, null);
176+
subTasksCollection.UpdateMany(
177+
t => t.ProjectId == existing.ProjectId && t.Category == existing.CategoryName,
178+
updateDefinition
179+
);
180+
173181
categoriesCollection.DeleteOne(c => c.Id == id);
174182
return Ok(new { message = "Category deleted successfully.", id = id });
175183
}

Controllers/ProjectsController.cs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,20 @@ public IActionResult RemoveMember(string id, [FromBody] RemoveMemberDto dto)
245245
if (result.MatchedCount == 0)
246246
return NotFound(new { message = "Project not found." });
247247

248+
// Remove the member from all subtasks in this project
249+
var subTasksCollection = db.GetCollection<FlowModels.SubTask>("subtasks");
250+
var subTaskFilter = Builders<FlowModels.SubTask>.Filter.And(
251+
Builders<FlowModels.SubTask>.Filter.Eq(st => st.ProjectId, id),
252+
Builders<FlowModels.SubTask>.Filter.AnyEq(st => st.AssignedTo, memberId)
253+
);
254+
var subTaskUpdate = Builders<FlowModels.SubTask>.Update.Pull(st => st.AssignedTo, memberId);
255+
var subTasksUpdateResult = subTasksCollection.UpdateMany(subTaskFilter, subTaskUpdate);
256+
248257
var updatedProject = collection.Find(p => p.Id == id).FirstOrDefault();
249-
return Ok(updatedProject);
258+
return Ok(new {
259+
project = updatedProject,
260+
tasksUpdated = subTasksUpdateResult.ModifiedCount
261+
});
250262
}
251263
catch (Exception ex)
252264
{
@@ -456,6 +468,14 @@ public IActionResult GetMembers(string id)
456468
var usersCollection = db.GetCollection<FlowModels.User>("user");
457469
var memberIds = project.TeamMembers ?? new List<string>();
458470

471+
// Filter out members who have "Client" role in permissions
472+
if (project.Permissions != null)
473+
{
474+
memberIds = memberIds.Where(memberId =>
475+
!project.Permissions.TryGetValue(memberId, out var role) || role != "Client"
476+
).ToList();
477+
}
478+
459479
if (memberIds.Count == 0)
460480
return Ok(new List<object>());
461481

@@ -613,8 +633,28 @@ public IActionResult Delete(string id)
613633
if (!isOwner && !User.IsInRole("Admin"))
614634
return StatusCode(403, new { message = "Only the project owner or an admin can delete this project." });
615635

636+
// Delete all subtasks associated with this project
637+
var subTasksCollection = db.GetCollection<FlowModels.SubTask>("subtasks");
638+
var subTasksDeleteResult = subTasksCollection.DeleteMany(st => st.ProjectId == id);
639+
640+
// Delete all main tasks associated with this project
641+
var mainTasksCollection = db.GetCollection<FlowModels.MainTask>("maintasks");
642+
var mainTasksDeleteResult = mainTasksCollection.DeleteMany(mt => mt.ProjectId == id);
643+
644+
// Delete all categories associated with this project
645+
var categoriesCollection = db.GetCollection<FlowModels.Category>("categories");
646+
var categoriesDeleteResult = categoriesCollection.DeleteMany(c => c.ProjectId == id);
647+
648+
// Delete the project itself
616649
collection.DeleteOne(p => p.Id == id);
617-
return Ok(new { message = "Project deleted successfully.", id = id });
650+
651+
return Ok(new {
652+
message = "Project and all associated data deleted successfully.",
653+
id = id,
654+
deletedSubTasks = subTasksDeleteResult.DeletedCount,
655+
deletedMainTasks = mainTasksDeleteResult.DeletedCount,
656+
deletedCategories = categoriesDeleteResult.DeletedCount
657+
});
618658
}
619659

620660
// 🔹 PATCH /api/projects/{id}/permissions

0 commit comments

Comments
 (0)