Scope all Drizzle queries by user_id from authenticated session

Every data API route now filters SELECT, INSERT, UPDATE, and DELETE
queries by the authenticated user's ID, ensuring full multi-tenant
data isolation. Candle queries are scoped via chart_id ownership.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marko Djordjevic 2026-02-20 13:08:09 +01:00
parent 9901d0f3f1
commit 5f727d84c6
15 changed files with 75 additions and 60 deletions

View file

@ -1,7 +1,7 @@
import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { candles, charts } from '@/lib/db/schema';
import { asc, desc, eq } from 'drizzle-orm';
import { asc, desc, eq, and } from 'drizzle-orm';
import { getAuthUser } from '@/lib/auth';
export async function GET(request: NextRequest) {
@ -16,7 +16,7 @@ export async function GET(request: NextRequest) {
// Fall back to most recent chart if no chartId provided
if (!chartId) {
const latest = await db.select({ id: charts.id }).from(charts).orderBy(desc(charts.created_at)).limit(1);
const latest = await db.select({ id: charts.id }).from(charts).where(eq(charts.user_id, user.id)).orderBy(desc(charts.created_at)).limit(1);
if (latest.length === 0) {
return NextResponse.json([]);
}
@ -31,6 +31,12 @@ export async function GET(request: NextRequest) {
);
}
// Verify chart belongs to user
const chartOwner = await db.select({ id: charts.id }).from(charts).where(and(eq(charts.id, chartIdNum), eq(charts.user_id, user.id))).limit(1);
if (chartOwner.length === 0) {
return NextResponse.json({ error: 'Chart not found' }, { status: 404 });
}
const allCandles = await db
.select({
time: candles.time,