Skip to content

Commit f386737

Browse files
security(cr): add record rules to CR detail models (ownership + area) (#261)
Reviewed head: c3f97fc
1 parent d03e810 commit f386737

15 files changed

Lines changed: 1626 additions & 35 deletions

File tree

‎spp_change_request_v2/README.rst‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,22 @@ Before declaring a new CR type complete:
853853
Changelog
854854
=========
855855

856+
19.0.3.1.3
857+
~~~~~~~~~~
858+
859+
- fix(security): add ownership and area record rules to every concrete
860+
change-request detail model. Detail rows were reachable by any
861+
``group_cr_user`` regardless of who owned the parent change request,
862+
so a requester could read or tamper with another user's detail data
863+
over RPC. Each detail model now carries
864+
user/validator/validator-HQ/manager rules scoped through its parent
865+
change request, plus a global rule mirroring the parent's area filter.
866+
``spp.cr.detail.split_household.member`` is additionally scoped on
867+
delete, the one detail model whose access-control entry grants
868+
``unlink`` to change-request users: requesters may delete member rows
869+
only on their own requests, while validators and managers keep the
870+
unrestricted delete their access-control entries grant.
871+
856872
19.0.3.1.2
857873
~~~~~~~~~~
858874

‎spp_change_request_v2/__manifest__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "OpenSPP Change Request V2",
3-
"version": "19.0.3.1.2",
3+
"version": "19.0.3.1.3",
44
"sequence": 50,
55
"category": "OpenSPP",
66
"summary": "Configuration-driven change request system with UX improvements, conflict detection and duplicate prevention",

‎spp_change_request_v2/readme/HISTORY.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### 19.0.3.1.3
2+
3+
- fix(security): add ownership and area record rules to every concrete change-request detail model. Detail rows were reachable by any `group_cr_user` regardless of who owned the parent change request, so a requester could read or tamper with another user's detail data over RPC. Each detail model now carries user/validator/validator-HQ/manager rules scoped through its parent change request, plus a global rule mirroring the parent's area filter. `spp.cr.detail.split_household.member` is additionally scoped on delete, the one detail model whose access-control entry grants `unlink` to change-request users: requesters may delete member rows only on their own requests, while validators and managers keep the unrestricted delete their access-control entries grant.
4+
15
### 19.0.3.1.2
26

37
- fix(security): route and apply the same single field for dynamic-approval change requests, and freeze the proposed change once the request leaves draft. The selected field, its old/new values and the detail pointer were writable after submission, so a requester could re-route an approval or alter the value that had already been approved. Note the mapped-source-field freeze applies to `field_mapping` request types; `custom`-strategy types freeze only the routing selector.

‎spp_change_request_v2/security/area_filter_rules.xml‎

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,271 @@ can be referenced without defensive guards.
3131
<field name="perm_create" eval="True" />
3232
<field name="perm_unlink" eval="True" />
3333
</record>
34+
35+
<!--
36+
Mirror the parent CR area filter onto each detail model. Detail models
37+
are separate tables and do NOT inherit the parent's global area rule, so
38+
without these an area-scoped officer could reach (via RPC) detail rows of
39+
change requests whose registrant is outside their center area, even though
40+
the parent CR is hidden. Global rule (no groups) so it ANDs with the
41+
ownership rules; users without center areas are unaffected (empty domain).
42+
-->
43+
44+
<record id="rule_cr_detail_add_member_area_filter" model="ir.rule">
45+
<field
46+
name="name"
47+
>CR Detail (add_member): visible only within user's center areas</field>
48+
<field name="model_id" ref="model_spp_cr_detail_add_member" />
49+
<field
50+
name="domain_force"
51+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
52+
<field name="global" eval="True" />
53+
<field name="perm_read" eval="True" />
54+
<field name="perm_write" eval="True" />
55+
<field name="perm_create" eval="True" />
56+
<field name="perm_unlink" eval="True" />
57+
</record>
58+
59+
<record id="rule_cr_detail_edit_individual_area_filter" model="ir.rule">
60+
<field
61+
name="name"
62+
>CR Detail (edit_individual): visible only within user's center areas</field>
63+
<field name="model_id" ref="model_spp_cr_detail_edit_individual" />
64+
<field
65+
name="domain_force"
66+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
67+
<field name="global" eval="True" />
68+
<field name="perm_read" eval="True" />
69+
<field name="perm_write" eval="True" />
70+
<field name="perm_create" eval="True" />
71+
<field name="perm_unlink" eval="True" />
72+
</record>
73+
74+
<record id="rule_cr_detail_edit_group_area_filter" model="ir.rule">
75+
<field
76+
name="name"
77+
>CR Detail (edit_group): visible only within user's center areas</field>
78+
<field name="model_id" ref="model_spp_cr_detail_edit_group" />
79+
<field
80+
name="domain_force"
81+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
82+
<field name="global" eval="True" />
83+
<field name="perm_read" eval="True" />
84+
<field name="perm_write" eval="True" />
85+
<field name="perm_create" eval="True" />
86+
<field name="perm_unlink" eval="True" />
87+
</record>
88+
89+
<record id="rule_cr_detail_remove_member_area_filter" model="ir.rule">
90+
<field
91+
name="name"
92+
>CR Detail (remove_member): visible only within user's center areas</field>
93+
<field name="model_id" ref="model_spp_cr_detail_remove_member" />
94+
<field
95+
name="domain_force"
96+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
97+
<field name="global" eval="True" />
98+
<field name="perm_read" eval="True" />
99+
<field name="perm_write" eval="True" />
100+
<field name="perm_create" eval="True" />
101+
<field name="perm_unlink" eval="True" />
102+
</record>
103+
104+
<record id="rule_cr_detail_change_hoh_area_filter" model="ir.rule">
105+
<field
106+
name="name"
107+
>CR Detail (change_hoh): visible only within user's center areas</field>
108+
<field name="model_id" ref="model_spp_cr_detail_change_hoh" />
109+
<field
110+
name="domain_force"
111+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
112+
<field name="global" eval="True" />
113+
<field name="perm_read" eval="True" />
114+
<field name="perm_write" eval="True" />
115+
<field name="perm_create" eval="True" />
116+
<field name="perm_unlink" eval="True" />
117+
</record>
118+
119+
<record id="rule_cr_detail_exit_registrant_area_filter" model="ir.rule">
120+
<field
121+
name="name"
122+
>CR Detail (exit_registrant): visible only within user's center areas</field>
123+
<field name="model_id" ref="model_spp_cr_detail_exit_registrant" />
124+
<field
125+
name="domain_force"
126+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
127+
<field name="global" eval="True" />
128+
<field name="perm_read" eval="True" />
129+
<field name="perm_write" eval="True" />
130+
<field name="perm_create" eval="True" />
131+
<field name="perm_unlink" eval="True" />
132+
</record>
133+
134+
<record id="rule_cr_detail_transfer_member_area_filter" model="ir.rule">
135+
<field
136+
name="name"
137+
>CR Detail (transfer_member): visible only within user's center areas</field>
138+
<field name="model_id" ref="model_spp_cr_detail_transfer_member" />
139+
<field
140+
name="domain_force"
141+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
142+
<field name="global" eval="True" />
143+
<field name="perm_read" eval="True" />
144+
<field name="perm_write" eval="True" />
145+
<field name="perm_create" eval="True" />
146+
<field name="perm_unlink" eval="True" />
147+
</record>
148+
149+
<record id="rule_cr_detail_update_id_area_filter" model="ir.rule">
150+
<field
151+
name="name"
152+
>CR Detail (update_id): visible only within user's center areas</field>
153+
<field name="model_id" ref="model_spp_cr_detail_update_id" />
154+
<field
155+
name="domain_force"
156+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
157+
<field name="global" eval="True" />
158+
<field name="perm_read" eval="True" />
159+
<field name="perm_write" eval="True" />
160+
<field name="perm_create" eval="True" />
161+
<field name="perm_unlink" eval="True" />
162+
</record>
163+
164+
<record id="rule_cr_detail_create_group_area_filter" model="ir.rule">
165+
<field
166+
name="name"
167+
>CR Detail (create_group): visible only within user's center areas</field>
168+
<field name="model_id" ref="model_spp_cr_detail_create_group" />
169+
<field
170+
name="domain_force"
171+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
172+
<field name="global" eval="True" />
173+
<field name="perm_read" eval="True" />
174+
<field name="perm_write" eval="True" />
175+
<field name="perm_create" eval="True" />
176+
<field name="perm_unlink" eval="True" />
177+
</record>
178+
179+
<record id="rule_cr_detail_merge_registrants_area_filter" model="ir.rule">
180+
<field
181+
name="name"
182+
>CR Detail (merge_registrants): visible only within user's center areas</field>
183+
<field name="model_id" ref="model_spp_cr_detail_merge_registrants" />
184+
<field
185+
name="domain_force"
186+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
187+
<field name="global" eval="True" />
188+
<field name="perm_read" eval="True" />
189+
<field name="perm_write" eval="True" />
190+
<field name="perm_create" eval="True" />
191+
<field name="perm_unlink" eval="True" />
192+
</record>
193+
194+
<record id="rule_cr_detail_split_household_area_filter" model="ir.rule">
195+
<field
196+
name="name"
197+
>CR Detail (split_household): visible only within user's center areas</field>
198+
<field name="model_id" ref="model_spp_cr_detail_split_household" />
199+
<field
200+
name="domain_force"
201+
>[('change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
202+
<field name="global" eval="True" />
203+
<field name="perm_read" eval="True" />
204+
<field name="perm_write" eval="True" />
205+
<field name="perm_create" eval="True" />
206+
<field name="perm_unlink" eval="True" />
207+
</record>
208+
209+
<record id="rule_cr_detail_split_household_member_area_filter" model="ir.rule">
210+
<field
211+
name="name"
212+
>CR Detail (split_household.member): visible only within user's center areas</field>
213+
<field name="model_id" ref="model_spp_cr_detail_split_household_member" />
214+
<field
215+
name="domain_force"
216+
>[('detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
217+
<field name="global" eval="True" />
218+
<field name="perm_read" eval="True" />
219+
<field name="perm_write" eval="True" />
220+
<field name="perm_create" eval="True" />
221+
<field name="perm_unlink" eval="True" />
222+
</record>
223+
224+
<record
225+
id="rule_cr_detail_create_group_member_existing_area_filter"
226+
model="ir.rule"
227+
>
228+
<field
229+
name="name"
230+
>CR Detail (create_group.member_existing): visible only within user's center areas</field>
231+
<field name="model_id" ref="model_spp_cr_detail_create_group_member_existing" />
232+
<field
233+
name="domain_force"
234+
>[('detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
235+
<field name="global" eval="True" />
236+
<field name="perm_read" eval="True" />
237+
<field name="perm_write" eval="True" />
238+
<field name="perm_create" eval="True" />
239+
<field name="perm_unlink" eval="True" />
240+
</record>
241+
242+
<record id="rule_cr_detail_create_group_member_new_area_filter" model="ir.rule">
243+
<field
244+
name="name"
245+
>CR Detail (create_group.member_new): visible only within user's center areas</field>
246+
<field name="model_id" ref="model_spp_cr_detail_create_group_member_new" />
247+
<field
248+
name="domain_force"
249+
>[('detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
250+
<field name="global" eval="True" />
251+
<field name="perm_read" eval="True" />
252+
<field name="perm_write" eval="True" />
253+
<field name="perm_create" eval="True" />
254+
<field name="perm_unlink" eval="True" />
255+
</record>
256+
257+
<record id="rule_cr_detail_create_group_phone_area_filter" model="ir.rule">
258+
<field
259+
name="name"
260+
>CR Detail (create_group.phone): visible only within user's center areas</field>
261+
<field name="model_id" ref="model_spp_cr_detail_create_group_phone" />
262+
<field
263+
name="domain_force"
264+
>['|', '|', '|', ('detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('add_member_detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('member_new_id.detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('split_household_detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
265+
<field name="global" eval="True" />
266+
<field name="perm_read" eval="True" />
267+
<field name="perm_write" eval="True" />
268+
<field name="perm_create" eval="True" />
269+
<field name="perm_unlink" eval="True" />
270+
</record>
271+
272+
<record id="rule_cr_detail_create_group_bank_area_filter" model="ir.rule">
273+
<field
274+
name="name"
275+
>CR Detail (create_group.bank): visible only within user's center areas</field>
276+
<field name="model_id" ref="model_spp_cr_detail_create_group_bank" />
277+
<field
278+
name="domain_force"
279+
>['|', '|', '|', ('detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('add_member_detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('member_new_id.detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('split_household_detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
280+
<field name="global" eval="True" />
281+
<field name="perm_read" eval="True" />
282+
<field name="perm_write" eval="True" />
283+
<field name="perm_create" eval="True" />
284+
<field name="perm_unlink" eval="True" />
285+
</record>
286+
287+
<record id="rule_cr_detail_create_group_id_doc_area_filter" model="ir.rule">
288+
<field
289+
name="name"
290+
>CR Detail (create_group.id_doc): visible only within user's center areas</field>
291+
<field name="model_id" ref="model_spp_cr_detail_create_group_id_doc" />
292+
<field
293+
name="domain_force"
294+
>['|', '|', ('detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('add_member_detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids), ('split_household_detail_id.change_request_id.registrant_id.area_id', 'child_of', user.center_area_ids.ids)] if user.center_area_ids else []</field>
295+
<field name="global" eval="True" />
296+
<field name="perm_read" eval="True" />
297+
<field name="perm_write" eval="True" />
298+
<field name="perm_create" eval="True" />
299+
<field name="perm_unlink" eval="True" />
300+
</record>
34301
</odoo>

0 commit comments

Comments
 (0)