Files
ims/lib/db/with-user.ts
T

30 lines
977 B
TypeScript

import 'server-only'
import { sql } from 'drizzle-orm'
import { userDb, adminDb, type UserDb, type AdminDb } from './index'
export type DrizzleTransaction = Parameters<Parameters<typeof userDb.transaction>[0]>[0]
/**
* Runs fn inside a transaction with app.user_id SET LOCAL to userId.
* All RLS policies read this GUC via app_current_user_id().
* The GUC is LOCAL so it is automatically cleared when the transaction ends.
*/
export async function withUser<T>(
userId: string,
fn: (tx: DrizzleTransaction) => Promise<T>
): Promise<T> {
return userDb.transaction(async (tx) => {
await tx.execute(sql`SELECT set_config('app.user_id', ${userId}, true)`)
return fn(tx)
})
}
/**
* Runs fn against the admin (BYPASSRLS) pool.
* Use only for: admin user CRUD, service operations that legitimately bypass RLS.
* Never use for regular user data access.
*/
export async function asAdmin<T>(fn: (db: AdminDb) => Promise<T>): Promise<T> {
return fn(adminDb)
}