diff --git a/app/api/code-completion/route.ts b/app/api/code-completion/route.ts index f7ede13..8bd2bf1 100644 --- a/app/api/code-completion/route.ts +++ b/app/api/code-completion/route.ts @@ -4,6 +4,7 @@ import { CodeSnippet, batchGenerateCompletions, } from '@/lib/code-completion' +import { getCurrentUser } from '@/lib/auth' import { getDb } from '@/lib/db' const LANG_EXTENSIONS: Record = { @@ -24,18 +25,20 @@ const LANG_EXTENSIONS: Record = { shell: ['.sh', '.bash'], } -async function fetchSnippetsFromDb(language: string): Promise { +async function fetchSnippetsFromDb(language: string, userId: string): Promise { try { const sql = getDb() const extensions = LANG_EXTENSIONS[language.toLowerCase()] ?? [] if (extensions.length === 0) return [] const rows = await sql` - SELECT id, path, name, extension, ai_summary, reusability_score, exports, imports - FROM repo_files - WHERE extension = ANY(${extensions}::text[]) - AND ai_summary IS NOT NULL - ORDER BY reusability_score DESC + SELECT rf.id, rf.path, rf.name, rf.extension, rf.ai_summary, rf.reusability_score, rf.exports, rf.imports + FROM repo_files rf + INNER JOIN repositories r ON r.id = rf.repository_id + WHERE r.user_id = ${userId} + AND rf.extension = ANY(${extensions}::text[]) + AND rf.ai_summary IS NOT NULL + ORDER BY rf.reusability_score DESC LIMIT 20 ` @@ -63,6 +66,9 @@ async function fetchSnippetsFromDb(language: string): Promise { export async function POST(request: NextRequest) { try { + const user = await getCurrentUser() + if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + const body = await request.json() const { incompleteCode, codebaseSnippets = [], language = 'python' } = body @@ -75,7 +81,7 @@ export async function POST(request: NextRequest) { const snippets: CodeSnippet[] = codebaseSnippets.length > 0 ? codebaseSnippets - : await fetchSnippetsFromDb(language) + : await fetchSnippetsFromDb(language, user.id) const result = await generateRelevanceGuidedCompletion( incompleteCode, @@ -120,6 +126,9 @@ export async function POST(request: NextRequest) { */ export async function PUT(request: NextRequest) { try { + const user = await getCurrentUser() + if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + const body = await request.json() const { codeSnippets = [], codebaseSnippets = [], language = 'python' } = body @@ -132,7 +141,7 @@ export async function PUT(request: NextRequest) { const snippets: CodeSnippet[] = codebaseSnippets.length > 0 ? codebaseSnippets - : await fetchSnippetsFromDb(language) + : await fetchSnippetsFromDb(language, user.id) const results = await batchGenerateCompletions( codeSnippets, diff --git a/app/api/projects/[id]/milestones/[milestoneId]/route.ts b/app/api/projects/[id]/milestones/[milestoneId]/route.ts index 0b04cb1..f75fd26 100644 --- a/app/api/projects/[id]/milestones/[milestoneId]/route.ts +++ b/app/api/projects/[id]/milestones/[milestoneId]/route.ts @@ -9,10 +9,10 @@ export async function PATCH( const user = await getCurrentUser() if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) - const { milestoneId } = await params + const { id, milestoneId } = await params try { const { completed } = await request.json() - const milestone = await toggleMilestone(milestoneId, Boolean(completed)) + const milestone = await toggleMilestone(milestoneId, id, user.id, Boolean(completed)) if (!milestone) return NextResponse.json({ error: 'Not found' }, { status: 404 }) return NextResponse.json({ milestone }) } catch (err) { @@ -28,9 +28,10 @@ export async function DELETE( const user = await getCurrentUser() if (!user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) - const { milestoneId } = await params + const { id, milestoneId } = await params try { - await deleteMilestone(milestoneId) + const deleted = await deleteMilestone(milestoneId, id, user.id) + if (!deleted) return NextResponse.json({ error: 'Not found' }, { status: 404 }) return NextResponse.json({ ok: true }) } catch (err) { console.error('[milestones/id] DELETE error:', err) diff --git a/lib/queries.ts b/lib/queries.ts index 7dd365e..06996f0 100644 --- a/lib/queries.ts +++ b/lib/queries.ts @@ -1044,27 +1044,53 @@ export async function createMilestone(data: { return result[0] as ProjectMilestone } -export async function toggleMilestone(id: string, completed: boolean): Promise { +export async function toggleMilestone( + id: string, + projectId: string, + userId: string, + completed: boolean, +): Promise { const sql = getDb() const result = completed ? await sql` - UPDATE project_milestones + UPDATE project_milestones AS m SET completed = true, completed_at = NOW() - WHERE id = ${id} - RETURNING * + FROM projects AS p + WHERE m.id = ${id} + AND m.project_id = ${projectId} + AND p.id = m.project_id + AND p.user_id = ${userId} + RETURNING m.* ` : await sql` - UPDATE project_milestones + UPDATE project_milestones AS m SET completed = false, completed_at = NULL - WHERE id = ${id} - RETURNING * + FROM projects AS p + WHERE m.id = ${id} + AND m.project_id = ${projectId} + AND p.id = m.project_id + AND p.user_id = ${userId} + RETURNING m.* ` return (result[0] as ProjectMilestone) || null } -export async function deleteMilestone(id: string): Promise { +export async function deleteMilestone( + id: string, + projectId: string, + userId: string, +): Promise { const sql = getDb() - await sql`DELETE FROM project_milestones WHERE id = ${id}` + const result = await sql` + DELETE FROM project_milestones AS m + USING projects AS p + WHERE m.id = ${id} + AND m.project_id = ${projectId} + AND p.id = m.project_id + AND p.user_id = ${userId} + RETURNING m.id + ` + return result.length > 0 } export async function seedDefaultMilestones(projectId: string): Promise {