From c3802f3965272e9c191c998df212675f513b5b35 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Thu, 30 Jul 2026 17:00:12 +0200 Subject: [PATCH 1/3] [IMP/FIX] web_dashboard_tile: [FIX] add admin group to avoid all user have the possibility to create / unlink all elements. As a result, this new groupr 'Tile Manager' has read access to 'ir.model' and 'ir.model.fields' model to prevent error. [FIX] store field name and model name in compute_sudo mode, because in V16, ir.model access changed and only admin user can read model [FIX] remove compute_sudo because otherwise, results are wrong. [FIX] avoid to overload 'fields' keyword [REF] simplify code --- web_dashboard_tile/README.rst | 4 +- web_dashboard_tile/__manifest__.py | 1 + web_dashboard_tile/models/tile_tile.py | 53 ++++++++++--------- web_dashboard_tile/readme/CONFIGURE.rst | 4 +- .../security/ir.model.access.csv | 8 ++- web_dashboard_tile/security/res_groups.xml | 7 +++ .../static/description/index.html | 3 +- web_dashboard_tile/views/menu.xml | 1 + web_dashboard_tile/views/tile_tile.xml | 11 +++- 9 files changed, 62 insertions(+), 30 deletions(-) create mode 100644 web_dashboard_tile/security/res_groups.xml diff --git a/web_dashboard_tile/README.rst b/web_dashboard_tile/README.rst index 274e5dd51324..3fb04054f6ca 100644 --- a/web_dashboard_tile/README.rst +++ b/web_dashboard_tile/README.rst @@ -57,7 +57,9 @@ Tile can be: Configuration ============= -First, you have to create tile categories. +First, ensure you are member of the group "Overview Manager". + +Then, you have to create tile categories. * Go to "Dashboards > Configuration > Overview Settings > Dashboard Categories" diff --git a/web_dashboard_tile/__manifest__.py b/web_dashboard_tile/__manifest__.py index 35816a8c7a55..5603bc0a9695 100644 --- a/web_dashboard_tile/__manifest__.py +++ b/web_dashboard_tile/__manifest__.py @@ -18,6 +18,7 @@ "category": "web", "license": "AGPL-3", "data": [ + "security/res_groups.xml", "security/ir.model.access.csv", "security/ir_rule.xml", "views/menu.xml", diff --git a/web_dashboard_tile/models/tile_tile.py b/web_dashboard_tile/models/tile_tile.py index d0c3d1965521..2963d53a6b67 100644 --- a/web_dashboard_tile/models/tile_tile.py +++ b/web_dashboard_tile/models/tile_tile.py @@ -102,12 +102,11 @@ class TileTile(models.Model): model_id = fields.Many2one( comodel_name="ir.model", string="Model", required=True, ondelete="cascade" ) - - model_name = fields.Char(string="Model name", related="model_id.model") + model_name = fields.Char(string="Model name", related="model_id.model", store=True) domain = fields.Text(default="[]", required=True) - domain_error = fields.Char(compute="_compute_data", compute_sudo=True) + domain_error = fields.Char(compute="_compute_data") action_id = fields.Many2one( comodel_name="ir.actions.act_window", @@ -125,9 +124,7 @@ class TileTile(models.Model): help="If checked, the item will be hidden if the primary value is null.", ) - hidden = fields.Boolean( - compute="_compute_data", compute_sudo=True, search="_search_hidden" - ) + hidden = fields.Boolean(compute="_compute_data", search="_search_hidden") # Primary Value primary_function = fields.Selection( @@ -143,18 +140,22 @@ class TileTile(models.Model): " ('ttype', 'in', ['float', 'integer', 'monetary'])]", ) + primary_field_name = fields.Char( + string="Primary Field Name", related="primary_field_id.name", store=True + ) + primary_format = fields.Char( help="Python Format String valid with str.format()\n" "ie: '{:,} Kgs' will output '1,000 Kgs' if value is 1000.", ) - primary_value = fields.Float(compute="_compute_data", compute_sudo=True) + primary_value = fields.Float(compute="_compute_data") - primary_formated_value = fields.Char(compute="_compute_data", compute_sudo=True) + primary_formated_value = fields.Char(compute="_compute_data") primary_helper = fields.Char(compute="_compute_helper", store=True) - primary_error = fields.Char(compute="_compute_data", compute_sudo=True) + primary_error = fields.Char(compute="_compute_data") # Secondary Value secondary_function = fields.Selection( @@ -168,22 +169,26 @@ class TileTile(models.Model): " ('ttype', 'in', ['float', 'integer', 'monetary'])]", ) + secondary_field_name = fields.Char( + string="Secondary Field Name", related="secondary_field_id.name", store=True + ) + secondary_format = fields.Char( help="Python Format String valid with str.format()\n" "ie: '{:,} Kgs' will output '1,000 Kgs' if value is 1000.", ) - secondary_value = fields.Float(compute="_compute_data", compute_sudo=True) + secondary_value = fields.Float(compute="_compute_data") - secondary_formated_value = fields.Char(compute="_compute_data", compute_sudo=True) + secondary_formated_value = fields.Char(compute="_compute_data") secondary_helper = fields.Char(compute="_compute_helper", store=True) - secondary_error = fields.Char(compute="_compute_data", compute_sudo=True) + secondary_error = fields.Char(compute="_compute_data") # Compute Section @api.depends( - "model_id", + "model_name", "domain", "primary_format", "primary_function", @@ -203,10 +208,10 @@ def _compute_data(self): tile.domain_error = False tile.primary_error = False tile.secondary_error = False - if not tile.model_id or not tile.active: + if not tile.model_name or not tile.active: continue - model = self.env[tile.model_id.model] + model = self.env[tile.model_name] eval_context = self._get_eval_context() domain = tile.domain or "[]" try: @@ -217,12 +222,12 @@ def _compute_data(self): ) tile.domain_error = str(e) continue - fields = [ - f.name for f in [tile.primary_field_id, tile.secondary_field_id] if f + field_names = [ + x for x in [tile.primary_field_name, tile.secondary_field_name] if x ] read_vals = ( - fields - and model.search_read(safe_eval(domain, eval_context), fields) + field_names + and model.search_read(safe_eval(domain, eval_context), field_names) or [] ) for f in ["primary_", "secondary_"]: @@ -274,8 +279,8 @@ def _compute_helper(self): def _compute_active(self): IrModelAccess = self.env["ir.model.access"] for tile in self: - if tile.model_id: - tile.active = IrModelAccess.check(tile.model_id.model, "read", False) + if tile.model_name: + tile.active = IrModelAccess.check(tile.model_name, "read", False) else: tile.active = True @@ -318,9 +323,9 @@ def _check_model_id_field_id(self): if any( [ tile.primary_field_id - and tile.primary_field_id.model_id.id != tile.model_id.id, + and tile.primary_field_id.model_id != tile.model_id, tile.secondary_field_id - and tile.secondary_field_id.model_id.id != tile.model_id.id, + and tile.secondary_field_id.model_id != tile.model_id, ] ): raise ValidationError( @@ -349,7 +354,7 @@ def open_link(self): action = { "view_mode": "tree", "view_id": False, - "res_model": self.model_id.model, + "res_model": self.model_name, "type": "ir.actions.act_window", "target": "current", "domain": self.domain, diff --git a/web_dashboard_tile/readme/CONFIGURE.rst b/web_dashboard_tile/readme/CONFIGURE.rst index 3fdb451f8e96..92a8e4827d58 100644 --- a/web_dashboard_tile/readme/CONFIGURE.rst +++ b/web_dashboard_tile/readme/CONFIGURE.rst @@ -1,4 +1,6 @@ -First, you have to create tile categories. +First, ensure you are member of the group "Overview Manager". + +Then, you have to create tile categories. * Go to "Dashboards > Configuration > Overview Settings > Dashboard Categories" diff --git a/web_dashboard_tile/security/ir.model.access.csv b/web_dashboard_tile/security/ir.model.access.csv index 06448cc9925d..f4550fa7c903 100644 --- a/web_dashboard_tile/security/ir.model.access.csv +++ b/web_dashboard_tile/security/ir.model.access.csv @@ -1,3 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -tile_user,tile_user,model_tile_tile,base.group_user,1,1,1,1 -tile_user_category,tile_user,model_tile_category,base.group_user,1,1,1,1 +tile_user,tile_user,model_tile_tile,base.group_user,1,0,0,0 +tile_manger,tile_user,model_tile_tile,web_dashboard_tile.group_tile_manager,1,1,1,1 +tile_user_category,tile_user,model_tile_category,base.group_user,1,0,0,0 +tile_manager_category,tile_user,model_tile_category,web_dashboard_tile.group_tile_manager,1,1,1,1 +model_reader,model_reader,base.model_ir_model,web_dashboard_tile.group_tile_manager,1,0,0,0 +field_reader,field_reader,base.model_ir_model_fields,web_dashboard_tile.group_tile_manager,1,0,0,0 diff --git a/web_dashboard_tile/security/res_groups.xml b/web_dashboard_tile/security/res_groups.xml new file mode 100644 index 000000000000..2be64976b860 --- /dev/null +++ b/web_dashboard_tile/security/res_groups.xml @@ -0,0 +1,7 @@ + + + + Overview Manager + + + diff --git a/web_dashboard_tile/static/description/index.html b/web_dashboard_tile/static/description/index.html index 06c9e1962fda..f8babb7da99a 100644 --- a/web_dashboard_tile/static/description/index.html +++ b/web_dashboard_tile/static/description/index.html @@ -406,7 +406,8 @@

Overview Dashboard (Tiles)

Configuration

-

First, you have to create tile categories.

+

First, ensure you are member of the group “Overview Manager”.

+

Then, you have to create tile categories.