security(grm): restrict GRM automation rules to GRM staff (drop portal write/create)#266
security(grm): restrict GRM automation rules to GRM staff (drop portal write/create)#266gonzalesedwin1123 wants to merge 1 commit into
Conversation
The ACL granted base.group_portal read/write/create on spp.grm.routing.rule and spp.grm.escalation.rule. These are global config models with no record rules, so a portal user could create an always-matching routing/escalation rule via RPC. Routing rules run on ticket creation and escalation rules run on stage changes and via the hourly cron over all open tickets (elevated), so a single planted rule could reassign/escalate/notify across all grievances. Reduce the two portal rows to read-only (1,0,0,0), matching the base.group_user rows. Rule evaluation runs as the current user and only needs read, so ticket routing still works; portal users can no longer create or modify global rules. GRM officers/managers retain full management. Add regression tests: portal users are denied create/write on both rule models but retain read, while a GRM manager can still create both.
There was a problem hiding this comment.
Code Review
This pull request restricts portal users to read-only access for GRM routing and escalation rules by updating the ACL configurations in ir.model.access.csv. It also introduces a comprehensive suite of integration tests in test_rule_acl.py to verify these access control constraints. There are no review comments, and I have no additional feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 19.0 #266 +/- ##
========================================
Coverage 75.31% 75.31%
========================================
Files 1098 1104 +6
Lines 65317 65586 +269
========================================
+ Hits 49191 49398 +207
- Misses 16126 16188 +62
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Problem
spp_grm_cel/security/ir.model.access.csvgrantedbase.group_portalread + write + create(
1,1,1,0) on the global config modelsspp.grm.routing.ruleandspp.grm.escalation.rule,with no
ir.rulerecord rules scoping them. A low-privileged portal user could thereforecreate an always-matching routing or escalation rule via RPC:
team_id,user_id,severity,priority.(executed elevated), and can reassign/escalate, send configured notifications, and create
cases.
So a single planted rule turns portal access into unauthorized, global GRM workflow
modification and potential mass disruption of grievance handling. Severity: High.
Fix
Reduce the two portal ACL rows to read-only (
1,0,0,0), matching the existingbase.group_userrows:Rule evaluation runs as the current user (
ticket.create()→apply_routing()→search()on the rule model), so read access must be retained or routing silently stopsapplying — exactly why
base.group_useralso has read-only. Portal users lose the ability tocreate or modify global rules; GRM officers/managers retain full management.
Portal ticket submission via the controller is already
sudo()d(
spp_grm/controllers/grm_portal.py), so that flow is unaffected either way.Tests
New
spp_grm_cel/tests/test_rule_acl.py:AccessError);AccessError);Written test-first (4 denial tests failed pre-fix — confirming portal could create/write —
then passed after).
./spp test spp_grm_cel→ 35 passed, 0 failed;./spp lintclean.Out of scope (noted for awareness)
spp_grmgrants portal1,1,1,0onspp.grm.ticketitself (portal can create tickets viaRPC, not only via the sudo controller) — separate question, not changed here.
apply_escalationwritesescalation_countwithoutsudo()(unlike routing's sudo'dcounter) — a pre-existing inconsistency; escalation triggered by a read-only portal user now
fails closed (caught/logged), which is the intended behavior.