Skip to content

Commit cc4504b

Browse files
committed
refactor(policy): move raw sql allowance into handler
1 parent cd78922 commit cc4504b

2 files changed

Lines changed: 20 additions & 15 deletions

File tree

packages/plugins/policy/src/plugin.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
import { type OnKyselyQueryArgs, type RuntimePlugin } from '@zenstackhq/orm';
22
import type { SchemaDef } from '@zenstackhq/orm/schema';
3-
import { RawNode } from 'kysely';
43
import { check } from './functions';
5-
import { PolicyHandler } from './policy-handler';
4+
import { PolicyHandler, type PolicyHandlerOptions } from './policy-handler';
65

7-
export type PolicyPluginOptions = {
8-
/**
9-
* Dangerously bypasses access-policy enforcement for raw SQL queries.
10-
* Raw queries remain in the current transaction, but the policy plugin will
11-
* not inspect or reject them.
12-
*/
13-
dangerouslyAllowRawSql?: boolean;
14-
};
6+
export type PolicyPluginOptions = PolicyHandlerOptions;
157

168
export class PolicyPlugin implements RuntimePlugin<SchemaDef, {}, {}, {}> {
179
constructor(private readonly options: PolicyPluginOptions = {}) {}
@@ -35,10 +27,7 @@ export class PolicyPlugin implements RuntimePlugin<SchemaDef, {}, {}, {}> {
3527
}
3628

3729
onKyselyQuery({ query, client, proceed }: OnKyselyQueryArgs<SchemaDef>) {
38-
if (this.options.dangerouslyAllowRawSql && RawNode.is(query as never)) {
39-
return proceed(query);
40-
}
41-
const handler = new PolicyHandler<SchemaDef>(client);
30+
const handler = new PolicyHandler<SchemaDef>(client, this.options);
4231
return handler.handle(query, proceed);
4332
}
4433
}

packages/plugins/policy/src/policy-handler.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
OperatorNode,
2424
ParensNode,
2525
PrimitiveValueListNode,
26+
RawNode,
2627
ReferenceNode,
2728
ReturningNode,
2829
SelectAllNode,
@@ -63,11 +64,23 @@ export type MutationQueryNode = InsertQueryNode | UpdateQueryNode | DeleteQueryN
6364

6465
type FieldLevelPolicyOperations = Exclude<CRUD_EXT, 'create' | 'delete'>;
6566

67+
export type PolicyHandlerOptions = {
68+
/**
69+
* Dangerously bypasses access-policy enforcement for raw SQL queries.
70+
* Raw queries remain in the current transaction, but the policy plugin will
71+
* not inspect or reject them.
72+
*/
73+
dangerouslyAllowRawSql?: boolean;
74+
};
75+
6676
export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransformer {
6777
private readonly dialect: BaseCrudDialect<Schema>;
6878
private readonly eb = expressionBuilder<any, any>();
6979

70-
constructor(private readonly client: ClientContract<Schema>) {
80+
constructor(
81+
private readonly client: ClientContract<Schema>,
82+
private readonly options: PolicyHandlerOptions = {},
83+
) {
7184
super();
7285
this.dialect = getCrudDialect(this.client.$schema, this.client.$options);
7386
}
@@ -76,6 +89,9 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
7689

7790
async handle(node: RootOperationNode, proceed: ProceedKyselyQueryFunction) {
7891
if (!this.isCrudQueryNode(node)) {
92+
if (this.options.dangerouslyAllowRawSql && RawNode.is(node as never)) {
93+
return proceed(node);
94+
}
7995
// non-CRUD queries are not allowed
8096
throw createRejectedByPolicyError(
8197
undefined,

0 commit comments

Comments
 (0)