Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions spp_api_v2/security/compliance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ record_rules: []

menus:
# Root menu - visible to all API V2 users
# Located under Registry > Configuration
# Located under Settings > Registry (OP#1009)
- id: menu_api_v2_root
name: "API V2"
parent: spp_registry.spp_configuration_menu_root
parent: spp_registry.menu_registry_settings_root
groups: [group_api_v2_viewer]

# API Clients submenu
Expand Down
4 changes: 2 additions & 2 deletions spp_api_v2/views/menu.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- API V2 Menu -->
<!-- API V2 Menu — superuser config under Settings > Registry (OP#1009) -->
<menuitem
id="menu_api_v2_root"
name="API V2"
parent="spp_registry.spp_configuration_menu_root"
parent="spp_registry.menu_registry_settings_root"
sequence="50"
groups="spp_api_v2.group_api_v2_viewer"
/>
Expand Down
1 change: 0 additions & 1 deletion spp_farmer_registry/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"data/cel_constants.xml",
"data/config_parameters.xml",
"data/user_roles.xml",
"views/res_config_settings_views.xml",
"views/farm_season_views.xml",
"views/farm_details_views.xml",
"views/farm_activity_views.xml",
Expand Down
1 change: 0 additions & 1 deletion spp_farmer_registry/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
from . import farm_activity
from . import farm_asset
from . import farm
from . import res_config_settings
17 changes: 0 additions & 17 deletions spp_farmer_registry/models/res_config_settings.py

This file was deleted.

23 changes: 0 additions & 23 deletions spp_farmer_registry/views/res_config_settings_views.xml

This file was deleted.

2 changes: 1 addition & 1 deletion spp_import_match/views/import_match_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
id="menu_spp_import_match"
name="Import Match"
action="action_spp_import_match"
parent="spp_registry.spp_configuration_menu_root"
parent="spp_registry.menu_registry_settings_root"
sequence="1000"
groups="spp_security.group_spp_admin"
/>
Expand Down
4 changes: 4 additions & 0 deletions spp_registry/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
# Wizards
"wizard/disable_registrant_view.xml",
# Views - Base
# res_config_settings_views.xml defines menu_registry_settings_root, which
# main_view.xml reparents the Configuration menu under (OP#1009), so it
# must load first.
"views/res_config_settings_views.xml",
"views/main_view.xml",
"views/reg_relationship_view.xml",
"views/reg_id_view.xml",
Expand Down
1 change: 1 addition & 0 deletions spp_registry/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
from . import reg_relationship
from . import registrant
from . import registry_config
from . import res_config_settings
from . import res_users
51 changes: 51 additions & 0 deletions spp_registry/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.

from odoo import fields, models

# Legacy config-parameter keys this toggle keeps in sync. The starter modules'
# controllers still read their own key (spp_farmer_registry reads the first,
# spp_starter_sp_mis reads the second), so the central "Registry Settings"
# toggle writes both — no migration or controller change needed, and neither
# deployment's enforcement breaks.
_LEGACY_KEYS = (
"spp_farmer_registry.registry_admin_only_crud",
"spp_starter.registry_admin_only_crud",
)


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

is_registry_admin_only_crud = fields.Boolean(
"Restrict Registry Create/Edit/Delete to Admin Only",
default=True,
help=(
"Only administrators can add, modify, or remove registrants. "
"Other users can still view all registry data but cannot make changes."
),
)

def get_values(self):
res = super().get_values()
# ir.config_parameter is a global system setting; sudo is the standard
# access pattern for reading it.
icp = self.env["ir.config_parameter"].sudo() # nosemgrep: odoo-sudo-without-context
# A deployment ships only one of the two starter controllers, so at most
# one key is set. Reflect an explicit value if present; otherwise fall
# back to the secure default (True), matching the legacy
# config_parameter default the starters used.
explicit = [v for v in (icp.get_param(key) for key in _LEGACY_KEYS) if v is not False]
res["is_registry_admin_only_crud"] = any(v == "True" for v in explicit) if explicit else True
return res

def set_values(self):
res = super().set_values()
# ir.config_parameter is a global system setting; sudo is the standard
# access pattern for writing it.
icp = self.env["ir.config_parameter"].sudo() # nosemgrep: odoo-sudo-without-context
value = "True" if self.is_registry_admin_only_crud else "False"
# Keep both legacy keys in sync so whichever starter controller is
# installed reads the value the operator set here.
for key in _LEGACY_KEYS:
icp.set_param(key, value)
return res
1 change: 1 addition & 0 deletions spp_registry/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
from . import test_membership_constraints
from . import test_registrant_misc
from . import test_group_aggregation
from . import test_res_config_settings
53 changes: 53 additions & 0 deletions spp_registry/tests/test_res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
"""Tests for the central Registry Settings (OP#1009).

The "Restrict Registry Edits to Admin Only" toggle lives in spp_registry and
keeps both legacy config-parameter keys in sync so whichever starter
controller is installed reads the operator's choice.
"""

from odoo.tests import TransactionCase, tagged

FARMER_KEY = "spp_farmer_registry.registry_admin_only_crud"
SPMIS_KEY = "spp_starter.registry_admin_only_crud"


@tagged("post_install", "-at_install")
class TestRegistryResConfigSettings(TransactionCase):
"""Registry admin-only-CRUD toggle: default + dual-key sync."""

def _icp(self):
return self.env["ir.config_parameter"].sudo()

def _clear_keys(self):
self._icp().search([("key", "in", [FARMER_KEY, SPMIS_KEY])]).unlink()

def test_defaults_true_when_unset(self):
"""With neither legacy key set, the toggle defaults to True (secure)."""
self._clear_keys()
settings = self.env["res.config.settings"].create({})
self.assertTrue(settings.is_registry_admin_only_crud)

def test_set_values_writes_both_keys(self):
"""Saving the toggle writes BOTH legacy keys so either controller reads it."""
settings = self.env["res.config.settings"].create({"is_registry_admin_only_crud": True})
settings.execute()
self.assertEqual(self._icp().get_param(FARMER_KEY), "True")
self.assertEqual(self._icp().get_param(SPMIS_KEY), "True")

settings = self.env["res.config.settings"].create({"is_registry_admin_only_crud": False})
settings.execute()
self.assertEqual(self._icp().get_param(FARMER_KEY), "False")
self.assertEqual(self._icp().get_param(SPMIS_KEY), "False")

def test_get_values_reflects_an_explicit_key(self):
"""An explicit value on either legacy key is reflected in the toggle."""
self._clear_keys()
self._icp().set_param(SPMIS_KEY, "False")
settings = self.env["res.config.settings"].create({})
self.assertFalse(settings.is_registry_admin_only_crud)

self._clear_keys()
self._icp().set_param(FARMER_KEY, "True")
settings = self.env["res.config.settings"].create({})
self.assertTrue(settings.is_registry_admin_only_crud)
9 changes: 8 additions & 1 deletion spp_registry/views/main_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@
groups="spp_security.group_spp_admin,spp_registry.group_registry_manager,spp_registry.group_registry_officer,spp_registry.group_registry_viewer"
/>

<!--
OP#1009: this "Configuration" menu (and every child menu other modules
hang off it) lives under Settings → Registry instead of the Registry app.
Its parent (menu_registry_settings_root) is defined in
res_config_settings_views.xml, which the manifest loads before this file
so the reference resolves.
-->
<menuitem
id="spp_configuration_menu_root"
name="Configuration"
parent="spp_main_menu_root"
parent="menu_registry_settings_root"
sequence="1000"
groups="spp_security.group_spp_admin,spp_registry.group_registry_config_admin"
/>
Expand Down
75 changes: 75 additions & 0 deletions spp_registry/views/res_config_settings_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Registry Settings section in the Settings app (mirrors Programs Settings) -->
<record id="res_config_settings_registry_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.registry</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="10" />
<field name="inherit_id" ref="base.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//form" position="inside">
<app
string="Registry Settings"
name="registry_settings"
logo="/spp_registry/static/description/icon.png"
>
<block title="Registry Access Control" name="registry_access_block">
<setting
string="Restrict Registry Edits to Admin Only"
help="Only administrators can add, modify, or remove registrants.
Other users can still view all registry data but cannot make changes."
>
<field name="is_registry_admin_only_crud" />
</setting>
</block>
</app>
</xpath>
</field>
</record>

<!-- Action that opens the Settings app focused on the Registry section -->
<record id="res_config_settings_menu_registry_action" model="ir.actions.act_window">
<field name="name">Settings</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.config.settings</field>
<field name="view_id" ref="res_config_settings_registry_view_form" />
<field name="view_mode">form</field>
<field name="target">current</field>
<field name="context">{'module': 'registry_settings'}</field>
</record>

<!-- "Registry" group under the Settings app — houses registry settings and
the relocated superuser configuration menus (e.g. API V2). -->
<menuitem
id="menu_registry_settings_root"
name="Registry"
parent="base.menu_administration"
sequence="50"
groups="spp_security.group_spp_admin,spp_registry.group_registry_config_admin"
/>

<menuitem
id="menu_registry_settings_general"
name="General Settings"
parent="menu_registry_settings_root"
sequence="0"
action="res_config_settings_menu_registry_action"
groups="spp_security.group_spp_admin"
/>

<!--
OP#1009: the registry settings + configuration menus now live under the
Odoo Settings app (base.menu_administration), which is otherwise limited
to base.group_system / base.group_erp_manager. Grant the OpenSPP admin
and registry-config-admin groups access to the Settings app so those
personas can actually reach Settings → Registry. Additive (Command.link)
so the stock system / access-rights visibility is preserved; every
section under Settings still enforces its own group gate.
-->
<record id="base.menu_administration" model="ir.ui.menu">
<field
name="group_ids"
eval="[Command.link(ref('spp_security.group_spp_admin')), Command.link(ref('spp_registry.group_registry_config_admin'))]"
/>
</record>
</odoo>
1 change: 0 additions & 1 deletion spp_starter_sp_mis/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
],
"data": [
"data/config_parameters.xml",
"views/res_config_settings_views.xml",
],
"assets": {
"web.assets_backend": [
Expand Down
1 change: 0 additions & 1 deletion spp_starter_sp_mis/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
from . import res_config_settings
17 changes: 0 additions & 17 deletions spp_starter_sp_mis/models/res_config_settings.py

This file was deleted.

37 changes: 0 additions & 37 deletions spp_starter_sp_mis/views/res_config_settings_views.xml

This file was deleted.

Loading