fix: prevent subtasks from disappearing when updating parent task (#984)
This commit addresses a critical bug where subtasks would disappear when updating the parent task (e.g., assigning tags). The issue had multiple potential causes: 1. Backend vulnerability: The updateSubtasks() function would delete all subtasks if an empty array was sent, treating it as "delete everything not in this list" 2. Frontend state management: After reloading a task, subtasks weren't being preserved if the backend response didn't include them 3. Unclear error messages: "Invalid parent task" errors didn't provide enough context for debugging Changes: - Added defensive logging in updateSubtasks() to warn when all subtasks are being deleted with an empty array - Enhanced validateParentTaskAccess() error messages to provide detailed diagnostics (task not found vs. permission issues vs. wrong user) - Updated handleTagsUpdate() in TaskDetails to explicitly preserve subtasks when reloading task after tag updates This fix is defensive in nature and adds better observability for diagnosing similar issues in the future. Fixes issue reported by user where subtasks disappeared after assigning tags to parent task, and "Invalid parent task" errors occurred when trying to update the orphaned subtasks.
This commit is contained in:
parent
11c3fe5e43
commit
e8c7eed226
3 changed files with 37 additions and 3 deletions
|
|
@ -92,6 +92,26 @@ async function updateSubtasks(taskId, subtasks, userId) {
|
|||
);
|
||||
|
||||
if (subtasksToDelete.length > 0) {
|
||||
if (
|
||||
subtasksToDelete.length === existingSubtasks.length &&
|
||||
subtasks.length === 0
|
||||
) {
|
||||
logError(
|
||||
'WARNING: Attempting to delete all subtasks with empty array:',
|
||||
{
|
||||
taskId,
|
||||
userId,
|
||||
existingCount: existingSubtasks.length,
|
||||
providedCount: subtasks.length,
|
||||
subtasksToDelete: subtasksToDelete.map((s) => ({
|
||||
id: s.id,
|
||||
name: s.name,
|
||||
parent_task_id: s.parent_task_id,
|
||||
})),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
await taskRepository.destroyMany({
|
||||
where: {
|
||||
id: subtasksToDelete.map((s) => s.id),
|
||||
|
|
|
|||
|
|
@ -36,7 +36,18 @@ async function validateParentTaskAccess(parentTaskId, userId) {
|
|||
where: { id: parentTaskId, user_id: userId },
|
||||
});
|
||||
if (!parentTask) {
|
||||
throw new Error('Invalid parent task.');
|
||||
const anyTask = await Task.findOne({
|
||||
where: { id: parentTaskId },
|
||||
});
|
||||
if (anyTask) {
|
||||
throw new Error(
|
||||
`Invalid parent task. Parent task exists but belongs to a different user (parent user_id: ${anyTask.user_id}, current user_id: ${userId}).`
|
||||
);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Invalid parent task. Parent task with id ${parentTaskId} not found.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const parentAccess = await permissionsService.getAccess(
|
||||
|
|
@ -49,7 +60,7 @@ async function validateParentTaskAccess(parentTaskId, userId) {
|
|||
isOwner || parentAccess === 'rw' || parentAccess === 'admin';
|
||||
|
||||
if (!canWrite) {
|
||||
throw new Error('Invalid parent task.');
|
||||
throw new Error('Invalid parent task. Insufficient permissions.');
|
||||
}
|
||||
|
||||
return parentTaskId;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue