From 1d70293093e6c26c02677a78b545b2ca7298d883 Mon Sep 17 00:00:00 2001 From: Nicolas Bayet Date: Mon, 25 Sep 2023 11:03:41 +0200 Subject: [PATCH] [REF] web_editor: move handle_history_divergence in tools.py As `handle_history_divergence` is not used in the controllers, it makes no sense to have it in `controllers/main.py`. task-3217965 closes odoo/odoo#136277 Signed-off-by: David Monjoie (dmo) --- addons/hr/models/hr_job.py | 2 +- addons/project/models/project_task.py | 2 +- addons/web_editor/controllers/main.py | 51 ------------------------ addons/web_editor/tools.py | 56 +++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 53 deletions(-) diff --git a/addons/hr/models/hr_job.py b/addons/hr/models/hr_job.py index 6698a441d84..be29f8f73bb 100644 --- a/addons/hr/models/hr_job.py +++ b/addons/hr/models/hr_job.py @@ -2,7 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ -from odoo.addons.web_editor.controllers.main import handle_history_divergence +from odoo.addons.web_editor.tools import handle_history_divergence class Job(models.Model): diff --git a/addons/project/models/project_task.py b/addons/project/models/project_task.py index f23d8661e5b..08e460bc396 100644 --- a/addons/project/models/project_task.py +++ b/addons/project/models/project_task.py @@ -8,7 +8,7 @@ from datetime import timedelta, datetime, time from odoo import api, Command, fields, models, tools, SUPERUSER_ID, _, _lt from odoo.addons.rating.models import rating_data -from odoo.addons.web_editor.controllers.main import handle_history_divergence +from odoo.addons.web_editor.tools import handle_history_divergence from odoo.exceptions import UserError, ValidationError, AccessError from odoo.osv import expression from odoo.tools.misc import get_lang diff --git a/addons/web_editor/controllers/main.py b/addons/web_editor/controllers/main.py index 7f439a896d5..2fbcfaa1a62 100644 --- a/addons/web_editor/controllers/main.py +++ b/addons/web_editor/controllers/main.py @@ -31,57 +31,6 @@ from ..models.ir_attachment import SUPPORTED_IMAGE_MIMETYPES logger = logging.getLogger(__name__) DEFAULT_LIBRARY_ENDPOINT = 'https://media-api.odoo.com' -diverging_history_regex = 'data-last-history-steps="([0-9,]+)"' - -# This method must be called in a context that has write access to the record as -# it will write to the bus. -def handle_history_divergence(record, html_field_name, vals): - # Do not handle history divergence if the field is not in the values. - if html_field_name not in vals: - return - incoming_html = vals[html_field_name] - incoming_history_matches = re.search(diverging_history_regex, incoming_html or '') - # When there is no incoming history id, it means that the value does not - # comes from the odoo editor or the collaboration was not activated. In - # project, it could come from the collaboration pad. In that case, we do not - # handle history divergences. - if request: - channel = (request.db, 'editor_collaboration', record._name, html_field_name, record.id) - if incoming_history_matches is None: - if request: - bus_data = { - 'model_name': record._name, - 'field_name': html_field_name, - 'res_id': record.id, - 'notificationName': 'html_field_write', - 'notificationPayload': {'last_step_id': None}, - } - request.env['bus.bus']._sendone(channel, 'editor_collaboration', bus_data) - return - incoming_history_ids = incoming_history_matches[1].split(',') - last_step_id = incoming_history_ids[-1] - - bus_data = { - 'model_name': record._name, - 'field_name': html_field_name, - 'res_id': record.id, - 'notificationName': 'html_field_write', - 'notificationPayload': {'last_step_id': last_step_id}, - } - if request: - request.env['bus.bus']._sendone(channel, 'editor_collaboration', bus_data) - - if record[html_field_name]: - server_history_matches = re.search(diverging_history_regex, record[html_field_name] or '') - # Do not check old documents without data-last-history-steps. - if server_history_matches: - server_last_history_id = server_history_matches[1].split(',')[-1] - if server_last_history_id not in incoming_history_ids: - logger.warning('The document was already saved from someone with a different history for model %r, field %r with id %r.', record._name, html_field_name, record.id) - raise ValidationError(_('The document was already saved from someone with a different history for model %r, field %r with id %r.', record._name, html_field_name, record.id)) - - # Save only the latest id. - vals[html_field_name] = incoming_html[0:incoming_history_matches.start(1)] + last_step_id + incoming_html[incoming_history_matches.end(1):] class Web_Editor(http.Controller): #------------------------------------------------------ diff --git a/addons/web_editor/tools.py b/addons/web_editor/tools.py index 9b3a844fb9d..00b77c399cc 100644 --- a/addons/web_editor/tools.py +++ b/addons/web_editor/tools.py @@ -3,6 +3,7 @@ import base64 import contextlib +import logging import re import requests @@ -10,8 +11,12 @@ from markupsafe import Markup from werkzeug.urls import url_encode from odoo import _ +from odoo.exceptions import ValidationError +from odoo.http import request from odoo.tools import image_process +logger = logging.getLogger(__name__) + # To detect if we have a valid URL or not valid_url_regex = r'^(http://|https://|//)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$' @@ -159,3 +164,54 @@ def get_video_thumbnail(video_url): if response and response.ok: return image_process(response.content) return None + +diverging_history_regex = 'data-last-history-steps="([0-9,]+)"' +# This method must be called in a context that has write access to the record as +# it will write to the bus. +def handle_history_divergence(record, html_field_name, vals): + # Do not handle history divergence if the field is not in the values. + if html_field_name not in vals: + return + incoming_html = vals[html_field_name] + incoming_history_matches = re.search(diverging_history_regex, incoming_html or '') + # When there is no incoming history id, it means that the value does not + # comes from the odoo editor or the collaboration was not activated. In + # project, it could come from the collaboration pad. In that case, we do not + # handle history divergences. + if request: + channel = (request.db, 'editor_collaboration', record._name, html_field_name, record.id) + if incoming_history_matches is None: + if request: + bus_data = { + 'model_name': record._name, + 'field_name': html_field_name, + 'res_id': record.id, + 'notificationName': 'html_field_write', + 'notificationPayload': {'last_step_id': None}, + } + request.env['bus.bus']._sendone(channel, 'editor_collaboration', bus_data) + return + incoming_history_ids = incoming_history_matches[1].split(',') + last_step_id = incoming_history_ids[-1] + + bus_data = { + 'model_name': record._name, + 'field_name': html_field_name, + 'res_id': record.id, + 'notificationName': 'html_field_write', + 'notificationPayload': {'last_step_id': last_step_id}, + } + if request: + request.env['bus.bus']._sendone(channel, 'editor_collaboration', bus_data) + + if record[html_field_name]: + server_history_matches = re.search(diverging_history_regex, record[html_field_name] or '') + # Do not check old documents without data-last-history-steps. + if server_history_matches: + server_last_history_id = server_history_matches[1].split(',')[-1] + if server_last_history_id not in incoming_history_ids: + logger.warning('The document was already saved from someone with a different history for model %r, field %r with id %r.', record._name, html_field_name, record.id) + raise ValidationError(_('The document was already saved from someone with a different history for model %r, field %r with id %r.', record._name, html_field_name, record.id)) + + # Save only the latest id. + vals[html_field_name] = incoming_html[0:incoming_history_matches.start(1)] + last_step_id + incoming_html[incoming_history_matches.end(1):]