Skip to content
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

fix: support check() policy function call in permission checkers #1820

Merged
merged 1 commit into from
Oct 30, 2024

Conversation

ymc9
Copy link
Member

@ymc9 ymc9 commented Oct 30, 2024

fixes #1612

Copy link
Contributor

coderabbitai bot commented Oct 30, 2024

📝 Walkthrough

Walkthrough

The pull request introduces significant enhancements to authorization checks and constraints within the policy management system. Key modifications include the addition of new types and methods to handle delegated constraints, improved error handling, and expanded test coverage for permission checks. The changes primarily affect the policy-utils.ts, types.ts, and constraint-transformer.ts files, ensuring a more robust and flexible policy enforcement mechanism that accommodates complex relationships and delegated permissions.

Changes

File Path Change Summary
packages/runtime/src/enhancements/node/policy/policy-utils.ts - Added import for traverse library.
- Expanded type imports to include DelegateConstraint and VariableConstraint.
- Modified getCheckerConstraint method to handle delegated constraints.
- Enhanced error handling in deniedByPolicy method.
packages/runtime/src/enhancements/node/types.ts - Added new type CRUD for CRUD operations.
- Introduced DelegateConstraint type.
- Updated PermissionCheckerConstraint type to include DelegateConstraint.
packages/schema/src/plugins/enhancer/policy/constraint-transformer.ts - Added imports including PluginError, getLiteral, DataModel, InvocationExpr.
- Introduced transformCheckInvocation method.
- Updated transformExpression and transformLiteral methods for better handling of check() invocations.
tests/integration/tests/enhancements/with-policy/checker.test.ts - Added new tests for permission checking with policy delegation.
- Renamed existing test for clarity.

Assessment against linked issues

Objective Addressed Explanation
Ensure enhance.model.check feature supports check(parent) policy (Issue #1612)

Possibly related PRs


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ymc9 ymc9 marked this pull request as ready for review October 30, 2024 22:34
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (6)
packages/runtime/src/enhancements/node/types.ts (3)

21-24: Enhance JSDoc documentation for the CRUD type.

The type definition is correct, but consider expanding the documentation to describe the purpose and usage of this type in the context of permission checking.

 /**
- * CRUD operations
+ * Represents the standard CRUD (Create, Read, Update, Delete) operations
+ * that can be performed on a model. This type is used in permission
+ * checking to specify which operation is being delegated.
  */
 export type CRUD = 'create' | 'read' | 'update' | 'delete';

82-91: Enhance documentation for DelegateConstraint type.

The type definition correctly implements the delegation mechanism needed for check(parent) policy support. Consider enhancing the documentation with an example.

 /**
  * Constraint delegated to another model through `check()` function call
  * on a relation field.
+ *
+ * @example
+ * // In a policy definition:
+ * check(parent) // Delegates to parent model's policy
+ * check(owner, 'read') // Delegates read operation to owner model's policy
  */
 export type DelegateConstraint = {
     kind: 'delegate';
     model: string;
     relation: string;
     operation?: CRUD;
 };

93-101: Improve type union formatting for better readability.

The addition of DelegateConstraint to the union type is correct and necessary.

 export type PermissionCheckerConstraint =
-    | ValueConstraint
-    | VariableConstraint
-    | ComparisonConstraint
-    | LogicalConstraint
-    | DelegateConstraint;
+    | ValueConstraint      // Constant value constraints
+    | VariableConstraint   // Free variable constraints
+    | ComparisonConstraint // Comparison operations
+    | LogicalConstraint    // Logical operations (AND, OR, NOT)
+    | DelegateConstraint;  // Delegated model checks
tests/integration/tests/enhancements/with-policy/checker.test.ts (2)

694-715: Consider expanding test coverage for explicit policy delegation.

While the test verifies the negative case (denial of read operation), it should also verify:

  1. The positive case where read is allowed
  2. Other operations (create, update, delete) with explicit operation checking

Consider adding these test cases:

     it('supports policy delegation explicit', async () => {
         const { enhance } = await load(
             `
             model Foo {
                 id Int @id @default(autoincrement())
                 model Model?
                 @@allow('all', true)
                 @@deny('update', true)
             }

             model Model {
                 id Int @id @default(autoincrement())
                 foo Foo @relation(fields: [fooId], references: [id])
                 fooId Int @unique
                 @@allow('read', check(foo, 'update'))
             }
             `,
             { preserveTsFiles: true }
         );

         await expect(enhance().model.check({ operation: 'read' })).toResolveFalsy();
+        // Test other operations
+        await expect(enhance().model.check({ operation: 'create' })).toResolveFalsy();
+        await expect(enhance().model.check({ operation: 'update' })).toResolveFalsy();
+        await expect(enhance().model.check({ operation: 'delete' })).toResolveFalsy();
+
+        // Test with authenticated user
+        await expect(enhance({ id: 1 }).model.check({ operation: 'read' })).toResolveFalsy();
     });

717-762: LGTM: Comprehensive test for combined policy delegation.

The test effectively covers:

  • Policy delegation with additional conditions (check(foo) && value > 0)
  • Combination of allow and deny rules
  • Various value conditions and authentication states

One minor suggestion: Consider adding a test case for the delete operation to maintain consistency with other test cases.

         await expect(enhance({ id: 1 }).model.check({ operation: 'update', where: { value: 0 } })).toResolveFalsy();
         await expect(enhance({ id: 1 }).model.check({ operation: 'update', where: { value: 1 } })).toResolveFalsy();
+
+        // Test delete operation
+        await expect(enhance().model.check({ operation: 'delete' })).toResolveFalsy();
+        await expect(enhance({ id: 1 }).model.check({ operation: 'delete', where: { value: 1 } })).toResolveTruthy();
+        await expect(enhance({ id: 1 }).model.check({ operation: 'delete', where: { value: 0 } })).toResolveFalsy();
     });
packages/runtime/src/enhancements/node/policy/policy-utils.ts (1)

709-709: Consider refactoring to avoid disabling ESLint's no-this-alias rule

Currently, const that = this; is used along with an ESLint disable comment to alias this. You can refactor the code to eliminate the need for that and the ESLint override. Since the traverse library provides a context where this refers to the traversal context, consider using a different approach to access the outer this, such as passing it as an argument or leveraging closures.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between daa3839 and 9de02ea.

📒 Files selected for processing (4)
  • packages/runtime/src/enhancements/node/policy/policy-utils.ts (3 hunks)
  • packages/runtime/src/enhancements/node/types.ts (2 hunks)
  • packages/schema/src/plugins/enhancer/policy/constraint-transformer.ts (5 hunks)
  • tests/integration/tests/enhancements/with-policy/checker.test.ts (2 hunks)
🔇 Additional comments (3)
packages/runtime/src/enhancements/node/types.ts (1)

Line range hint 21-101: Verify type usage across the codebase.

Let's ensure the new types are properly imported and used in related files.

✅ Verification successful

Let me analyze the usage of these types with one more verification to ensure proper integration:


Based on the analysis of the code, I can now provide a final response:

Types are properly integrated and used across the codebase

The verification shows proper integration:

  1. The DelegateConstraint type is correctly used in:

    • packages/schema/src/plugins/enhancer/policy/constraint-transformer.ts for transforming policy constraints
    • packages/runtime/src/enhancements/node/policy/policy-utils.ts for policy enforcement
  2. The CRUD type is properly used throughout the codebase for:

    • Policy definitions and operations
    • Permission checking
    • API handlers across different frameworks (Express, Fastify, Next.js, SvelteKit)

The types are well-integrated into the policy enforcement system and are used consistently across the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check imports of the new types
echo "Checking imports of new types..."
rg -l "import.*(?:CRUD|DelegateConstraint).*from.*types"

# Check usage of DelegateConstraint
echo -e "\nChecking DelegateConstraint usage..."
rg "kind:\s*['\"]delegate['\"]" --type ts

# Check for potential missed imports
echo -e "\nChecking for potential missed imports..."
rg "(?:CRUD|DelegateConstraint)" --type ts

Length of output: 4354


Script:

#!/bin/bash
# Check the implementation in constraint-transformer.ts to verify proper type usage
echo "Checking constraint-transformer.ts implementation..."
cat packages/schema/src/plugins/enhancer/policy/constraint-transformer.ts

# Check policy-utils.ts to verify proper imports and type usage
echo -e "\nChecking policy-utils.ts implementation..."
cat packages/runtime/src/enhancements/node/policy/policy-utils.ts

Length of output: 75188

tests/integration/tests/enhancements/with-policy/checker.test.ts (2)

360-360: LGTM: Improved test name clarity.

The rename from "unsolvable" to "unsatisfiable" better reflects the mathematical terminology used in constraint satisfaction problems.


653-692: LGTM: Well-structured test for basic policy delegation.

The test effectively covers:

  • Policy delegation from Model to Foo using check(foo)
  • Permission inheritance for read, create, and update operations
  • Proper authentication checks through the relationship chain

@ymc9 ymc9 merged commit be28f2e into dev Oct 30, 2024
13 checks passed
@ymc9 ymc9 deleted the fix/check-in-check branch October 30, 2024 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant