export const dynamic = 'force-dynamic'; import { NextRequest, NextResponse } from 'next/server'; import { supabase } from '@/lib/supabase'; import { ensureAuthenticated, getAuthContext } from '@/lib/access-control'; async function canAccessTask(userId: string, isAdmin: boolean, accessibleProjectIds: string[], taskId: string) { if (isAdmin) return { ok: true as const }; const { data: task, error } = await supabase .from('tasks') .select('id,project_id,owner_user_id,executor_ids,help_requested_to_user_id') .eq('id', taskId) .maybeSingle(); if (error) return { ok: false as const, status: 500, error: error.message }; if (!task) return { ok: false as const, status: 404, error: '计划不存在' }; if (task.project_id && accessibleProjectIds.includes(task.project_id)) return { ok: true as const }; if (task.owner_user_id === userId) return { ok: true as const }; if (task.help_requested_to_user_id === userId) return { ok: true as const }; if (Array.isArray(task.executor_ids) && task.executor_ids.includes(userId)) return { ok: true as const }; return { ok: false as const, status: 403, error: '无权限' }; } export async function PATCH( request: NextRequest, { params }: { params: { id: string } } ) { const ctx = await getAuthContext(request); const auth = ensureAuthenticated(ctx); if (!auth.ok) { return NextResponse.json({ error: auth.error }, { status: auth.status }); } const access = await canAccessTask(ctx!.user.id, ctx!.isAdmin, ctx!.accessibleProjectIds, params.id); if (!access.ok) { return NextResponse.json({ error: access.error }, { status: access.status }); } const body = await request.json(); const { title, description, status, priority, urgency, owner_user_id, executor_ids, start_date, end_date, help_requested_to_user_id, help_requested_by_user_id, } = body; const updateData: Record = { updated_at: new Date().toISOString() }; if (title !== undefined) updateData.title = title; if (description !== undefined) updateData.description = description; if (status !== undefined) updateData.status = status; if (priority !== undefined) updateData.priority = priority; if (urgency !== undefined) updateData.urgency = urgency; if (owner_user_id !== undefined) updateData.owner_user_id = owner_user_id; if (executor_ids !== undefined) updateData.executor_ids = executor_ids; if (start_date !== undefined) updateData.start_date = start_date; if (end_date !== undefined) updateData.end_date = end_date; if (help_requested_to_user_id !== undefined) { updateData.help_requested_to_user_id = help_requested_to_user_id; if (help_requested_to_user_id) { updateData.help_requested_by_user_id = help_requested_by_user_id || null; updateData.help_requested_at = new Date().toISOString(); } else { updateData.help_requested_by_user_id = null; updateData.help_requested_at = null; } } const { data, error } = await supabase .from('tasks') .update(updateData) .eq('id', params.id) .select() .single(); if (error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json(data); } export async function DELETE( request: NextRequest, { params }: { params: { id: string } } ) { const ctx = await getAuthContext(request); const auth = ensureAuthenticated(ctx); if (!auth.ok) { return NextResponse.json({ error: auth.error }, { status: auth.status }); } const access = await canAccessTask(ctx!.user.id, ctx!.isAdmin, ctx!.accessibleProjectIds, params.id); if (!access.ok) { return NextResponse.json({ error: access.error }, { status: access.status }); } const { error } = await supabase .from('tasks') .delete() .eq('id', params.id); if (error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json({ success: true }); }