-
Notifications
You must be signed in to change notification settings - Fork 42
[18.0][ADD] cetmix_tower_jet_isolation: base module add new module #486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 18.0
Are you sure you want to change the base?
Changes from all commits
577eee9
bb589d6
c0066cd
834ea5d
6582561
2fe26fc
1028b27
7c1970e
1126d98
6c96323
385a528
f74940a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| ========================== | ||
| Cetmix Tower Jet Isolation | ||
| ========================== | ||
|
|
||
| .. | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| !! This file is generated by oca-gen-addon-readme !! | ||
| !! changes will be overwritten. !! | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
|
||
| .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
| :target: https://odoo-community.org/page/development-status | ||
| :alt: Beta | ||
| .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png | ||
| :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
| :alt: License: AGPL-3 | ||
| .. |badge3| image:: https://img.shields.io/badge/github-cetmix%2Fcetmix--tower-lightgray.png?logo=github | ||
| :target: https://github.com/cetmix/cetmix-tower | ||
| :alt: cetmix/cetmix-tower | ||
|
|
||
| |badge1| |badge2| |badge3| | ||
|
|
||
| Adds strict isolation mode for Jets, preventing users from altering command visibility. | ||
|
|
||
| **Table of contents** | ||
|
|
||
| .. contents:: | ||
| :local: | ||
|
|
||
| Installation | ||
| ============ | ||
|
|
||
| To install this module, you need to: | ||
|
|
||
| 1. Clone cetmix-tower repository. | ||
| 2. Install this module `cetmix_tower_jet_isolation` into your Odoo instance. | ||
|
|
||
| Configuration | ||
| ============= | ||
|
|
||
| To configure this module, you need to: | ||
|
|
||
| 1. Go to Tower > Jet Templates. | ||
| 2. Open a Jet Template. | ||
| 3. Enable 'Isolation Mode' and configure forced applicability and tags. | ||
|
|
||
| Usage | ||
| ===== | ||
|
|
||
| When users run a command or a flight plan from an isolated Jet, the wizard will have the applicability options and tag selections locked, enforcing the parameters defined by the administrator in the Template. | ||
|
|
||
| Bug Tracker | ||
| =========== | ||
|
|
||
| Bugs are tracked on `GitHub Issues <https://github.com/cetmix/cetmix-tower/issues>`_. | ||
|
|
||
| Credits | ||
| ======= | ||
|
|
||
| Authors | ||
| ~~~~~~~ | ||
|
|
||
| * Cetmix | ||
| * Crumges | ||
|
|
||
| Maintainers | ||
| ~~~~~~~~~~~ | ||
|
|
||
| This module is maintained by the Cetmix team. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| from . import models, wizards | ||
| from .hooks import uninstall_hook |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "name": "Cetmix Tower Jet Isolation", | ||
| "version": "18.0.1.0.1", | ||
| "category": "Tower", | ||
| "summary": "Adds strict isolation mode for Jets.", | ||
| "author": "Cetmix, Crumges", | ||
| "website": "https://tower.cetmix.com", | ||
| "depends": [ | ||
| "cetmix_tower_server", | ||
| ], | ||
| "data": [ | ||
| "views/cx_tower_jet_template_views.xml", | ||
| "views/cx_tower_command_run_wizard_views.xml", | ||
| "views/cx_tower_plan_run_wizard_views.xml", | ||
| ], | ||
| "installable": True, | ||
| "license": "AGPL-3", | ||
| "uninstall_hook": "uninstall_hook", | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| def uninstall_hook(env): | ||
| """Reset isolation fields on all jet templates when the module is uninstalled. | ||
|
|
||
| Odoo does not drop columns when a module is uninstalled, so any templates | ||
| that had ``isolation_mode`` enabled would still carry the value ``True`` | ||
| in their row. When the module is re-installed (or the column is somehow | ||
| still read) those stale values would silently reactivate the restriction | ||
| logic. Resetting them here ensures a clean state. | ||
| """ | ||
| env["cx.tower.jet.template"].search([("isolation_mode", "=", True)]).write( | ||
| { | ||
| "isolation_mode": False, | ||
| "forced_applicability": False, | ||
| "forced_command_tag_ids": [(5,)], | ||
| "forced_plan_tag_ids": [(5,)], | ||
| } | ||
| ) | ||
|
Comment on lines
+10
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, find and examine the hooks.py file
find . -name "hooks.py" -path "*cetmix_tower_jet_isolation*" -type fRepository: cetmix/cetmix-tower Length of output: 100 🏁 Script executed: # Also search for the model definition to understand the structure
find . -path "*cetmix_tower_jet_isolation*" -name "*.py" -type f | head -20Repository: cetmix/cetmix-tower Length of output: 477 🏁 Script executed: # Check for model definitions with cx.tower.jet.template
rg "cx\.tower\.jet\.template" --type py -A 5 -B 5Repository: cetmix/cetmix-tower Length of output: 50375 🏁 Script executed: cat -n ./cetmix_tower_jet_isolation/hooks.pyRepository: cetmix/cetmix-tower Length of output: 937 🏁 Script executed: cat -n ./cetmix_tower_jet_isolation/models/cx_tower_jet_template.pyRepository: cetmix/cetmix-tower Length of output: 882 🌐 Web query:
💡 Result: In Odoo, models that define an 'active' field (typically BooleanField with default=True) have automatic filtering behavior in ORM methods like search, read_group, etc. The parameter 'active_test' controls whether this filtering is applied. Default behavior: active_test defaults to True when not specified in the context. This means searches and similar operations automatically filter to only include records where active=True (active records), excluding archived/inactive ones (active=False). To include inactive records, explicitly set active_test=False in the context, e.g.: self.with_context(active_test=False).search(domain) or in views: This applies to any model with an 'active' field (or custom _active_name field). Official docs confirm the 'active' field "toggles the global visibility of the record, if active is set to False the record is invisible in most searches and listing." Multiple secondary sources and code examples confirm the default is True, requiring explicit False to bypass filtering. Citations:
🏁 Script executed: # Find the parent cx.tower.jet.template model definition
rg "_name = \"cx\.tower\.jet\.template\"" --type py -A 20 -B 2Repository: cetmix/cetmix-tower Length of output: 3753 🏁 Script executed: # Check if the parent model has an active field
rg "active.*Boolean" cetmix_tower_server/models/cx_tower_jet_template.py -A 2 -B 2Repository: cetmix/cetmix-tower Length of output: 190 Reset all isolation fields on both active and archived templates. The current search only updates active templates with 🛠️ Proposed fix- env["cx.tower.jet.template"].search([("isolation_mode", "=", True)]).write(
+ env["cx.tower.jet.template"].with_context(active_test=False).search([]).write(
{
"isolation_mode": False,
"forced_applicability": False,
"forced_command_tag_ids": [(5,)],
"forced_plan_tag_ids": [(5,)],🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from . import cx_tower_jet_template |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class CxTowerJetTemplate(models.Model): | ||
| _inherit = "cx.tower.jet.template" | ||
|
|
||
| isolation_mode = fields.Boolean( | ||
| help="Prevents changing applicability or tags when running commands." | ||
| ) | ||
| forced_applicability = fields.Selection( | ||
| [("this", "For selected server(s)"), ("shared", "Non server restricted")] | ||
| ) | ||
|
|
||
| forced_command_tag_ids = fields.Many2many( | ||
| comodel_name="cx.tower.tag", | ||
| relation="cx_tower_template_forced_command_tag_rel", | ||
| ) | ||
|
|
||
| forced_plan_tag_ids = fields.Many2many( | ||
| comodel_name="cx.tower.tag", | ||
| relation="cx_tower_template_forced_plan_tag_rel", | ||
| ) | ||
|
Comment on lines
+14
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Specify Other 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [build-system] | ||
| requires = ["setuptools"] | ||
| build-backend = "setuptools.build_meta" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,58 @@ | ||||||||||||||||||||
| <?xml version="1.0" encoding="utf-8" ?> | ||||||||||||||||||||
| <odoo> | ||||||||||||||||||||
| <record id="cx_tower_command_run_wizard_view_form_isolation" model="ir.ui.view"> | ||||||||||||||||||||
| <field name="name">cx.tower.command.run.wizard.view.form.isolation</field> | ||||||||||||||||||||
| <field name="model">cx.tower.command.run.wizard</field> | ||||||||||||||||||||
| <field | ||||||||||||||||||||
| name="inherit_id" | ||||||||||||||||||||
| ref="cetmix_tower_server.cx_tower_command_run_wizard_view_form" | ||||||||||||||||||||
| /> | ||||||||||||||||||||
| <field name="arch" type="xml"> | ||||||||||||||||||||
| <xpath expr="//field[@name='tag_ids']" position="before"> | ||||||||||||||||||||
| <field name="is_restricted_context" invisible="1" /> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
|
|
||||||||||||||||||||
| <xpath expr="//label[@for='applicability']" position="attributes"> | ||||||||||||||||||||
| <attribute name="invisible">is_restricted_context or result</attribute> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
|
|
||||||||||||||||||||
| <xpath expr="//field[@name='applicability']" position="attributes"> | ||||||||||||||||||||
| <attribute name="readonly">is_restricted_context</attribute> | ||||||||||||||||||||
| <attribute name="force_save">1</attribute> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
|
Comment on lines
+19
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Overriding The parent view sets 🔧 Proposed fix <xpath expr="//field[`@name`='applicability']" position="attributes">
- <attribute name="readonly">is_isolated_context</attribute>
+ <attribute name="readonly">is_isolated_context or show_servers</attribute>
<attribute name="force_save">1</attribute>
</xpath>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
| <xpath expr="//field[@name='tag_ids']" position="attributes"> | ||||||||||||||||||||
| <attribute name="groups">cetmix_tower_server.group_manager</attribute> | ||||||||||||||||||||
| <attribute name="invisible">is_restricted_context or result</attribute> | ||||||||||||||||||||
| <attribute name="force_save">1</attribute> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
|
Comment on lines
+24
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify static group narrowing on tag_ids versus dynamic restriction logic.
rg -n -C4 'name="tag_ids"|is_restricted_context|manager_ids|has_group\("cetmix_tower_server.group_manager"\)' \
cetmix_tower_jet_isolation/views/cx_tower_command_run_wizard_views.xml \
cetmix_tower_jet_isolation/wizards/cx_tower_command_run_wizard.pyRepository: cetmix/cetmix-tower Length of output: 7612 Remove static group restriction on tag_ids field. Line 25 unnecessarily restricts Proposed fix <xpath expr="//field[`@name`='tag_ids']" position="attributes">
- <attribute name="groups">cetmix_tower_server.group_manager</attribute>
<attribute name="invisible">is_restricted_context or result</attribute>
<attribute name="force_save">1</attribute>
</xpath>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
| <xpath expr="//field[@name='tag_ids']" position="after"> | ||||||||||||||||||||
| <field | ||||||||||||||||||||
| name="isolated_tag_ids" | ||||||||||||||||||||
| widget="many2many_tags" | ||||||||||||||||||||
| invisible="not is_restricted_context or result" | ||||||||||||||||||||
| /> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
|
|
||||||||||||||||||||
| <xpath expr="//notebook" position="attributes"> | ||||||||||||||||||||
| <attribute name="groups" /> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
| <xpath expr="//page[@name='code']" position="attributes"> | ||||||||||||||||||||
| <attribute name="invisible">is_restricted_context</attribute> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
| <xpath expr="//field[@name='rendered_code']" position="attributes"> | ||||||||||||||||||||
| <attribute name="groups" /> | ||||||||||||||||||||
| <attribute name="readonly">1</attribute> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
|
marionumza marked this conversation as resolved.
|
||||||||||||||||||||
| <xpath | ||||||||||||||||||||
| expr="//field[@name='custom_variable_value_ids']" | ||||||||||||||||||||
| position="attributes" | ||||||||||||||||||||
| > | ||||||||||||||||||||
| <attribute | ||||||||||||||||||||
| name="readonly" | ||||||||||||||||||||
| >not have_access_to_server or is_restricted_context</attribute> | ||||||||||||||||||||
| </xpath> | ||||||||||||||||||||
| </field> | ||||||||||||||||||||
| </record> | ||||||||||||||||||||
| </odoo> | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| <?xml version="1.0" encoding="utf-8" ?> | ||
| <odoo> | ||
| <record id="cx_tower_jet_template_view_form_isolation" model="ir.ui.view"> | ||
| <field name="name">cx.tower.jet.template.view.form.isolation</field> | ||
| <field name="model">cx.tower.jet.template</field> | ||
| <field | ||
| name="inherit_id" | ||
| ref="cetmix_tower_server.cx_tower_jet_template_view_form" | ||
| /> | ||
| <field name="arch" type="xml"> | ||
| <xpath expr="//group[@name='general']" position="after"> | ||
| <group name="isolation" string="Execution Security (Isolation Mode)"> | ||
| <field name="isolation_mode" widget="boolean_toggle" /> | ||
| <field | ||
| name="forced_applicability" | ||
| invisible="not isolation_mode" | ||
| required="isolation_mode" | ||
| /> | ||
| <field | ||
| name="forced_command_tag_ids" | ||
| widget="many2many_tags" | ||
| invisible="not isolation_mode" | ||
| /> | ||
| <field | ||
| name="forced_plan_tag_ids" | ||
| widget="many2many_tags" | ||
| invisible="not isolation_mode" | ||
| /> | ||
| </group> | ||
| </xpath> | ||
| </field> | ||
| </record> | ||
| </odoo> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| <?xml version="1.0" encoding="utf-8" ?> | ||
| <odoo> | ||
| <record id="cx_tower_plan_run_wizard_view_form_isolation" model="ir.ui.view"> | ||
| <field name="name">cx.tower.plan.run.wizard.view.form.isolation</field> | ||
| <field name="model">cx.tower.plan.run.wizard</field> | ||
| <field | ||
| name="inherit_id" | ||
| ref="cetmix_tower_server.cx_tower_plan_run_wizard_view_form" | ||
| /> | ||
| <field name="arch" type="xml"> | ||
| <xpath expr="//field[@name='tag_ids']" position="before"> | ||
| <field name="is_restricted_context" invisible="1" /> | ||
| </xpath> | ||
|
|
||
| <xpath expr="//label[@for='applicability']" position="attributes"> | ||
| <attribute name="invisible">is_restricted_context</attribute> | ||
| </xpath> | ||
|
|
||
| <xpath expr="//field[@name='applicability']" position="attributes"> | ||
| <attribute name="readonly">is_restricted_context</attribute> | ||
| <attribute name="force_save">1</attribute> | ||
| </xpath> | ||
|
Comment on lines
+19
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
fd -t f 'cx_tower_plan_run_wizard_view.xml' | xargs -I{} rg -n -C2 "name=['\"]applicability['\"]" {}Repository: cetmix/cetmix-tower Length of output: 299 🏁 Script executed: # Find the parent view by examining the file and locating the parent reference
fd -t f '*.xml' -p 'cetmix_tower_jet_isolation/views/*' | head -20Repository: cetmix/cetmix-tower Length of output: 184 🏁 Script executed: # Search for the parent view name referenced in the file being reviewed
rg -A5 -B5 "cx_tower_plan_run_wizard_view" cetmix_tower_jet_isolation/views/cx_tower_plan_run_wizard_views.xml | head -40Repository: cetmix/cetmix-tower Length of output: 658 🏁 Script executed: # Look for any parent view definition files that might contain applicability field
fd -t f '*.xml' cetmix_tower_jet_isolation/views/ | xargs grep -l "applicability" | head -10Repository: cetmix/cetmix-tower Length of output: 347 🏁 Script executed: # List all XML files to understand the structure
find . -name "*.xml" -type f | grep -E "(cetmix_tower_server|cetmix_tower_jet)" | head -20Repository: cetmix/cetmix-tower Length of output: 1292 🏁 Script executed: # Search for the parent view definition across the entire repo
rg -l "cx_tower_plan_run_wizard_view_form" --type xmlRepository: cetmix/cetmix-tower Length of output: 192 🏁 Script executed: # Search for applicability field with readonly attribute
rg "readonly.*applicability|applicability.*readonly" --type xml -A2 -B2Repository: cetmix/cetmix-tower Length of output: 45 🏁 Script executed: # Read the parent view file to find applicability field definition
cat -n cetmix_tower_server/wizards/cx_tower_plan_run_wizard_view.xml | grep -A10 -B10 "applicability"Repository: cetmix/cetmix-tower Length of output: 1462 Combine readonly conditions instead of replacing: The parent view already sets 🤖 Prompt for AI Agents |
||
|
|
||
| <xpath expr="//field[@name='tag_ids']" position="attributes"> | ||
| <attribute name="invisible">is_restricted_context</attribute> | ||
| <attribute name="force_save">1</attribute> | ||
| </xpath> | ||
|
|
||
| <xpath expr="//field[@name='tag_ids']" position="after"> | ||
| <field | ||
| name="isolated_tag_ids" | ||
| widget="many2many_tags" | ||
| invisible="not is_restricted_context" | ||
| /> | ||
| </xpath> | ||
|
|
||
| <xpath | ||
| expr="//field[@name='custom_variable_value_ids']" | ||
| position="attributes" | ||
| > | ||
| <attribute name="readonly">is_restricted_context</attribute> | ||
| </xpath> | ||
| </field> | ||
| </record> | ||
| </odoo> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| from . import cx_tower_command_run_wizard | ||
| from . import cx_tower_plan_run_wizard |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| from odoo import api, fields, models | ||
|
|
||
|
|
||
| class CxTowerCommandRunWizardFilter(models.TransientModel): | ||
| _inherit = "cx.tower.command.run.wizard" | ||
|
|
||
| is_restricted_context = fields.Boolean(compute="_compute_is_restricted_context") | ||
| isolated_tag_ids = fields.Many2many( | ||
| comodel_name="cx.tower.tag", | ||
| compute="_compute_isolated_tag_ids", | ||
| string="Forced Tags", | ||
| ) | ||
|
|
||
| @api.depends("jet_ids") | ||
| def _compute_is_restricted_context(self): | ||
| is_global_manager = self.env.user.has_group("cetmix_tower_server.group_manager") | ||
| for record in self: | ||
| jets = record.jet_ids or self.env["cx.tower.jet"].browse( | ||
| self.env.context.get("default_jet_ids", []) | ||
| ) | ||
|
|
||
| is_isolated = bool( | ||
| jets and any(j.jet_template_id.isolation_mode for j in jets) | ||
| ) | ||
|
|
||
| if is_global_manager: | ||
| is_manager = True | ||
| elif jets and all(self.env.user in j.manager_ids for j in jets): | ||
| is_manager = True | ||
| else: | ||
| is_manager = False | ||
|
|
||
| record.is_restricted_context = is_isolated and not is_manager | ||
|
|
||
| @api.depends("tag_ids") | ||
| def _compute_isolated_tag_ids(self): | ||
| for record in self: | ||
| record.isolated_tag_ids = record.tag_ids | ||
|
|
||
| @api.model | ||
| def default_get(self, fields_list): | ||
| res = super().default_get(fields_list) | ||
| if "default_jet_ids" in self.env.context: | ||
| jet_ids = self.env["cx.tower.jet"].browse( | ||
| self.env.context["default_jet_ids"] | ||
| ) | ||
| if jet_ids: | ||
| template = jet_ids[0].jet_template_id | ||
|
|
||
| if template.isolation_mode: | ||
| if template.forced_applicability: | ||
| res["applicability"] = template.forced_applicability | ||
| if template.forced_command_tag_ids: | ||
| res["tag_ids"] = [(6, 0, template.forced_command_tag_ids.ids)] | ||
| return res | ||
|
Comment on lines
+40
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistency between
Iterate over all jets and apply the strictest forced values, or otherwise define a deterministic selection rule (e.g., the first isolated template). 🛠️ Proposed fix- if 'default_jet_ids' in self.env.context:
- jet_ids = self.env['cx.tower.jet'].browse(self.env.context['default_jet_ids'])
- if jet_ids:
- template = jet_ids[0].jet_template_id
-
- if template.isolation_mode:
- if template.forced_applicability:
- res['applicability'] = template.forced_applicability
- if template.forced_command_tag_ids:
- res['tag_ids'] = [(6, 0, template.forced_command_tag_ids.ids)]
+ jet_ids_ctx = self.env.context.get('default_jet_ids')
+ if jet_ids_ctx:
+ jets = self.env['cx.tower.jet'].browse(jet_ids_ctx)
+ isolated_templates = jets.jet_template_id.filtered('isolation_mode')
+ if isolated_templates:
+ template = isolated_templates[0]
+ if template.forced_applicability:
+ res['applicability'] = template.forced_applicability
+ forced_tags = isolated_templates.mapped('forced_command_tag_ids')
+ if forced_tags:
+ res['tag_ids'] = [(6, 0, forced_tags.ids)]🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| from odoo import api, fields, models | ||
|
|
||
|
|
||
| class CxTowerPlanRunWizardFilter(models.TransientModel): | ||
| _inherit = "cx.tower.plan.run.wizard" | ||
|
|
||
| is_restricted_context = fields.Boolean(compute="_compute_is_restricted_context") | ||
| isolated_tag_ids = fields.Many2many( | ||
| comodel_name="cx.tower.tag", | ||
| compute="_compute_isolated_tag_ids", | ||
| string="Forced Tags", | ||
| ) | ||
|
|
||
| @api.depends("jet_ids") | ||
| def _compute_is_restricted_context(self): | ||
| is_global_manager = self.env.user.has_group("cetmix_tower_server.group_manager") | ||
| for record in self: | ||
| jets = record.jet_ids or self.env["cx.tower.jet"].browse( | ||
| self.env.context.get("default_jet_ids", []) | ||
| ) | ||
|
|
||
| is_isolated = bool( | ||
| jets and any(j.jet_template_id.isolation_mode for j in jets) | ||
| ) | ||
|
|
||
| if is_global_manager: | ||
| is_manager = True | ||
| elif jets and all(self.env.user in j.manager_ids for j in jets): | ||
| is_manager = True | ||
| else: | ||
| is_manager = False | ||
|
|
||
| record.is_restricted_context = is_isolated and not is_manager | ||
|
|
||
| @api.depends("tag_ids") | ||
| def _compute_isolated_tag_ids(self): | ||
| for record in self: | ||
| record.isolated_tag_ids = record.tag_ids | ||
|
|
||
| @api.model | ||
| def default_get(self, fields_list): | ||
| res = super().default_get(fields_list) | ||
| if "default_jet_ids" in self.env.context: | ||
| jet_ids = self.env["cx.tower.jet"].browse( | ||
| self.env.context["default_jet_ids"] | ||
| ) | ||
| if jet_ids: | ||
| template = jet_ids[0].jet_template_id | ||
|
|
||
| if template.isolation_mode: | ||
| if template.forced_applicability: | ||
| res["applicability"] = template.forced_applicability | ||
| if template.forced_plan_tag_ids: | ||
| res["tag_ids"] = [(6, 0, template.forced_plan_tag_ids.ids)] | ||
| return res | ||
|
Comment on lines
+40
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Server-side enforcement is missing — isolation is bypassable.
Enforce the isolation constraints on the server side by overriding 🤖 Prompt for AI Agents |
||
Uh oh!
There was an error while loading. Please reload this page.