feat: Restrict access to stock quantity reports by user allowed warehouses and refactor stock model access control to use ir.rules.
This commit is contained in:
parent
172d6c1349
commit
9dfecde29e
@ -6,3 +6,4 @@ from . import stock_picking
|
|||||||
from . import approval_request
|
from . import approval_request
|
||||||
from . import procurement_group
|
from . import procurement_group
|
||||||
from . import stock_move
|
from . import stock_move
|
||||||
|
from . import report_stock_quantity
|
||||||
|
|||||||
23
models/report_stock_quantity.py
Normal file
23
models/report_stock_quantity.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from odoo import models, api
|
||||||
|
from odoo.osv import expression
|
||||||
|
|
||||||
|
class ReportStockQuantity(models.Model):
|
||||||
|
_inherit = 'report.stock.quantity'
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _search(self, domain, offset=0, limit=None, order=None, **kwargs):
|
||||||
|
user = self.env.user
|
||||||
|
# START Custom Restriction Logic
|
||||||
|
# Bylass for System admins or explicit bypass context
|
||||||
|
if not user.has_group('base.group_system') and not self.env.context.get('bypass_user_restriction'):
|
||||||
|
allowed_wh = user.allowed_warehouse_ids | user.allowed_location_ids.warehouse_id
|
||||||
|
# If user has specific allowed warehouses/locations, restrict report
|
||||||
|
if allowed_wh:
|
||||||
|
domain = expression.AND([domain, [('warehouse_id', 'in', allowed_wh.ids)]])
|
||||||
|
|
||||||
|
# Note: If allowed_wh is empty but allowed_location_ids is NOT empty, it means
|
||||||
|
# the allowed locations don't belong to any warehouse (unlikely) or just user config issue.
|
||||||
|
# If BOTH are empty, we fall back to standard access (All).
|
||||||
|
# END Custom Restriction Logic
|
||||||
|
|
||||||
|
return super()._search(domain, offset, limit, order, **kwargs)
|
||||||
@ -36,24 +36,9 @@ class StockPickingType(models.Model):
|
|||||||
domain = Domain(domain or []) & Domain([('id', 'in', allowed_ids)])
|
domain = Domain(domain or []) & Domain([('id', 'in', allowed_ids)])
|
||||||
return super()._search(domain, offset=offset, limit=limit, order=order, **kwargs)
|
return super()._search(domain, offset=offset, limit=limit, order=order, **kwargs)
|
||||||
|
|
||||||
class StockLocation(models.Model):
|
|
||||||
_inherit = 'stock.location'
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _search(self, domain, offset=0, limit=None, order=None, **kwargs):
|
|
||||||
if self.env.context.get('bypass_user_restriction'):
|
|
||||||
return super()._search(domain, offset=offset, limit=limit, order=order, **kwargs)
|
|
||||||
if not self.env.su and not self.env.user.has_group('base.group_system'):
|
|
||||||
allowed_ids = get_allowed_ids(self.env, 'res_users_stock_location_rel', 'location_id', self.env.user.id)
|
|
||||||
if allowed_ids:
|
|
||||||
restrict_domain = [
|
|
||||||
'|', '|',
|
|
||||||
('id', 'parent_of', allowed_ids),
|
|
||||||
('id', 'child_of', allowed_ids),
|
|
||||||
('usage', 'not in', ['internal', 'transit'])
|
|
||||||
]
|
|
||||||
domain = Domain(domain or []) & Domain(restrict_domain)
|
|
||||||
return super()._search(domain, offset=offset, limit=limit, order=order, **kwargs)
|
|
||||||
|
|
||||||
class MrpWorkcenter(models.Model):
|
class MrpWorkcenter(models.Model):
|
||||||
_inherit = 'mrp.workcenter'
|
_inherit = 'mrp.workcenter'
|
||||||
|
|||||||
@ -1,87 +1,129 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
<data>
|
||||||
<!-- Permissive Rules to allow Read access, avoiding Access Errors.
|
<!--
|
||||||
Actual visibility restriction is handled by _search method in models/restricted_models.py. -->
|
RESTRICTIVE RULES
|
||||||
|
These rules restrict access based on User's allowed fields.
|
||||||
|
They include a context check 'bypass_user_restriction' to allow system/sudo operations to pass if needed.
|
||||||
|
-->
|
||||||
|
|
||||||
<record id="stock_warehouse_permissive_rule" model="ir.rule">
|
<!-- Stock Warehouse -->
|
||||||
<field name="name">Stock Warehouse Permissive Access</field>
|
<record id="stock_warehouse_allowed_rule" model="ir.rule">
|
||||||
|
<field name="name">Stock Warehouse Allowed Access</field>
|
||||||
<field name="model_id" ref="stock.model_stock_warehouse"/>
|
<field name="model_id" ref="stock.model_stock_warehouse"/>
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
<field name="domain_force">
|
||||||
<field name="perm_read" eval="True"/>
|
(
|
||||||
<field name="perm_write" eval="False"/>
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
<field name="perm_create" eval="False"/>
|
[('id', 'in', user.allowed_warehouse_ids.ids)] if user.allowed_warehouse_ids else [(1, '=', 1)]
|
||||||
<field name="perm_unlink" eval="False"/>
|
)
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="stock_picking_type_permissive_rule" model="ir.rule">
|
<!-- Stock Picking Type -->
|
||||||
<field name="name">Stock Picking Type Permissive Access</field>
|
<record id="stock_picking_type_allowed_rule" model="ir.rule">
|
||||||
|
<field name="name">Stock Picking Type Allowed Access</field>
|
||||||
<field name="model_id" ref="stock.model_stock_picking_type"/>
|
<field name="model_id" ref="stock.model_stock_picking_type"/>
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
<field name="domain_force">
|
||||||
<field name="perm_read" eval="True"/>
|
(
|
||||||
<field name="perm_write" eval="False"/>
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
<field name="perm_create" eval="False"/>
|
[('id', 'in', user.allowed_picking_type_ids.ids)] if user.allowed_picking_type_ids else [(1, '=', 1)]
|
||||||
<field name="perm_unlink" eval="False"/>
|
)
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="stock_location_permissive_rule" model="ir.rule">
|
<!-- Stock Location -->
|
||||||
<field name="name">Stock Location Permissive Access</field>
|
<record id="stock_location_allowed_rule" model="ir.rule">
|
||||||
|
<field name="name">Stock Location Allowed Access</field>
|
||||||
<field name="model_id" ref="stock.model_stock_location"/>
|
<field name="model_id" ref="stock.model_stock_location"/>
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
<field name="domain_force">
|
||||||
<field name="perm_read" eval="True"/>
|
(
|
||||||
<field name="perm_write" eval="False"/>
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
<field name="perm_create" eval="False"/>
|
['|', '|', ('id', 'in', user.allowed_location_ids.ids), ('id', 'child_of', user.allowed_location_ids.ids), ('id', 'parent_of', user.allowed_location_ids.ids)] if user.allowed_location_ids else [(1, '=', 1)]
|
||||||
<field name="perm_unlink" eval="False"/>
|
)
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="mrp_workcenter_permissive_rule" model="ir.rule">
|
<!-- Stock Quant (The critical one for Reports) -->
|
||||||
<field name="name">MRP Workcenter Permissive Access</field>
|
<record id="stock_quant_allowed_rule" model="ir.rule">
|
||||||
<field name="model_id" ref="mrp.model_mrp_workcenter"/>
|
<field name="name">Stock Quant Allowed Access</field>
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
|
||||||
<field name="perm_read" eval="True"/>
|
|
||||||
<field name="perm_write" eval="False"/>
|
|
||||||
<field name="perm_create" eval="False"/>
|
|
||||||
<field name="perm_unlink" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="approval_category_permissive_rule" model="ir.rule">
|
|
||||||
<field name="name">Approval Category Permissive Access</field>
|
|
||||||
<field name="model_id" ref="approvals.model_approval_category"/>
|
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
|
||||||
<field name="perm_read" eval="True"/>
|
|
||||||
<field name="perm_write" eval="False"/>
|
|
||||||
<field name="perm_create" eval="False"/>
|
|
||||||
<field name="perm_unlink" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- New rules to satisfy Inventory Reporting requirements -->
|
|
||||||
|
|
||||||
|
|
||||||
<record id="stock_quant_permissive_rule" model="ir.rule">
|
|
||||||
<field name="name">Stock Quant Permissive Access</field>
|
|
||||||
<field name="model_id" ref="stock.model_stock_quant"/>
|
<field name="model_id" ref="stock.model_stock_quant"/>
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
<field name="domain_force">
|
||||||
<field name="perm_read" eval="True"/>
|
(
|
||||||
<field name="perm_write" eval="False"/>
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
<field name="perm_create" eval="False"/>
|
['|', ('location_id', 'in', user.allowed_location_ids.ids), ('location_id', 'child_of', user.allowed_location_ids.ids)] if user.allowed_location_ids else [(1, '=', 1)]
|
||||||
<field name="perm_unlink" eval="False"/>
|
)
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="approval_request_permissive_rule" model="ir.rule">
|
<!-- Stock Move -->
|
||||||
<field name="name">Approval Request Permissive Access</field>
|
<record id="stock_move_allowed_rule" model="ir.rule">
|
||||||
<field name="model_id" ref="approvals.model_approval_request"/>
|
<field name="name">Stock Move Allowed Access</field>
|
||||||
|
<field name="model_id" ref="stock.model_stock_move"/>
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
<field name="domain_force">[(1, '=', 1)]</field>
|
<field name="domain_force">
|
||||||
<field name="perm_read" eval="True"/>
|
(
|
||||||
<field name="perm_write" eval="False"/>
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
<field name="perm_create" eval="False"/>
|
['|', '|', ('location_id', 'in', user.allowed_location_ids.ids), ('location_id', 'child_of', user.allowed_location_ids.ids),
|
||||||
<field name="perm_unlink" eval="False"/>
|
'|', ('location_dest_id', 'in', user.allowed_location_ids.ids), ('location_dest_id', 'child_of', user.allowed_location_ids.ids)] if user.allowed_location_ids else [(1, '=', 1)]
|
||||||
|
)
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Stock Move Line -->
|
||||||
|
<record id="stock_move_line_allowed_rule" model="ir.rule">
|
||||||
|
<field name="name">Stock Move Line Allowed Access</field>
|
||||||
|
<field name="model_id" ref="stock.model_stock_move_line"/>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
(
|
||||||
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
|
['|', '|', ('location_id', 'in', user.allowed_location_ids.ids), ('location_id', 'child_of', user.allowed_location_ids.ids),
|
||||||
|
'|', ('location_dest_id', 'in', user.allowed_location_ids.ids), ('location_dest_id', 'child_of', user.allowed_location_ids.ids)] if user.allowed_location_ids else [(1, '=', 1)]
|
||||||
|
)
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- MRP Workcenter -->
|
||||||
|
<record id="mrp_workcenter_allowed_rule" model="ir.rule">
|
||||||
|
<field name="name">MRP Workcenter Allowed Access</field>
|
||||||
|
<field name="model_id" ref="mrp.model_mrp_workcenter"/>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
(
|
||||||
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
|
[('id', 'in', user.allowed_workcenter_ids.ids)] if user.allowed_workcenter_ids else [(1, '=', 1)]
|
||||||
|
)
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Approval Category -->
|
||||||
|
<record id="approval_category_allowed_rule" model="ir.rule">
|
||||||
|
<field name="name">Approval Category Allowed Access</field>
|
||||||
|
<field name="model_id" ref="approvals.model_approval_category"/>
|
||||||
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
(
|
||||||
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
|
[('id', 'in', user.allowed_approval_category_ids.ids)] if user.allowed_approval_category_ids else [(1, '=', 1)]
|
||||||
|
)
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Report Stock Quantity -->
|
||||||
|
<record id="report_stock_quantity_allowed_rule" model="ir.rule">
|
||||||
|
<field name="name">Report Stock Quantity Allowed Access</field>
|
||||||
|
<field name="model_id" ref="stock.model_report_stock_quantity"/>
|
||||||
|
<field name="global" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
(
|
||||||
|
[(1, '=', 1)] if user.env.context.get('bypass_user_restriction') or user.has_group('base.group_system') else
|
||||||
|
[('warehouse_id', 'in', (user.allowed_warehouse_ids + user.allowed_location_ids.warehouse_id).ids)] if (user.allowed_warehouse_ids or user.allowed_location_ids) else [(1, '=', 1)]
|
||||||
|
)
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user