Files
enterprise-addons/documents/models/ir_actions_server.py
T

83 lines
3.7 KiB
Python

from odoo import _, fields, models
from odoo.exceptions import UserError
class DocumentsSentinel:
"""Sentinel class to prevent context spoofing via RPC."""
pass
class IrActionsServer(models.Model):
_inherit = 'ir.actions.server'
# The documents actions add a check that the current document is in a folder
# on which the current action is pinned (to avoid executing server action
# means to be used in a different folder).
usage = fields.Selection(
selection_add=[('documents_embedded', 'Documents')],
ondelete={'documents_embedded': 'set ir_actions_server'},
)
def action_open_documents_server_action_view(self):
self.check_access('read')
form_view = self.env.ref('documents.ir_actions_server_view_form_documents', raise_if_not_found=False)
search_view = self.env.ref('documents.ir_actions_server_action_search_documents', raise_if_not_found=False)
return {
'context': {
'default_model_id': self.env['ir.model']._get_id('documents.document'),
'default_update_path': 'tag_ids',
'default_usage': 'documents_embedded',
},
'display_name': _('Server Actions'),
'domain': [
('model_name', '=', 'documents.document'),
('parent_id', '=', False),
],
'help': """
<div style="width:650px;">
<p class="d-none">%s</p>
<img class="w-100 w-md-75" src="/documents/static/img/documents_server_action.svg"/>
</div>
""" % _('No server actions found for Documents!'),
'res_model': 'ir.actions.server',
'target': 'current',
'type': 'ir.actions.act_window',
'view_mode': 'list,form',
'views': [(False, 'list'), (form_view.id if form_view else False, 'form')],
'search_view_id': [search_view.id if search_view else False, 'search'],
}
def _run(self, records, eval_context):
"""Override to implement 'Entry Point' security for Documents actions."""
if isinstance(self.env.context.get('__documents_embedded_checked'), DocumentsSentinel):
return super()._run(records, eval_context)
descendants = self
while descendants.child_ids - descendants:
descendants |= descendants.child_ids
if 'documents_embedded' in descendants.mapped('usage'):
self._check_is_document_action_embedded(records)
return super(IrActionsServer, self.with_context(
__documents_embedded_checked=DocumentsSentinel()
))._run(records, eval_context)
return super()._run(records, eval_context)
def _check_is_document_action_embedded(self, records):
"""Verify that the action is explicitly embedded (pinned) on the current folder of the given records."""
for record in records:
record_actions = record.available_embedded_actions_ids.action_id
record_server_actions_sudo = record_actions.sudo().filtered(lambda a: a.type == 'ir.actions.server')
available_server_actions_sudo = self.env['ir.actions.server'].browse(record_server_actions_sudo.ids).sudo()
# Add the child actions
actions = available_server_actions_sudo
while actions.child_ids:
next_actions = actions.child_ids - available_server_actions_sudo
available_server_actions_sudo |= actions.child_ids
actions = next_actions
if self not in available_server_actions_sudo:
raise UserError(_('This action was not made available on the containing folder.'))