Compare commits

..

1 Commits

Author SHA1 Message Date
I-Fun
0d27befed0 fix: resolve 5 bugs — auth, ownership, crash, notification, and HTML issues
- dashboard.php: fix PDO parameter count crash for users with no groups
  (used max(count,1) for placeholder count but provided 0 group params)
- index.php: add missing auth check on get_tasks_status API endpoint
  (was accessible without a session, exposing all task data)
- index.php: enforce ownership check on delete_comment API
  (any logged-in user could delete any comment; now requires authorship or admin)
- tasks.php: fix task creation notification using undefined $_SESSION['username']
  (replaced with $current_user['username'] so {assignor} template works correctly)
- tasks.php: remove duplicate id attribute on att-lightbox-body element

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 23:21:15 +07:00
4 changed files with 19 additions and 5 deletions

5
.gitignore vendored
View File

@@ -2,3 +2,8 @@
uploads/* uploads/*
*.log *.log
.env .env
.agents/*
.antigravity/*
.vscode/*
.gemini/*
.cursor/*

View File

@@ -96,14 +96,23 @@ if ($action === 'api') {
if(!isset($_SESSION['user_id'])) die(json_encode(['status'=>'error','msg'=>'unauthorized'])); if(!isset($_SESSION['user_id'])) die(json_encode(['status'=>'error','msg'=>'unauthorized']));
$comment_id = $_POST['comment_id'] ?? null; $comment_id = $_POST['comment_id'] ?? null;
if($comment_id) { if($comment_id) {
$stmt = $pdo->prepare("DELETE FROM task_comments WHERE id = ?"); $user_id = $_SESSION['user_id'];
$stmt->execute([$comment_id]); $is_admin = !empty($_SESSION['is_admin']);
$comment_check = query("SELECT created_by FROM task_comments WHERE id = ?", [$comment_id])->fetch();
if($comment_check && ($comment_check['created_by'] == $user_id || $is_admin)) {
$stmt = $pdo->prepare("DELETE FROM task_comments WHERE id = ?");
$stmt->execute([$comment_id]);
} else {
echo json_encode(['status'=>'error','msg'=>'forbidden']);
exit;
}
} }
echo json_encode(['status'=>'ok']); echo json_encode(['status'=>'ok']);
exit; exit;
} }
if($api_action === 'get_tasks_status') { if($api_action === 'get_tasks_status') {
if(!isset($_SESSION['user_id'])) die(json_encode(['status'=>'error','msg'=>'unauthorized']));
$task_id = $_GET['task_id'] ?? null; $task_id = $_GET['task_id'] ?? null;
// Correlated subquery gives attachment count per task. // Correlated subquery gives attachment count per task.

View File

@@ -17,7 +17,7 @@ try {
// ── Task Counts ─────────────────────────────────────────────────────────────── // ── Task Counts ───────────────────────────────────────────────────────────────
$user_groups = get_user_groups($user_id); $user_groups = get_user_groups($user_id);
$my_group_ids = array_column($user_groups, 'id'); $my_group_ids = array_column($user_groups, 'id');
$group_in = implode(',', array_fill(0, max(count($my_group_ids), 1), '?')) ?: '0'; $group_in = $my_group_ids ? implode(',', array_fill(0, count($my_group_ids), '?')) : '0';
$params_tasks = array_merge([$user_id, $user_id], $my_group_ids, $my_group_ids, [$user_id]); $params_tasks = array_merge([$user_id, $user_id], $my_group_ids, $my_group_ids, [$user_id]);
$sql_tasks = "SELECT status, COUNT(*) as cnt FROM tasks WHERE $sql_tasks = "SELECT status, COUNT(*) as cnt FROM tasks WHERE
(assignee_type='user' AND assignee_id=?) (assignee_type='user' AND assignee_id=?)

View File

@@ -155,7 +155,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_task'])) {
} }
// Handle notifications // Handle notifications
$ctx = ['action' => 'Created', 'module' => 'Task', 'item' => $title, 'assignor' => $_SESSION['username'] ?? 'System', 'due_date' => $due_date ?: 'None']; $ctx = ['action' => 'Created', 'module' => 'Task', 'item' => $title, 'assignor' => $current_user['username'] ?? 'System', 'due_date' => $due_date ?: 'None'];
foreach($to_list as $rec) { foreach($to_list as $rec) {
$u = query("SELECT id FROM users WHERE username=?", [$rec])->fetch(); $u = query("SELECT id FROM users WHERE username=?", [$rec])->fetch();
if($u) notify_user($u['id'], "You have been assigned a new task: $title", $ctx); if($u) notify_user($u['id'], "You have been assigned a new task: $title", $ctx);
@@ -463,7 +463,7 @@ body.dark-mode .kanban-task { border: 1px solid rgba(255,255,255,0.05); border-l
<span id="att-lightbox-title">Preview</span> <span id="att-lightbox-title">Preview</span>
<button id="att-lightbox-close" onclick="closeAttachmentPreview()" title="Close">✕</button> <button id="att-lightbox-close" onclick="closeAttachmentPreview()" title="Close">✕</button>
</div> </div>
<div id="att-lightbox-body" id="att-lightbox-body"></div> <div id="att-lightbox-body"></div>
</div> </div>
</div> </div>