New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

prisma-rls

Package Overview
Dependencies
Maintainers
0
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prisma-rls - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1

26

dist/extension.js

@@ -16,3 +16,3 @@ "use strict";

return extension_1.Prisma.defineExtension({
name: "prisma-extension-rls",
name: "prisma-rls",
query: {

@@ -25,3 +25,3 @@ $allModels: {

case "findUnique":
if (!modelPermissions.select) {
if (!modelPermissions.read) {
return Promise.resolve(null);

@@ -32,3 +32,3 @@ }

case "findUniqueOrThrow":
if (!modelPermissions.select) {
if (!modelPermissions.read) {
throw new library_1.PrismaClientKnownRequestError(`No ${modelName} found`, {

@@ -41,3 +41,3 @@ code: "P2025",

case "findMany":
if (!modelPermissions.select) {
if (!modelPermissions.read) {
return Promise.resolve([]);

@@ -47,3 +47,3 @@ }

case "aggregate":
if (!modelPermissions.select) {
if (!modelPermissions.read) {
return query({

@@ -56,3 +56,3 @@ ...args,

case "count":
if (!modelPermissions.select) {
if (!modelPermissions.read) {
return Promise.resolve(0);

@@ -62,3 +62,3 @@ }

case "groupBy":
if (!modelPermissions.select) {
if (!modelPermissions.read) {
return Promise.resolve([]);

@@ -94,7 +94,7 @@ }

case "findUniqueOrThrow":
if (modelPermissions.select !== true || args.select || args.include) {
if (modelPermissions.read !== true || args.select || args.include) {
return query({
...args,
...(0, utils_1.mergeSelectAndInclude)(permissionsConfig, context, fieldsMap, modelName, args.select, args.include),
where: (0, utils_1.mergeWhereUnique)(fieldsMap, modelName, args.where, (0, utils_1.resolveWhere)(modelPermissions.select, context)),
where: (0, utils_1.mergeWhereUnique)(fieldsMap, modelName, args.where, (0, utils_1.resolveWhere)(modelPermissions.read, context)),
});

@@ -106,7 +106,7 @@ }

case "findMany":
if (modelPermissions.select !== true || args.select || args.include) {
if (modelPermissions.read !== true || args.select || args.include) {
return query({
...args,
...(0, utils_1.mergeSelectAndInclude)(permissionsConfig, context, fieldsMap, modelName, args.select, args.include),
where: (0, utils_1.mergeWhere)(args.where, (0, utils_1.resolveWhere)(modelPermissions.select, context)),
where: (0, utils_1.mergeWhere)(args.where, (0, utils_1.resolveWhere)(modelPermissions.read, context)),
});

@@ -118,6 +118,6 @@ }

case "groupBy":
if (modelPermissions.select !== true) {
if (modelPermissions.read !== true) {
return query({
...args,
where: (0, utils_1.mergeWhere)(args.where, (0, utils_1.resolveWhere)(modelPermissions.select, context)),
where: (0, utils_1.mergeWhere)(args.where, (0, utils_1.resolveWhere)(modelPermissions.read, context)),
});

@@ -124,0 +124,0 @@ }

@@ -8,3 +8,3 @@ import type { DMMF } from "@prisma/client/runtime/library";

export type ModelPermissionsConfig<TypeMap extends PrismaTypeMap, ModelName extends PrismaModelName<TypeMap>, Context extends unknown> = {
select: boolean | PrismaModelWhere<TypeMap, ModelName> | ((context: Context) => PrismaModelWhere<TypeMap, ModelName>);
read: boolean | PrismaModelWhere<TypeMap, ModelName> | ((context: Context) => PrismaModelWhere<TypeMap, ModelName>);
create: boolean;

@@ -11,0 +11,0 @@ update: boolean | PrismaModelWhere<TypeMap, ModelName> | ((context: Context) => PrismaModelWhere<TypeMap, ModelName>);

@@ -66,3 +66,3 @@ "use strict";

const relationPermissions = permissionsConfig[relationModelName];
select[fieldName] = { where: (0, exports.resolveWhere)(relationPermissions.select, context) };
select[fieldName] = { where: (0, exports.resolveWhere)(relationPermissions.read, context) };
}

@@ -89,13 +89,13 @@ }

const relationPermissions = permissionsConfig[relationModelName];
if (relationPermissions.select === false) {
if (relationPermissions.read === false) {
return { where: (0, exports.generateImpossibleWhere)(fieldsMap[modelName]) };
}
else if (relationPermissions.select !== true && selectValue === true) {
return { where: (0, exports.resolveWhere)(relationPermissions.select, context) };
else if (relationPermissions.read !== true && selectValue === true) {
return { where: (0, exports.resolveWhere)(relationPermissions.read, context) };
}
else if (relationPermissions.select !== true && selectValue !== false) {
else if (relationPermissions.read !== true && selectValue !== false) {
return {
...selectValue,
...(0, exports.mergeSelectAndInclude)(permissionsConfig, context, fieldsMap, relationModelName, selectValue.select, selectValue.include),
where: (0, exports.mergeWhere)(selectValue.where, (0, exports.resolveWhere)(relationPermissions.select, context)),
where: (0, exports.mergeWhere)(selectValue.where, (0, exports.resolveWhere)(relationPermissions.read, context)),
};

@@ -102,0 +102,0 @@ }

{
"name": "prisma-rls",
"version": "0.1.0",
"version": "0.1.1",
"description": "Prisma client extension for row-level security on any database",

@@ -11,6 +11,7 @@ "license": "MIT",

"prisma-extension",
"rls"
"rls",
"row-level-security"
],
"author": "s1owjke",
"homepage": "https://github.com/s1owjke/prisma-extension-rls",
"homepage": "https://github.com/s1owjke/prisma-rls",
"main": "dist/index.js",

@@ -17,0 +18,0 @@ "types": "dist/index.d.ts",

# Prisma RLS
> 🚧 It's an experimental package, under development
[![Published on npm](https://img.shields.io/npm/v/prisma-rls?color=brightgreen)](https://www.npmjs.com/package/prisma-rls) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
The classical approach to implementing Row-Level Security (RLS) involves using a database with built-in support and writing row-level security policies for tables.
> 🚧 The package is under active development, public api could be changed
The classic approach to implementing Row-Level Security (RLS) requires a database with built-in support and writing row-level security policies for tables.
This library offers an alternative approach - an extension to the Prisma client that adds additional "where" clauses to all model queries. This approach doesn't require RLS support on the database side (for example, in MySQL).
It's important to keep in mind that this extension doesn't cover raw queries. In such cases, you should take care of it yourself.
It's important to keep in mind that this extension doesn't cover raw queries. In such cases, you should take care of it yourself or use classic approach.
## How to use it
Extend the Prisma client with the rls extension
Define permissions for all models in your schema.
```typescript
import { Prisma } from "@prisma/client";
import { PermissionsConfig } from "prisma-rls";
export type Context = Record<string, any>;
type RolePermissions = PermissionsConfig<Prisma.TypeMap, Context>;
export const Guest: RolePermissions = {
Post: {
read: { published: { equals: true } },
create: false,
update: false,
delete: false,
},
User: {
read: { role: { not: { equals: "admin" } } },
create: false,
update: false,
delete: false,
},
}
```
Extend the Prisma client with the rls extension.
```typescript
import { Prisma, PrismaClient } from "@prisma/client";
import { createRlsExtension } from "prisma-extension-rls";
import { createRlsExtension } from "prisma-rls";
import { permissions } from "./permissions";
import { Guest } from "./permissions/guest";
const db = new PrismaClient().$extends(createRlsExtension(Prisma.dmmf, permissions, null));
const context: Context = {};
const db = new PrismaClient().$extends(createRlsExtension(Prisma.dmmf, Guest, context));
```
Since Prisma doesn't support contexts to pass data to the [extensions](https://www.prisma.io/docs/orm/prisma-client/client-extensions), you will typically extend the Prisma client per request (based on current auth toke role)
After that all requests except raw will be executed according to permissions
### Permissions registry
Almost always you will have several roles, to describe them in a type-safe way use the following pattern:
```typescript
import { admin } from "./admin";
import { guest } from "./guest";
type Role = "Admin" | "Guest";
type PermissionsRegistry = Record<Role, RolePermissions>;
export const permissionsRegistry = {
Admin: admin,
Guest: guest,
} satisfies PermissionsRegistry;
```
### Context
Since Prisma doesn't support context to pass data to the [extensions](https://www.prisma.io/docs/orm/prisma-client/client-extensions), you will typically extend the client per request (based on role associated with auth token):
```typescript
import { Prisma, PrismaClient } from "@prisma/client";
import Fastify, { FastifyRequest } from "fastify";
import { createRlsExtension } from "prisma-extension-rls";
import { createRlsExtension } from "prisma-rls";
import { permissions } from "./permissions";
import { permissionsRegistry } from "./permissions";

@@ -39,3 +88,3 @@ (async () => {

const role = resolveRole(request.headers.authorization);
const rolePermissions = permissions[role];
const rolePermissions = permissionsRegistry[role];

@@ -42,0 +91,0 @@ return { db: prisma.$extends(createRlsExtension(Prisma.dmmf, rolePermissions, { role })) };

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc