export const dynamic = 'force-dynamic'; import { NextRequest, NextResponse } from 'next/server'; import { supabase } from '@/lib/supabase'; import { ensureAuthenticated, getAuthContext, hasProjectAccess } from '@/lib/access-control'; export async function GET(request: NextRequest) { const ctx = await getAuthContext(request); const auth = ensureAuthenticated(ctx); if (!auth.ok) { return NextResponse.json({ error: auth.error }, { status: auth.status }); } const searchParams = request.nextUrl.searchParams; const kr_id = searchParams.get('kr_id'); const project_id = searchParams.get('project_id'); const user_id = searchParams.get('user_id'); const help_requested_to_user_id = searchParams.get('help_requested_to_user_id'); const include_help = searchParams.get('include_help') === 'true'; if (!ctx!.isAdmin) { if (user_id && user_id !== ctx!.user.id) { return NextResponse.json({ error: '无权限' }, { status: 403 }); } if (help_requested_to_user_id && help_requested_to_user_id !== ctx!.user.id) { return NextResponse.json({ error: '无权限' }, { status: 403 }); } if (project_id && !hasProjectAccess(ctx!, project_id)) { return NextResponse.json({ error: '无权限' }, { status: 403 }); } if (kr_id) { const { data: kr, error: krErr } = await supabase .from('krs') .select('id,project_id') .eq('id', kr_id) .maybeSingle(); if (krErr) return NextResponse.json({ error: krErr.message }, { status: 500 }); if (!kr) return NextResponse.json({ error: 'KR不存在' }, { status: 404 }); if (!hasProjectAccess(ctx!, kr.project_id)) { return NextResponse.json({ error: '无权限' }, { status: 403 }); } } } const baseQuery = () => supabase .from('tasks') .select(` *, steps:task_steps(*) `) .order('created_at', { ascending: false }); const applyParams = (query: ReturnType) => { let q = query; if (kr_id) { q = q.eq('kr_id', kr_id); } else if (project_id) { q = q.eq('project_id', project_id).is('kr_id', null); } if (help_requested_to_user_id) { q = q.eq('help_requested_to_user_id', help_requested_to_user_id); } else if (user_id) { if (include_help) { q = q.or(`owner_user_id.eq.${user_id},help_requested_to_user_id.eq.${user_id}`); } else { q = q.eq('owner_user_id', user_id); } } return q; }; if (ctx!.isAdmin) { const { data, error } = await applyParams(baseQuery()); if (error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json(data); } if (project_id || kr_id) { const { data, error } = await applyParams(baseQuery()); if (error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json(data); } const relatedTasks = new Map(); const addRows = (rows: any[] | null) => { if (!rows) return; for (const row of rows) { relatedTasks.set(row.id, row); } }; const projectIds = ctx!.accessibleProjectIds; const builders: any[] = []; if (projectIds.length > 0) { builders.push(applyParams(baseQuery().in('project_id', projectIds))); } builders.push(applyParams(baseQuery().or(`owner_user_id.eq.${ctx!.user.id},help_requested_to_user_id.eq.${ctx!.user.id}`))); builders.push(applyParams(baseQuery().contains('executor_ids', [ctx!.user.id]))); const results = await Promise.all(builders.map(b => b)); for (const r of results) { if (r.error) { return NextResponse.json({ error: r.error.message }, { status: 500 }); } addRows(r.data); } return NextResponse.json(Array.from(relatedTasks.values())); } export async function POST(request: NextRequest) { const ctx = await getAuthContext(request); const auth = ensureAuthenticated(ctx); if (!auth.ok) { return NextResponse.json({ error: auth.error }, { status: auth.status }); } const body = await request.json(); const { kr_id, project_id, 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 isHelpRequested = Boolean(help_requested_to_user_id); if (!ctx!.isAdmin) { if (project_id && !hasProjectAccess(ctx!, project_id)) { return NextResponse.json({ error: '无权限' }, { status: 403 }); } if (kr_id) { const { data: kr, error: krErr } = await supabase .from('krs') .select('id,project_id') .eq('id', kr_id) .maybeSingle(); if (krErr) return NextResponse.json({ error: krErr.message }, { status: 500 }); if (!kr) return NextResponse.json({ error: 'KR不存在' }, { status: 404 }); if (!hasProjectAccess(ctx!, kr.project_id)) { return NextResponse.json({ error: '无权限' }, { status: 403 }); } } } const { data, error } = await supabase .from('tasks') .insert({ kr_id: kr_id || null, project_id: project_id || null, title, description, status: status || 'todo', priority: priority || 3, urgency: urgency || 3, owner_user_id, executor_ids: executor_ids || [], start_date, end_date, help_requested_to_user_id: help_requested_to_user_id || null, help_requested_by_user_id: help_requested_by_user_id || null, help_requested_at: isHelpRequested ? new Date().toISOString() : null, }) .select() .single(); if (error) { return NextResponse.json({ error: error.message }, { status: 500 }); } return NextResponse.json(data); }