Registry / database / prisma-rls

prisma-rls

JSON →
library0.5.6jsnpmunverified

prisma-rls is a Prisma client extension designed to implement row-level security (RLS) on any database, including those without native RLS support (e.g., MySQL). It achieves this by automatically injecting 'where' clauses into all Prisma model queries, effectively filtering data based on defined permissions. The current stable version is `0.5.6`. The package shows active development with frequent minor releases and bug fixes, indicated by the recent changelog entries. A key differentiator is its database-agnostic approach, allowing RLS where it wouldn't natively exist, and its integration directly into the Prisma client query pipeline. It ships with TypeScript types, providing a type-safe way to define permissions configurations and contexts. It's crucial to note that this extension does not apply to raw database queries, which require manual handling.

npm install prisma-rls
INSTALL
IMPORT
SIG · PRISMA-RLS
P
prisma-rls
databasejavascriptv0.5.6
Install
—
Import
—
Disk
—
Pass rate
0/ 6
Env Coverage0 / 6
glibc
18–22
musl
18–22
Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
node 18–226 runs
build_error
glibc
node 18–226 runs
build_error
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

createRlsExtension
✓ import { createRlsExtension } from 'prisma-rls';
✗ const { createRlsExtension } = require('prisma-rls');
Primary entry point for creating the RLS extension; `require()` is not supported for this ESM-first library.
PermissionsConfig
✓ import { PermissionsConfig } from 'prisma-rls';
✗ import type { PermissionsConfig } from 'prisma-rls';
This is a runtime value, not just a type, as it defines the structure for permissions at runtime.
ExtensionOptions
✓ import type { ExtensionOptions } from 'prisma-rls';
✗ import { ExtensionOptions } from 'prisma-rls';
This is a TypeScript type, so use `import type` for clarity and to avoid bundling issues.

This example demonstrates how to integrate `prisma-rls` with a Fastify server to apply row-level security based on user roles and context. It defines permissions for 'User' and 'Guest' roles, creates a dynamic Prisma client extension per request, and applies RLS to `Post` and `User` model queries. Authorization is simulated via a bearer token.

import { Prisma, PrismaClient } from "@prisma/client"; import Fastify, { FastifyRequest } from "fastify"; import { createRlsExtension, PermissionsConfig } from "prisma-rls"; // Define shared types for roles and permissions context export type Role = "User" | "Guest"; export type PermissionsContext = { userId: string | null }; export type RolePermissions = PermissionsConfig<Prisma.TypeMap, PermissionsContext>; export type PermissionsRegistry = Record<Role, RolePermissions>; // Define user permissions const userPermissions: RolePermissions = { Post: { read: { published: { equals: true } }, create: true, update: (ctx) => ({ authorId: { equals: ctx.userId } }), delete: (ctx) => ({ authorId: { equals: ctx.userId } }) }, User: { read: (ctx) => ({ id: { equals: ctx.userId } }), create: false, update: (ctx) => ({ id: { equals: ctx.userId } }), delete: false } }; // Define guest permissions const guestPermissions: RolePermissions = { Post: { read: { published: { equals: true } }, create: false, update: false, delete: false }, User: { read: false, create: false, update: false, delete: false } }; // Combine permissions into a registry export const permissionsRegistry = { User: userPermissions, Guest: guestPermissions } satisfies PermissionsRegistry; (async () => { const prisma = new PrismaClient(); const server = Fastify(); // Dummy function to resolve user from auth header const resolveUser = async (authorizationHeader?: string | string[] | undefined) => { if (authorizationHeader === 'Bearer user-token') { return { id: 'user-123', role: 'User' }; } return null; }; server.decorateRequest('db', null); server.addHook('onRequest', async (request: any, reply) => { const user = await resolveUser(request.headers.authorization); const userRole: Role = user ? user.role : "Guest"; const permissionsContext: PermissionsContext = { userId: user?.id ?? null }; const rlsExtension = createRlsExtension({ dmmf: Prisma.dmmf, permissionsConfig: permissionsRegistry[userRole], context: permissionsContext, }); request.db = prisma.$extends(rlsExtension); }); server.get("/posts", async function handler(request: any, reply) { // Assuming a user with 'user-token' can only see their own posts // and public posts. Guests can only see public posts. return await request.db.post.findMany(); }); server.get("/profile", async function handler(request: any, reply) { // A user can only see their own profile, guests see nothing. return await request.db.user.findMany(); // Will apply RLS based on `userId` }); await server.listen({ port: 8080, host: "0.0.0.0" }); console.log('Server listening on http://0.0.0.0:8080'); })();
Debug
Known issues
breakingVersion `0.5.0` introduced major internal type safety improvements and refactored error handling to use dedicated error classes (`AuthorizationError`, `ReferentialIntegrityError`). Existing error handling logic might need updates.
fix
Review and update error handling for `AuthorizationError` and `ReferentialIntegrityError` classes. Ensure types are correctly inferred with the narrower type definitions.
affects: >=0.5.0
gotchaThe `prisma-rls` extension does not apply to raw Prisma queries (e.g., `prisma.$queryRaw`, `prisma.$executeRaw`). RLS for raw queries must be handled manually at the database level or through application-side validation.
fix
Avoid using raw queries for operations requiring RLS, or implement custom security checks and `WHERE` clauses for all raw queries.
affects: >=0.1.0
gotchaWhen dealing with mandatory 'belongs-to' relations (where the foreign key owner side is required), Prisma typically does not generate filters to prevent referential integrity violations. This can lead to unexpected behavior where RLS might not apply as expected.
fix
Enable the `checkRequiredBelongsTo` flag in `createRlsExtension` options if explicit checks are required for these relations, accepting potential performance implications. Alternatively, design your schema to avoid mandatory 'belongs-to' relations where RLS is critical, or handle these specific cases with custom logic.
affects: >=0.1.0
Errors
Common errors & fixes
TypeError: Cannot read properties of undefined (reading 'id')
The `PermissionsContext` object or a property within it (e.g., `user` or `user.id`) is `null` or `undefined` when a permission function tries to access it.
fix
Ensure that your `PermissionsContext` object is always fully populated with expected values, or add null-checking/optional chaining within your permission functions, for example: `permissionContext.user?.id`.
PrismaClientKnownRequestError: Argument 'where' must not be empty.
A permission function evaluated to an empty `where` object when a non-empty `where` clause was expected, potentially due to a context issue or a misconfigured permission that disallows access entirely (e.g., `false`).
fix
Review the permission definition for the specific model and operation. Ensure the permission function returns a valid `where` object or `true` for allowed access, or `false` for explicit denial, rather than an implicitly empty object.
Upgrade
Version history
0.5.6latest on npm
Audit
Dependencies
@prisma/clientrequiredRequired Prisma Client for extension functionality and type generation.
Agent activity
11 hits · last 30 days
node
10
OpenAI (training)
1
Resources
prisma-rls — npm install prisma-rls · libregistry