Integrating With Clerk
Clerk is a comprehensive authentication and user management platform, providing both APIs and pre-made UI components.
Set up Clerk​
First, follow Clerk's quick start guides to set up your project.
Adjust your ZModel​
Since Clerk manages both user authentication and storage, you don't need to store users in your database anymore. However, since the auth()
function is resolved to the User
model in ZModel, you still need to define it in your schema. The trick here is to mark the User
model as ignored so Prisma doesn't map it to a database table.
You can include any field you want in the User
model, as long as you provide the same set of fields in the context object used for creating the enhanced Prisma client.
The following code shows an example blog post schema:
model User {
id String @id
@@ignore
}
model Post {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
published Boolean @default(false)
authorId String // stores Clerk's user ID
// author has full access
@@allow('all', auth() != null && auth().id == authorId)
// logged-in users can view published posts
@@allow('read', auth() != null && published)
}
If you choose to synchronize user data to your database, you can model the User
model as a regular Prisma model without putting the @@ignore
attribute there.
Create an enhanced Prisma client​
You can create an enhanced Prisma client that automatically validates access policies, field validation rules, etc., during CRUD operations. For more details, please refer to ZModel Language reference.
To create such a client with a standard setup, call the enhance
API with a regular Prisma client and the current user (fetched from Clerk). Here's an example:
import type { NextApiRequest } from 'next';
import { enhance } from '@zenstackhq/runtime';
import { getAuth } from '@clerk/nextjs/server';
import { prisma } from '../lib/db';
async function getPrisma(req: NextApiRequest) {
const auth = getAuth(req);
// create a wrapper of Prisma client that enforces access policy,
// data validation, and @password, @omit behaviors
return enhance(prisma, { user: auth ? { id: auth.userId } : undefined });
}
You can find a working sample project here.