mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 09:12:04 +02:00
121 lines
4.8 KiB
Python
121 lines
4.8 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import contextlib
|
|
|
|
from odoo import _, models, fields, api
|
|
from odoo.exceptions import AccessError, UserError
|
|
from odoo.tools.misc import limited_field_access_token, verify_limited_field_access_token
|
|
from odoo.addons.mail.tools.discuss import Store
|
|
|
|
|
|
class IrAttachment(models.Model):
|
|
_inherit = 'ir.attachment'
|
|
|
|
thumbnail = fields.Image()
|
|
has_thumbnail = fields.Boolean(compute="_compute_has_thumbnail")
|
|
|
|
@api.depends("thumbnail")
|
|
def _compute_has_thumbnail(self):
|
|
for attachment in self.with_context(bin_size=True):
|
|
attachment.has_thumbnail = bool(attachment.thumbnail)
|
|
|
|
def _has_attachments_ownership(self, attachment_tokens):
|
|
""" Checks if the current user has ownership of all attachments in the recordset.
|
|
Ownership is defined as either:
|
|
- Having 'write' access to the attachment.
|
|
- Providing a valid, scoped 'attachment_ownership' access token.
|
|
|
|
:param list attachment_tokens: A list of access tokens
|
|
"""
|
|
attachment_tokens = attachment_tokens or ([None] * len(self))
|
|
if len(attachment_tokens) != len(self):
|
|
raise UserError(_("An access token must be provided for each attachment."))
|
|
|
|
def is_owned(attachment, token):
|
|
if not attachment.exists():
|
|
return False
|
|
if attachment.sudo(False).has_access("write"):
|
|
return True
|
|
return token and verify_limited_field_access_token(
|
|
attachment, "id", token, scope="attachment_ownership"
|
|
)
|
|
|
|
return all(is_owned(att, tok) for att, tok in zip(self, attachment_tokens, strict=True))
|
|
|
|
def _post_add_create(self, **kwargs):
|
|
""" Overrides behaviour when the attachment is created through the controller
|
|
"""
|
|
super()._post_add_create(**kwargs)
|
|
self.register_as_main_attachment(force=False)
|
|
|
|
def register_as_main_attachment(self, force=True):
|
|
""" Registers this attachment as the main one of the model it is
|
|
attached to.
|
|
|
|
:param bool force: if set, the method always updates the existing main attachment
|
|
otherwise it only sets the main attachment if there is none.
|
|
"""
|
|
todo = self.filtered(lambda a: a.res_model and a.res_id)
|
|
if not todo:
|
|
return
|
|
|
|
for model, attachments in todo.grouped("res_model").items():
|
|
related_records = self.env[model].browse(attachments.mapped("res_id"))
|
|
if not hasattr(related_records, '_message_set_main_attachment_id'):
|
|
return
|
|
|
|
# this action is generic; if user cannot update record do not crash
|
|
# just skip update
|
|
for related_record, attachment in zip(related_records, attachments):
|
|
with contextlib.suppress(AccessError):
|
|
related_record._message_set_main_attachment_id(attachment, force=force)
|
|
|
|
def _delete_and_notify(self, message=None):
|
|
if message:
|
|
# sudo: mail.message - safe write just updating the date, because guests don't have the rights
|
|
message.sudo().write({}) # to make sure write_date on the message is updated
|
|
for attachment in self:
|
|
attachment._bus_send(
|
|
"ir.attachment/delete",
|
|
{
|
|
"id": attachment.id,
|
|
"message": (
|
|
{"id": message.id, "write_date": message.write_date} if message else None
|
|
),
|
|
},
|
|
)
|
|
self.unlink()
|
|
|
|
def _get_store_ownership_fields(self):
|
|
return [Store.Attr("ownership_token", lambda a: a._get_ownership_token())]
|
|
|
|
def _to_store_defaults(self, target):
|
|
return [
|
|
"checksum",
|
|
"create_date",
|
|
"file_size",
|
|
"has_thumbnail",
|
|
"mimetype",
|
|
"name",
|
|
Store.Attr("raw_access_token", lambda a: a._get_raw_access_token()),
|
|
"res_name",
|
|
"res_model",
|
|
Store.One("thread", [], as_thread=True),
|
|
Store.Attr("thumbnail_access_token", lambda a: a._get_thumbnail_token()),
|
|
"type",
|
|
"url",
|
|
]
|
|
|
|
def _get_ownership_token(self):
|
|
""" Returns a scoped limited access token that indicates ownership of the attachment when
|
|
using _has_attachments_ownership. If verified by verify_limited_field_access_token,
|
|
accessing the attachment bypasses the ACLs.
|
|
|
|
:rtype: str
|
|
"""
|
|
self.ensure_one()
|
|
return limited_field_access_token(self, field_name="id", scope="attachment_ownership")
|
|
|
|
def _get_thumbnail_token(self):
|
|
self.ensure_one()
|
|
return limited_field_access_token(self, "thumbnail", scope="binary")
|