[FIX] web_editor: duplicate attachments in html field

Before this commit, when an image was cropped in a record on which
multiple users were collaborating, multiple attachments would be created
for the same image (one per user).

Multiple attachments for the same image would also be created if the
user uploaded the same image multiple times in the same record.

This commit makes sure that, when about to create an attachment via the
'add_data', 'add_url' and 'modify_image' routes, if an attachment
already exists for the same field values, the existing attachment is
returned instead of creating a new one.

task-3524601

closes odoo/odoo#148556

X-original-commit: 0e2508388fc03b2ea7a4033e571d289efa4ac479
Signed-off-by: Nicolas Bayet (nby) <nby@odoo.com>
This commit is contained in:
Rodolpho Lima
2024-01-10 06:12:32 +00:00
parent 3dd8d8d329
commit cce80f4c73
2 changed files with 28 additions and 3 deletions
+27 -2
View File
@@ -34,6 +34,26 @@ DEFAULT_LIBRARY_ENDPOINT = 'https://media-api.odoo.com'
DEFAULT_OLG_ENDPOINT = 'https://olg.api.odoo.com'
def get_existing_attachment(IrAttachment, vals):
"""
Check if an attachment already exists for the same vals. Return it if
so, None otherwise.
"""
fields = dict(vals)
# Falsy res_id defaults to 0 on attachment creation.
fields['res_id'] = fields.get('res_id') or 0
raw, datas = fields.pop('raw', None), fields.pop('datas', None)
domain = [(field, '=', value) for field, value in fields.items()]
if fields.get('type') == 'url':
if 'url' not in fields:
return None
domain.append(('checksum', '=', False))
else:
if not (raw or datas):
return None
domain.append(('checksum', '=', IrAttachment._compute_checksum(raw or b64decode(datas))))
return IrAttachment.search(domain, limit=1) or None
class Web_Editor(http.Controller):
#------------------------------------------------------
# convert font into picture
@@ -355,7 +375,8 @@ class Web_Editor(http.Controller):
if not attachment_data['public']:
attachment.sudo().generate_access_token()
else:
attachment = IrAttachment.create(attachment_data)
attachment = get_existing_attachment(IrAttachment, attachment_data) \
or IrAttachment.create(attachment_data)
return attachment
@@ -530,7 +551,11 @@ class Web_Editor(http.Controller):
fields['res_id'] = res_id
if fields['mimetype'] == 'image/webp':
fields['name'] = re.sub(r'\.(jpe?g|png)$', '.webp', fields['name'], flags=re.I)
attachment = attachment.copy(fields)
existing_attachment = get_existing_attachment(request.env['ir.attachment'], fields)
if existing_attachment and not existing_attachment.url:
attachment = existing_attachment
else:
attachment = attachment.copy(fields)
if alt_data:
for size, per_type in alt_data.items():
reference_id = attachment.id
@@ -315,7 +315,7 @@ export class FileSelector extends Component {
}
async onUploaded(attachment) {
this.state.attachments = [attachment, ...this.state.attachments];
this.state.attachments = [attachment, ...this.state.attachments.filter(attach => attach.id !== attachment.id)];
this.selectAttachment(attachment);
if (!this.props.multiSelect) {
await this.props.save();