[FIX] web_editor: do not use image when uploading document from URL

The goal of this commit is to forward port [the original commit] which
was introduced in 16.4 but, due to an error, has not been forward
ported.

Original commit message:
Since [1] when uploading images from URL the data is downloaded and then
hosted on the Odoo instance. As stated in its task (task-3129360) it
should not have been applied to document URLs.
Because of this, when hitting a CORS issue to fetch binary data, we try
to fetch the data through an `<img>` element by setting its `src` field
- which also fails when the data is not an image.

This commit makes the changes of [1] specific to image uploads and
restores the previous behavior for other files.

Steps to reproduce:
- Drop a "Text - Image" snippet.
- Double-click on the image.
- Go to the Documents tab.
- Click on "Add URL".
- Enter an example PDF URL.
E.g.: https://www.africau.edu/images/default/sample.pdf
- Click on "Add URL".

=> Fails because of a CORS issue.

[the original commit]: https://github.com/odoo/odoo/commit/238566d1dea29fd11353e7e6529d29843c4f658b
[1]: https://github.com/odoo/odoo/commit/943944dd249c15de870d6800d89e48d54a422e5a

task-3493618

closes odoo/odoo#163576

Signed-off-by: Romain Derie (rde) <rde@odoo.com>
This commit is contained in:
Benoit Socias
2024-04-26 18:54:39 +00:00
committed by Louis (loco)
parent d00c64e263
commit a4ea153932
2 changed files with 31 additions and 27 deletions
@@ -285,33 +285,10 @@ export class FileSelector extends Component {
}
async uploadUrl(url) {
await fetch(url).then(async result => {
const blob = await result.blob();
blob.id = new Date().getTime();
blob.name = new URL(url).pathname.split("/").findLast(s => s);
await this.uploadFiles([blob]);
}).catch(async () => {
await new Promise(resolve => {
// If it works from an image, use URL.
const imageEl = document.createElement("img");
imageEl.onerror = () => {
// This message is about the blob fetch failure.
// It is only displayed if the fallback did not work.
this.notificationService.add(_t("An error occurred while fetching the entered URL."), {
title: _t("Error"),
sticky: true,
});
resolve();
};
imageEl.onload = () => {
this.uploadService.uploadUrl(url, {
resModel: this.props.resModel,
resId: this.props.resId,
}, attachment => this.onUploaded(attachment)).then(resolve);
};
imageEl.src = url;
});
});
await this.uploadService.uploadUrl(url, {
resModel: this.props.resModel,
resId: this.props.resId,
}, attachment => this.onUploaded(attachment));
}
async onUploaded(attachment) {
@@ -142,6 +142,33 @@ export class ImageSelector extends FileSelector {
await this.uploadService.uploadFiles(files, { resModel: this.props.resModel, resId: this.props.resId, isImage: true }, (attachment) => this.onUploaded(attachment));
}
async uploadUrl(url) {
await fetch(url).then(async result => {
const blob = await result.blob();
blob.id = new Date().getTime();
blob.name = new URL(url).pathname.split("/").findLast(s => s);
await this.uploadFiles([blob]);
}).catch(async () => {
await new Promise(resolve => {
// If it works from an image, use URL.
const imageEl = document.createElement("img");
imageEl.onerror = () => {
// This message is about the blob fetch failure.
// It is only displayed if the fallback did not work.
this.notificationService.add(_t("An error occurred while fetching the entered URL."), {
title: _t("Error"),
sticky: true,
});
resolve();
};
imageEl.onload = () => {
super.uploadUrl(url).then(resolve);
};
imageEl.src = url;
});
});
}
validateUrl(...args) {
const { isValidUrl, path } = super.validateUrl(...args);
const isValidFileFormat = IMAGE_EXTENSIONS.some(format => path.endsWith(format));