Database
In our application, we use a single Prisma client instance which is then split into two contexts within a request:
-
database
(protected): This instance is enhanced with the user session using Zenstack. It provides access control based on the current user's permissions. -
databaseUnprotected
: This is the raw Prisma client instance without any protection or enhancement.
Database Provider
The database provider is set up in app/core/database/index.ts
:
import { PrismaClient } from '@prisma/client'
const singleton = globalThis as unknown as {
prisma: PrismaClient | undefined
}
if (!singleton.prisma) {
singleton.prisma = new PrismaClient({
log: ['error'],
})
}
export const Database = singleton.prisma
This setup ensures that we have a single Prisma client instance across the application.
Context Creation
The splitting of the database instance happens in the getPrisma
function, typically located in app/core/authentication/server/context.tsx
:
const getPrisma = (session: Awaited<ReturnType<typeof getSession>>) => {
const databaseProtected = enhance(Database, { user: session.user })
return {
database: databaseProtected,
databaseUnprotected: Database,
prisma: databaseProtected,
masterPrisma: Database,
}
}
This function applies the Zenstack enhancer to create a protected database instance based on the user's session.
Usage
When working with the database, you'll typically use the database
instance for operations that should respect user permissions, and databaseUnprotected
for operations that bypass permission checks.
For a deeper understanding of how user sessions affect SQL queries and how roles and permissions are managed, please refer to the Roles and Permissions section. Zenstack manages these permissions to provide a simple interface for access control in your database operations.