@kysera/rls 0.8.7 → 0.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +11 -4
- package/dist/index.js +11 -12
- package/dist/index.js.map +1 -1
- package/dist/native/index.d.ts +1 -1
- package/dist/native/index.js +77 -8
- package/dist/native/index.js.map +1 -1
- package/dist/{types-CyqksFKU.d.ts → types-D3hQINlj.d.ts} +11 -1
- package/package.json +15 -15
- package/src/native/postgres.ts +60 -10
- package/src/plugin.ts +19 -12
- package/src/policy/types.ts +12 -1
- package/src/transformer/mutation.ts +3 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RLSSchema, O as Operation, P as PolicyCondition, a as PolicyHints, b as PolicyActivationCondition, C as ConditionalPolicyDefinition, F as FilterCondition, T as TableRLSConfig, c as PolicyDefinition, d as CompiledPolicy, e as CompiledFilterPolicy, f as RLSContext, g as RLSAuthContext, h as RLSRequestContext, i as PolicyEvaluationContext } from './types-
|
|
2
|
-
export { k as PolicyActivationContext, j as PolicyType } from './types-
|
|
1
|
+
import { R as RLSSchema, O as Operation, P as PolicyCondition, a as PolicyHints, b as PolicyActivationCondition, C as ConditionalPolicyDefinition, F as FilterCondition, T as TableRLSConfig, c as PolicyDefinition, d as CompiledPolicy, e as CompiledFilterPolicy, f as RLSContext, g as RLSAuthContext, h as RLSRequestContext, i as PolicyEvaluationContext } from './types-D3hQINlj.js';
|
|
2
|
+
export { k as PolicyActivationContext, j as PolicyType } from './types-D3hQINlj.js';
|
|
3
3
|
import { KyseraLogger, DatabaseError, ErrorCode } from '@kysera/core';
|
|
4
4
|
import { Plugin } from '@kysera/executor';
|
|
5
5
|
import { z } from 'zod';
|
|
@@ -663,8 +663,14 @@ interface RLSPluginOptions<DB = unknown> {
|
|
|
663
663
|
/** RLS policy schema */
|
|
664
664
|
schema: RLSSchema<DB>;
|
|
665
665
|
/**
|
|
666
|
-
*
|
|
667
|
-
*
|
|
666
|
+
* Whitelist of tables to apply RLS to.
|
|
667
|
+
* If provided, only these tables will have RLS enforced.
|
|
668
|
+
* Takes precedence over excludeTables when both are provided.
|
|
669
|
+
*/
|
|
670
|
+
tables?: string[];
|
|
671
|
+
/**
|
|
672
|
+
* Tables to exclude from RLS (always bypass policies).
|
|
673
|
+
* Ignored if `tables` whitelist is provided.
|
|
668
674
|
*/
|
|
669
675
|
excludeTables?: string[];
|
|
670
676
|
/** Roles that bypass RLS entirely (e.g., ['admin', 'superuser']) */
|
|
@@ -719,6 +725,7 @@ interface RLSPluginOptions<DB = unknown> {
|
|
|
719
725
|
* Note: 'schema' and 'onViolation' are not included as they are complex runtime objects.
|
|
720
726
|
*/
|
|
721
727
|
declare const RLSPluginOptionsSchema: z.ZodObject<{
|
|
728
|
+
tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
722
729
|
excludeTables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
723
730
|
bypassRoles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
724
731
|
requireContext: z.ZodOptional<z.ZodBoolean>;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DatabaseError, silentLogger } from '@kysera/core';
|
|
1
|
+
import { DatabaseError, silentLogger, shouldApplyToTable } from '@kysera/core';
|
|
2
2
|
import { isRepositoryLike, getRawDb } from '@kysera/executor';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { AsyncLocalStorage } from 'async_hooks';
|
|
4
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
5
5
|
import { sql } from 'kysely';
|
|
6
6
|
|
|
7
7
|
// src/errors.ts
|
|
@@ -1173,9 +1173,9 @@ var MutationGuard = class {
|
|
|
1173
1173
|
if (skipFor.some((role) => ctx.auth.roles.includes(role))) {
|
|
1174
1174
|
return;
|
|
1175
1175
|
}
|
|
1176
|
+
const evalCtx = this.createEvalContext(ctx, table, operation, row, data);
|
|
1176
1177
|
const denies = this.registry.getDenies(table, operation);
|
|
1177
1178
|
for (const deny2 of denies) {
|
|
1178
|
-
const evalCtx = this.createEvalContext(ctx, table, operation, row, data);
|
|
1179
1179
|
const result = await this.evaluatePolicy(deny2.evaluate, evalCtx, deny2.name);
|
|
1180
1180
|
if (result) {
|
|
1181
1181
|
throw new RLSPolicyViolation(operation, table, `Denied by policy: ${deny2.name}`);
|
|
@@ -1184,7 +1184,6 @@ var MutationGuard = class {
|
|
|
1184
1184
|
if ((operation === "create" || operation === "update") && data) {
|
|
1185
1185
|
const validates = this.registry.getValidates(table, operation);
|
|
1186
1186
|
for (const validate2 of validates) {
|
|
1187
|
-
const evalCtx = this.createEvalContext(ctx, table, operation, row, data);
|
|
1188
1187
|
const result = await this.evaluatePolicy(validate2.evaluate, evalCtx, validate2.name);
|
|
1189
1188
|
if (!result) {
|
|
1190
1189
|
throw new RLSPolicyViolation(operation, table, `Validation failed: ${validate2.name}`);
|
|
@@ -1199,7 +1198,6 @@ var MutationGuard = class {
|
|
|
1199
1198
|
if (allows.length > 0) {
|
|
1200
1199
|
let allowed = false;
|
|
1201
1200
|
for (const allow2 of allows) {
|
|
1202
|
-
const evalCtx = this.createEvalContext(ctx, table, operation, row, data);
|
|
1203
1201
|
const result = await this.evaluatePolicy(allow2.evaluate, evalCtx, allow2.name);
|
|
1204
1202
|
if (result) {
|
|
1205
1203
|
allowed = true;
|
|
@@ -1292,6 +1290,7 @@ var MutationGuard = class {
|
|
|
1292
1290
|
var RAW_VERSION = "__VERSION__";
|
|
1293
1291
|
var VERSION = RAW_VERSION.startsWith("__") ? "0.0.0-dev" : RAW_VERSION;
|
|
1294
1292
|
var RLSPluginOptionsSchema = z.object({
|
|
1293
|
+
tables: z.array(z.string()).optional(),
|
|
1295
1294
|
excludeTables: z.array(z.string()).optional(),
|
|
1296
1295
|
bypassRoles: z.array(z.string()).optional(),
|
|
1297
1296
|
requireContext: z.boolean().optional(),
|
|
@@ -1302,7 +1301,8 @@ var RLSPluginOptionsSchema = z.object({
|
|
|
1302
1301
|
function rlsPlugin(options) {
|
|
1303
1302
|
const {
|
|
1304
1303
|
schema,
|
|
1305
|
-
|
|
1304
|
+
tables,
|
|
1305
|
+
excludeTables,
|
|
1306
1306
|
bypassRoles = [],
|
|
1307
1307
|
logger = silentLogger,
|
|
1308
1308
|
requireContext = true,
|
|
@@ -1319,8 +1319,8 @@ function rlsPlugin(options) {
|
|
|
1319
1319
|
return {
|
|
1320
1320
|
name: "@kysera/rls",
|
|
1321
1321
|
version: VERSION,
|
|
1322
|
-
//
|
|
1323
|
-
priority:
|
|
1322
|
+
// SECURITY plugin: must run FIRST to enforce access policies before other plugins
|
|
1323
|
+
priority: 1e3,
|
|
1324
1324
|
// No dependencies by default
|
|
1325
1325
|
dependencies: [],
|
|
1326
1326
|
/**
|
|
@@ -1329,7 +1329,7 @@ function rlsPlugin(options) {
|
|
|
1329
1329
|
onInit(_executor) {
|
|
1330
1330
|
logger.info?.("[RLS] Initializing RLS plugin", {
|
|
1331
1331
|
tables: Object.keys(schema).length,
|
|
1332
|
-
excludeTables: excludeTables
|
|
1332
|
+
excludeTables: excludeTables?.length ?? 0,
|
|
1333
1333
|
bypassRoles: bypassRoles.length
|
|
1334
1334
|
});
|
|
1335
1335
|
registry = new PolicyRegistry(schema);
|
|
@@ -1344,7 +1344,6 @@ function rlsPlugin(options) {
|
|
|
1344
1344
|
onDestroy() {
|
|
1345
1345
|
registry.clear();
|
|
1346
1346
|
logger.info?.("[RLS] RLS plugin destroyed, cleared policy registry");
|
|
1347
|
-
return Promise.resolve();
|
|
1348
1347
|
},
|
|
1349
1348
|
/**
|
|
1350
1349
|
* Intercept queries to apply RLS filtering
|
|
@@ -1355,7 +1354,7 @@ function rlsPlugin(options) {
|
|
|
1355
1354
|
*/
|
|
1356
1355
|
interceptQuery(qb, context) {
|
|
1357
1356
|
const { operation, table, metadata } = context;
|
|
1358
|
-
if (
|
|
1357
|
+
if (!shouldApplyToTable(table, { tables, excludeTables })) {
|
|
1359
1358
|
logger.debug?.(`[RLS] Skipping RLS for excluded table: ${table}`);
|
|
1360
1359
|
return qb;
|
|
1361
1360
|
}
|
|
@@ -1438,7 +1437,7 @@ function rlsPlugin(options) {
|
|
|
1438
1437
|
}
|
|
1439
1438
|
const baseRepo = repo;
|
|
1440
1439
|
const table = baseRepo.tableName;
|
|
1441
|
-
if (
|
|
1440
|
+
if (!shouldApplyToTable(table, { tables, excludeTables })) {
|
|
1442
1441
|
logger.debug?.(`[RLS] Skipping repository extension for excluded table: ${table}`);
|
|
1443
1442
|
return repo;
|
|
1444
1443
|
}
|