fix(policy): extra fields included for policy evaluation should be dropped upon return#2286
fix(policy): extra fields included for policy evaluation should be dropped upon return#2286
Conversation
📝 WalkthroughWalkthroughThis pull request resolves issue #2283 by enhancing field-level policy handling in policy-utils to respect select/include directives and queryArgs.omit when removing unreadable fields from query results. It also extends test infrastructure to support database file injection and adds a regression test with complex nested access policies. Changes
Sequence Diagram(s)sequenceDiagram
participant Query as Query Executor
participant PolicyUtil as Policy Utils
participant PostProc as Post-Processing
participant Result as Query Result
Query->>PolicyUtil: Execute query with select/include
PolicyUtil->>PolicyUtil: Apply access policy rules
PolicyUtil->>Result: Fetch data with extra policy fields
Result->>PostProc: Pass result to post-processing
PostProc->>PostProc: Check queryArgs.omit
PostProc->>PostProc: Verify select/include for each field
alt Field selected/included or required for policy
PostProc->>Result: Keep field
else Field not in select/include or omitted
PostProc->>Result: Remove field
end
PostProc->>Query: Return cleaned result matching select/include
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
packages/testtools/src/schema.ts (2)
153-154: Document and scopedbFileusage (sqlite-only)
Add a brief JSDoc and clarify it’s intended for sqlite schemas; consider validating provider to avoid silent misuse.export type SchemaLoadOptions = { + /** + * Pre-seeded SQLite database file to copy into prisma/dev.db for tests. + * Only applies when provider === 'sqlite'. Ignored otherwise. + */ dbFile?: string; };
341-344: Harden db file copy: mkdir, safe join, overwrite, existence check
Create target dir before copy, use path.join with segments, force overwrite, and provide a clearer error if the source is missing. Also optionally no-op or warn when provider !== 'sqlite’.- if (opt.dbFile) { - fs.cpSync(opt.dbFile, path.join(projectDir, 'prisma/dev.db')); - } + if (opt.dbFile) { + if (!fs.existsSync(opt.dbFile)) { + throw new Error(`dbFile not found: ${opt.dbFile}`); + } + const destDb = path.join(projectDir, 'prisma', 'dev.db'); + fs.mkdirSync(path.dirname(destDb), { recursive: true }); + fs.cpSync(opt.dbFile, destDb, { force: true }); + } else if (opt.pushDb) { run('npx prisma db push --skip-generate --accept-data-loss'); }Optional provider guard (if desired):
- if (opt.dbFile) { + if (opt.dbFile) { + if (opt.provider !== 'sqlite') { + console.warn('SchemaLoadOptions.dbFile is only used for sqlite; skipping copy.'); + } else { + // copy as above + } }packages/runtime/src/enhancements/node/policy/policy-utils.ts (1)
1531-1535: Avoid accidental relation drops when both select and include are present; dedupe pruning logic
- If both select and include appear (edge cases / future changes), the relation prune should not drop a field that’s explicitly selected. Add a select guard.
- The selection/inclusion pruning runs both here and again under hasFieldLevelPolicy, causing duplicate checks. Consider consolidating to a single pruning step, then run readability checks.
- if (fieldInfo.isDataModel && queryArgs?.include && typeof queryArgs.include === 'object' && !queryArgs.include[field]) { + if ( + fieldInfo.isDataModel && + queryArgs?.include && + typeof queryArgs.include === 'object' && + !queryArgs.include[field] && + !(queryArgs?.select && queryArgs.select[field]) + ) { // respect include delete entityData[field]; continue; }Optional cleanup: remove the duplicated select/include deletion inside the
hasFieldLevelPolicyblock and keep only readability checks there.Also applies to: 1537-1542, 1543-1548
tests/regression/tests/issue-2283/regression.test.ts (2)
6-7: Close Prisma client to avoid open handles in tests
Call$disconnect()after the test to prevent lingering handles/timeouts.- const { enhance } = await loadSchema( + const { enhance, prisma } = await loadSchema( ` ... `, { dbFile: path.join(__dirname, 'dev.db'), } ); @@ - const db = enhance(); + const db = enhance(); + try { + // test body... + } finally { + await db.$disconnect?.(); + await prisma.$disconnect?.(); + }Also applies to: 636-639
681-682: Strengthen the assertion across all returned classes
Ensure no class leaks themodulerelation when it wasn’t selected.- expect(r.lab.content[0].modules[0].classes[0].module).toBeUndefined(); + for (const c of r.lab.content.flatMap((co) => co.modules).flatMap((m) => m.classes)) { + expect(c.module).toBeUndefined(); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
tests/regression/tests/issue-2283/dev.dbis excluded by!**/*.db,!**/*.db
📒 Files selected for processing (3)
packages/runtime/src/enhancements/node/policy/policy-utils.ts(1 hunks)packages/testtools/src/schema.ts(2 hunks)tests/regression/tests/issue-2283/regression.test.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
tests/regression/tests/issue-2283/regression.test.ts (1)
packages/testtools/src/schema.ts (1)
loadSchema(173-249)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-test (20.x)
- GitHub Check: OSSAR-Scan
- GitHub Check: build-test (20.x)
- GitHub Check: build-test (20.x)
- GitHub Check: dependency-review
fixes #2283