-
Notifications
You must be signed in to change notification settings - Fork 64
RLS: support the explicit table name APIs #873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe changes enhance Row Level Security functionality by introducing explicit table-name parameters across read/write operations. Both the implementation and tests are updated to support implicit (single-argument) and explicit (table-qualified) API patterns, with test coverage expanded for both calling conventions. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
commit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/convex-helpers/server/rowLevelSecurity.ts (1)
239-257: Fix security bypass inget(id)whendefaultPolicy: "deny"is configured.The single-argument
get(id)form bypassesdefaultPolicy: "deny"for tables without explicit rules. When an ID belongs to a table not in the rules configuration,tableName()returnsnull(line 220), causing the condition on line 251 (if (tableName && ...)) to short-circuit without checking the predicate. This allows documents from rule-less tables to be returned regardless of the default policy.The condition should be inverted to ensure the predicate is always evaluated. When
tableNameis null, the predicate check will apply the default policy:async get(arg0: any, arg1?: any): Promise<any> { const [tableName, id]: [string | null, GenericId<string>] = arg1 !== undefined ? [arg0, arg1] : [this.tableName(arg0), arg0]; const doc = await this.db.get(id); if (doc) { - if (tableName && !(await this.predicate(tableName, doc))) { + if (tableName === null || !(await this.predicate(tableName!, doc))) { return null; } return doc; } return null; }The non-null assertion (
tableName!) is safe here because the predicate's optional chaining (this.rules[tableName]?.read) handles any string value, including those not in the rules object, applying the default policy accordingly.
🧹 Nitpick comments (1)
packages/convex-helpers/server/rowLevelSecurity.ts (1)
427-428: Type placement is fine but consider adding a brief doc comment.TypeScript hoists type declarations, so this works correctly. A short JSDoc explaining the purpose of
NonUnionwould help maintainers:+/** + * Prevents TypeScript from distributing over union types in overload resolution. + */ type NonUnion<T> = T extends never ? never : T;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/convex-helpers/server/rowLevelSecurity.test.ts(3 hunks)packages/convex-helpers/server/rowLevelSecurity.ts(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
When modifying complex TypeScript types, run
npm run typecheckin the repository root to ensure types are correct, rather than runningtscmanually
Files:
packages/convex-helpers/server/rowLevelSecurity.test.tspackages/convex-helpers/server/rowLevelSecurity.ts
🔇 Additional comments (5)
packages/convex-helpers/server/rowLevelSecurity.test.ts (2)
87-141: LGTM! Well-structured test reorganization.The describe block cleanly separates implicit and explicit table name API tests. The use of
@ts-expect-erroris appropriate here since TypeScript doesn't yet know about the 2-argument overload fordelete, but you're intentionally testing that new API path.
279-391: LGTM! Good coverage for both policy modes.The tests comprehensively verify default allow and default deny policies for both implicit and explicit table name variants of
patch. The@ts-expect-errorannotations correctly document that the 3-argumentpatchAPI is being exercised.packages/convex-helpers/server/rowLevelSecurity.ts (3)
335-356: LGTM!checkAuthcorrectly handles both explicit and inferred table names.The updated logic properly prioritizes the explicitly provided
tableNameArgwhen available, falling back to inference viathis.tableName(id)only when needed.
358-375: LGTM! Overload pattern is correct.The 3-argument vs 2-argument disambiguation via
arg2 !== undefinedis sound. The@ts-expect-errorcomment appropriately documents the version dependency on [email protected].
396-410:checkAuthis called with explicit table name but the same potential issue exists.Similar to the
getmethod inWrapReader, iftableNameisnullwhen using the single-argument delete form, thecheckAuthmethod will callthis.get(id)(line 345), which has the same potential bypass issue noted earlier. The fix toWrapReader.getwould address this as well.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.