{"library":"prisma-rls","title":"Prisma Row-Level Security Extension","description":"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.","language":"javascript","status":"active","last_verified":"Wed Apr 22","install":{"commands":["npm install prisma-rls"],"cli":null},"imports":["import { createRlsExtension } from 'prisma-rls';","import { PermissionsConfig } from 'prisma-rls';","import type { ExtensionOptions } from 'prisma-rls';"],"auth":{"required":false,"env_vars":[]},"quickstart":{"code":"import { Prisma, PrismaClient } from \"@prisma/client\";\nimport Fastify, { FastifyRequest } from \"fastify\";\nimport { createRlsExtension, PermissionsConfig } from \"prisma-rls\";\n\n// Define shared types for roles and permissions context\nexport type Role = \"User\" | \"Guest\";\nexport type PermissionsContext = { userId: string | null };\nexport type RolePermissions = PermissionsConfig<Prisma.TypeMap, PermissionsContext>;\nexport type PermissionsRegistry = Record<Role, RolePermissions>;\n\n// Define user permissions\nconst userPermissions: RolePermissions = {\n  Post: {\n    read: { published: { equals: true } },\n    create: true,\n    update: (ctx) => ({ authorId: { equals: ctx.userId } }),\n    delete: (ctx) => ({ authorId: { equals: ctx.userId } })\n  },\n  User: {\n    read: (ctx) => ({ id: { equals: ctx.userId } }),\n    create: false,\n    update: (ctx) => ({ id: { equals: ctx.userId } }),\n    delete: false\n  }\n};\n\n// Define guest permissions\nconst guestPermissions: RolePermissions = {\n  Post: {\n    read: { published: { equals: true } },\n    create: false,\n    update: false,\n    delete: false\n  },\n  User: {\n    read: false,\n    create: false,\n    update: false,\n    delete: false\n  }\n};\n\n// Combine permissions into a registry\nexport const permissionsRegistry = {\n  User: userPermissions,\n  Guest: guestPermissions\n} satisfies PermissionsRegistry;\n\n(async () => {\n  const prisma = new PrismaClient();\n  const server = Fastify();\n\n  // Dummy function to resolve user from auth header\n  const resolveUser = async (authorizationHeader?: string | string[] | undefined) => {\n    if (authorizationHeader === 'Bearer user-token') {\n      return { id: 'user-123', role: 'User' };\n    }\n    return null;\n  };\n\n  server.decorateRequest('db', null);\n\n  server.addHook('onRequest', async (request: any, reply) => {\n    const user = await resolveUser(request.headers.authorization);\n    const userRole: Role = user ? user.role : \"Guest\";\n    const permissionsContext: PermissionsContext = { userId: user?.id ?? null };\n\n    const rlsExtension = createRlsExtension({\n      dmmf: Prisma.dmmf,\n      permissionsConfig: permissionsRegistry[userRole],\n      context: permissionsContext,\n    });\n    request.db = prisma.$extends(rlsExtension);\n  });\n\n  server.get(\"/posts\", async function handler(request: any, reply) {\n    // Assuming a user with 'user-token' can only see their own posts\n    // and public posts. Guests can only see public posts.\n    return await request.db.post.findMany();\n  });\n\n  server.get(\"/profile\", async function handler(request: any, reply) {\n    // A user can only see their own profile, guests see nothing.\n    return await request.db.user.findMany(); // Will apply RLS based on `userId`\n  });\n\n  await server.listen({ port: 8080, host: \"0.0.0.0\" });\n  console.log('Server listening on http://0.0.0.0:8080');\n})();","lang":"typescript","description":"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.","tag":null,"tag_description":null,"last_tested":null,"results":[]},"compatibility":null}