Skip to content

Commit cc11557

Browse files
committed
fix(spp_security): gate Apps menu via post_init_hook, not XML record override
Move the base.menu_management group_ids write out of groups_admin.xml and into a new _gate_apps_menu function called from post_init_hook. XML record overrides for cross-module Many2many fields are unreliable: the override can be wiped when the owning module (base) gets upgraded, silently reverting our gating. Hooks are idempotent and re-apply on every spp_security install/upgrade, which is the same pattern this module already uses to wire spp_security.group_spp_admin into base.group_system.implied_ids. No behavior change in steady state — the hook produces the same effect as the XML record did, just more robustly.
1 parent 8ce0cd4 commit cc11557

3 files changed

Lines changed: 39 additions & 11 deletions

File tree

spp_security/hooks.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def post_init_hook(env_or_cr, registry=None):
3131
env = env_or_cr
3232

3333
_setup_admin_group_inheritance(env)
34+
_gate_apps_menu(env)
3435

3536

3637
def _setup_admin_group_inheritance(env):
@@ -63,3 +64,33 @@ def _setup_admin_group_inheritance(env):
6364

6465
except Exception as e:
6566
_logger.warning("Failed to set up admin group inheritance: %s", str(e))
67+
68+
69+
def _gate_apps_menu(env):
70+
"""
71+
Restrict the "Apps" top-level menu (base.menu_management) to base.group_system.
72+
73+
Out of the box this menuitem has no `groups` attribute, so every logged-in
74+
user sees it. Per the OP#951 role/menu audit only System Admin should see
75+
Apps; everyone else should not. base.group_system is the only group System
76+
Admin pulls in transitively (via spp_user_roles.global_role_admin), so a
77+
single Many2many write here enforces the audit for every role.
78+
79+
Idempotent — re-applies on every install/upgrade of spp_security. Uses a
80+
hook rather than a `<record id="base.menu_management">` XML override
81+
because cross-module Many2many writes via data XML can be wiped on
82+
subsequent base-module upgrades.
83+
"""
84+
try:
85+
apps_menu = env.ref("base.menu_management", raise_if_not_found=False)
86+
system_admin = env.ref("base.group_system", raise_if_not_found=False)
87+
if not apps_menu or not system_admin:
88+
_logger.warning("Could not gate Apps menu: base.menu_management or base.group_system not found")
89+
return
90+
if apps_menu.group_ids == system_admin:
91+
_logger.debug("Apps menu gating already configured")
92+
return
93+
apps_menu.write({"group_ids": [(6, 0, [system_admin.id])]})
94+
_logger.info("Gated Apps menu (base.menu_management) on base.group_system")
95+
except Exception as e:
96+
_logger.warning("Failed to gate Apps menu: %s", str(e))

spp_security/readme/HISTORY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
### 19.0.2.0.1
22

3-
- fix(security): gate the Odoo-stock **Apps** top-level menu (`base.menu_management`) on `base.group_system`. Out of the box the menu had no `groups` restriction and was visible to every logged-in user, so the OP#951 audit's `Apps: no` rows were silently violated. System Admin is the only OpenSPP role that pulls in `base.group_system`, so this single override hides Apps from every other role without touching any individual role definition.
3+
- fix(security): gate the Odoo-stock **Apps** top-level menu (`base.menu_management`) on `base.group_system` via a new `_gate_apps_menu` hook called from `post_init_hook`. Out of the box the menu had no `groups` restriction and was visible to every logged-in user, so the OP#951 audit's `Apps: no` rows were silently violated. System Admin is the only OpenSPP role that pulls in `base.group_system`, so this single Many2many write hides Apps from every other role without touching any individual role definition. Hook is idempotent and re-applies on every install/upgrade.
44

55
### 19.0.2.0.0
66

spp_security/security/groups_admin.xml

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,14 @@ Used for field agents and limited-access users.</field>
4040
</record>
4141

4242
<!--
43-
Gate the "Apps" top-level menu on base.group_system. Out of the box
44-
the Apps root menuitem has no `groups` attribute, so every logged-in
45-
user can see (but not click into) it. Per the OP#951 role/menu audit
46-
only System Admin should see Apps; everyone else gets `Apps no`.
47-
Restricting the menu to base.group_system enforces the audit without
48-
touching individual roles (System Admin is the only role that pulls
49-
in base.group_system).
43+
Note: the "Apps" top-level menu (base.menu_management) is gated on
44+
base.group_system at install / upgrade time by the post_init_hook
45+
(see hooks.py:_gate_apps_menu). A hook is used instead of an
46+
`<record id="base.menu_management" ...>` override because the XML
47+
override is unreliable for cross-module Many2many writes (it can
48+
be wiped on subsequent base-module upgrades). The hook idempotently
49+
re-applies the gating on every install/upgrade of spp_security.
5050
-->
51-
<record id="base.menu_management" model="ir.ui.menu">
52-
<field name="group_ids" eval="[Command.set([ref('base.group_system')])]" />
53-
</record>
5451

5552
<!--
5653
How domain modules extend this:

0 commit comments

Comments
 (0)