Files
odoo_source/addons/web_editor/models/ir_attachment.py
T
Benoit Socias 943944dd24 [IMP] web_editor, website_slides: keep data when adding URL attachments
When a URL is entered to add an attachment through the media dialog
a URL attachment is created. If the source material is removed the
attachment will not be reachable anymore.

This commit fetches the data and adds it as an uploaded file when
adding a URL image in website.
If the image binary cannot be fetched by the client (e.g. CORS), the
old approach is used instead.

This commit also adapts test tours which relied on the image's `src` to
verify if the entered URL had been taken into account by making them
rely on the image's `data-original-src` instead.

task-3129360

closes odoo/odoo#118877

Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2023-07-04 14:02:20 +02:00

86 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from werkzeug.urls import url_quote
from odoo import api, models, fields, tools
SUPPORTED_IMAGE_MIMETYPES = {
'image/gif': '.gif',
'image/jpe': '.jpe',
'image/jpeg': '.jpeg',
'image/jpg': '.jpg',
'image/png': '.png',
'image/svg+xml': '.svg',
}
class IrAttachment(models.Model):
_inherit = "ir.attachment"
local_url = fields.Char("Attachment URL", compute='_compute_local_url')
image_src = fields.Char(compute='_compute_image_src')
image_width = fields.Integer(compute='_compute_image_size')
image_height = fields.Integer(compute='_compute_image_size')
original_id = fields.Many2one('ir.attachment', string="Original (unoptimized, unresized) attachment")
def _compute_local_url(self):
for attachment in self:
if attachment.url:
attachment.local_url = attachment.url
else:
attachment.local_url = '/web/image/%s?unique=%s' % (attachment.id, attachment.checksum)
@api.depends('mimetype', 'url', 'name')
def _compute_image_src(self):
for attachment in self:
# Only add a src for supported images
if attachment.mimetype not in SUPPORTED_IMAGE_MIMETYPES:
attachment.image_src = False
continue
if attachment.type == 'url':
if attachment.url.startswith('/'):
# Local URL
attachment.image_src = attachment.url
else:
name = url_quote(attachment.name)
attachment.image_src = '/web/image/%s-redirect/%s' % (attachment.id, name)
else:
# Adding unique in URLs for cache-control
unique = attachment.checksum[:8]
if attachment.url:
# For attachments-by-url, unique is used as a cachebuster. They
# currently do not leverage max-age headers.
separator = '&' if '?' in attachment.url else '?'
attachment.image_src = '%s%sunique=%s' % (attachment.url, separator, unique)
else:
name = url_quote(attachment.name)
attachment.image_src = '/web/image/%s-%s/%s' % (attachment.id, unique, name)
@api.depends('datas')
def _compute_image_size(self):
for attachment in self:
try:
image = tools.base64_to_image(attachment.datas)
attachment.image_width = image.width
attachment.image_height = image.height
except Exception:
attachment.image_width = 0
attachment.image_height = 0
def _get_media_info(self):
"""Return a dict with the values that we need on the media dialog."""
self.ensure_one()
return self._read_format(['id', 'name', 'description', 'mimetype', 'checksum', 'url', 'type', 'res_id', 'res_model', 'public', 'access_token', 'image_src', 'image_width', 'image_height', 'original_id'])[0]
def _can_bypass_rights_on_media_dialog(self, **attachment_data):
""" This method is meant to be overridden, for instance to allow to
create image attachment despite the user not allowed to create
attachment, eg:
- Portal user uploading an image on the forum (bypass acl)
- Non admin user uploading an unsplash image (bypass binary/url check)
"""
return False