Force strict equivalence in mongo role checks#834
Conversation
📝 WalkthroughWalkthroughThe MongoDB adapter's permission-filtering methods undergo regex pattern refinement. The Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/Database/Adapter/Mongo.php`:
- Line 2029: The permission regex is built from raw role strings so
metacharacters in roles can break matching; update the code that builds $roles
(used in new Regex("{$forPermission}\\(\"(?:{$roles})\"\\)", 'i')) to escape
each role with preg_quote (specifying the regex delimiter, e.g., '/') before
imploding with '|' (e.g., $roles = implode('|', array_map(fn($r) =>
preg_quote($r, '/'), $this->authorization->getRoles()))), and apply the same
change in the count() and sum() branches where the identical Regex construction
occurs so all three usages (find/count/sum) use escaped role values.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fe44fb97-3b41-4dfa-9118-e8a23ca61ff2
📒 Files selected for processing (1)
src/Database/Adapter/Mongo.php
| if ($this->authorization->getStatus()) { | ||
| $roles = \implode('|', $this->authorization->getRoles()); | ||
| $filters['_permissions']['$in'] = [new Regex("{$forPermission}\\(\".*(?:{$roles}).*\"\\)", 'i')]; | ||
| $filters['_permissions']['$in'] = [new Regex("{$forPermission}\\(\"(?:{$roles})\"\\)", 'i')]; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the exact code at the three mentioned lines
sed -n '2025,2035p' src/Database/Adapter/Mongo.phpRepository: utopia-php/database
Length of output: 1882
🏁 Script executed:
# Check lines 2290 and 2380
sed -n '2285,2295p' src/Database/Adapter/Mongo.php
sed -n '2375,2385p' src/Database/Adapter/Mongo.phpRepository: utopia-php/database
Length of output: 1882
🏁 Script executed:
# Check the Permission and Role helper classes to understand toString() behavior
cat src/Database/Helpers/Permission.phpRepository: utopia-php/database
Length of output: 7107
🏁 Script executed:
# Check Role.php
cat src/Database/Helpers/Role.phpRepository: utopia-php/database
Length of output: 4142
🏁 Script executed:
# Search for how getRoles() is implemented to understand what values it returns
rg -A 5 "function getRoles" src/Repository: utopia-php/database
Length of output: 409
Escape role values before interpolating them into these permission regexes.
This is not a strict-equivalence check. Permission::toString() stores permission("role") strings where the role contains identifiers and dimensions appended verbatim (e.g., user:identifier/dimension). Since getRoles() returns raw role strings and the regex is built via implode('|', $this->authorization->getRoles()) without escaping, any regex metacharacters in identifiers or dimensions will be interpreted as regex syntax rather than literal characters. This causes over-matching or under-matching in find(), count(), and sum().
🔧 Suggested fix
- $roles = \implode('|', $this->authorization->getRoles());
- $filters['_permissions']['$in'] = [new Regex("{$forPermission}\\(\"(?:{$roles})\"\\)", 'i')];
+ $roles = \implode('|', \array_map(
+ static fn (string $role): string => \preg_quote($role, '/'),
+ $this->authorization->getRoles()
+ ));
+ $permission = \preg_quote($forPermission, '/');
+ $filters['_permissions']['$in'] = [new Regex("{$permission}\\(\"(?:{$roles})\"\\)", 'i')];Apply the same escaping in the count() and sum() branches as well.
Also applies to: 2290–2290, 2380–2380
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/Database/Adapter/Mongo.php` at line 2029, The permission regex is built
from raw role strings so metacharacters in roles can break matching; update the
code that builds $roles (used in new
Regex("{$forPermission}\\(\"(?:{$roles})\"\\)", 'i')) to escape each role with
preg_quote (specifying the regex delimiter, e.g., '/') before imploding with '|'
(e.g., $roles = implode('|', array_map(fn($r) => preg_quote($r, '/'),
$this->authorization->getRoles()))), and apply the same change in the count()
and sum() branches where the identical Regex construction occurs so all three
usages (find/count/sum) use escaped role values.
Summary by CodeRabbit