summaryrefslogtreecommitdiff
path: root/addons/web_editor/controllers/main.py
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web_editor/controllers/main.py')
-rw-r--r--addons/web_editor/controllers/main.py91
1 files changed, 78 insertions, 13 deletions
diff --git a/addons/web_editor/controllers/main.py b/addons/web_editor/controllers/main.py
index 5285af88c2c..e79751eeb79 100644
--- a/addons/web_editor/controllers/main.py
+++ b/addons/web_editor/controllers/main.py
@@ -4,18 +4,21 @@ import io
import logging
import re
import time
+import requests
import werkzeug.wrappers
from PIL import Image, ImageFont, ImageDraw
from lxml import etree
-from base64 import b64decode
+from base64 import b64decode, b64encode
from odoo.http import request
-from odoo import http, tools, _
+from odoo import http, tools, _, SUPERUSER_ID
+from odoo.addons.http_routing.models.ir_http import slug
from odoo.exceptions import UserError
-from odoo.modules.module import get_resource_path
+from odoo.modules.module import get_module_path, get_resource_path
+from odoo.tools.misc import file_open
logger = logging.getLogger(__name__)
-
+DEFAULT_LIBRARY_ENDPOINT = 'https://media-api.odoo.com'
class Web_Editor(http.Controller):
#------------------------------------------------------
@@ -505,24 +508,30 @@ class Web_Editor(http.Controller):
return '%s?access_token=%s' % (attachment.image_src, attachment.access_token)
@http.route(['/web_editor/shape/<module>/<path:filename>'], type='http', auth="public", website=True)
- def background_shape(self, module, filename, **kwargs):
+ def shape(self, module, filename, **kwargs):
"""
- Returns a color-customized background-shape.
+ Returns a color-customized svg (background shape or illustration).
"""
- shape_path = get_resource_path(module, 'static', 'shapes', filename)
- if shape_path:
- svg = open(shape_path, 'r').read()
- else:
- # Fallback to attachments for future migrations
- attachment = request.env['ir.attachment'].search([('url', '=like', request.httprequest.path)], limit=1)
+ svg = None
+ if module == 'illustration':
+ attachment = request.env['ir.attachment'].sudo().search([('url', '=like', request.httprequest.path), ('public', '=', True)], limit=1)
if not attachment:
raise werkzeug.exceptions.NotFound()
svg = b64decode(attachment.datas).decode('utf-8')
+ else:
+ shape_path = get_resource_path(module, 'static', 'shapes', filename)
+ if not shape_path:
+ raise werkzeug.exceptions.NotFound()
+ with tools.file_open(shape_path, 'r') as file:
+ svg = file.read()
user_colors = []
for key, color in kwargs.items():
- match = re.match('^c([12345])$', key)
+ match = re.match('^c([1-5])$', key)
if match:
+ # Check that color is hex or rgb(a) to prevent arbitrary injection
+ if not re.match(r'(?i)^#[0-9A-F]{6,8}$|^rgba?\(\d{1,3},\d{1,3},\d{1,3}(?:,[0-9.]{1,4})?\)$', color.replace(' ', '')):
+ raise werkzeug.exceptions.BadRequest()
user_colors.append([tools.html_escape(color), match.group(1)])
default_palette = {
@@ -545,3 +554,59 @@ class Web_Editor(http.Controller):
('Content-type', 'image/svg+xml'),
('Cache-control', 'max-age=%s' % http.STATIC_CACHE_LONG),
])
+
+ @http.route(['/web_editor/media_library_search'], type='json', auth="user", website=True)
+ def media_library_search(self, **params):
+ ICP = request.env['ir.config_parameter'].sudo()
+ endpoint = ICP.get_param('web_editor.media_library_endpoint', DEFAULT_LIBRARY_ENDPOINT)
+ params['dbuuid'] = ICP.get_param('database.uuid')
+ response = requests.post('%s/media-library/1/search' % endpoint, data=params)
+ if response.status_code == requests.codes.ok and response.headers['content-type'] == 'application/json':
+ return response.json()
+ else:
+ return {'error': response.status_code}
+
+ @http.route('/web_editor/save_library_media', type='json', auth='user', methods=['POST'])
+ def save_library_media(self, media):
+ """
+ Saves images from the media library as new attachments, making them
+ dynamic SVGs if needed.
+ media = {
+ <media_id>: {
+ 'query': 'space separated search terms',
+ 'is_dynamic_svg': True/False,
+ }, ...
+ }
+ """
+ attachments = []
+ ICP = request.env['ir.config_parameter'].sudo()
+ library_endpoint = ICP.get_param('web_editor.media_library_endpoint', DEFAULT_LIBRARY_ENDPOINT)
+
+ media_ids = ','.join(media.keys())
+ params = {
+ 'dbuuid': ICP.get_param('database.uuid'),
+ 'media_ids': media_ids,
+ }
+ response = requests.post('%s/media-library/1/download_urls' % library_endpoint, data=params)
+ if response.status_code != requests.codes.ok:
+ raise Exception(_("ERROR: couldn't get download urls from media library."))
+
+ for id, url in response.json().items():
+ req = requests.get(url)
+ name = '_'.join([media[id]['query'], url.split('/')[-1]])
+ # Need to bypass security check to write image with mimetype image/svg+xml
+ # ok because svgs come from whitelisted origin
+ context = {'binary_field_real_user': request.env['res.users'].sudo().browse([SUPERUSER_ID])}
+ attachment = request.env['ir.attachment'].sudo().with_context(context).create({
+ 'name': name,
+ 'mimetype': req.headers['content-type'],
+ 'datas': b64encode(req.content),
+ 'public': True,
+ 'res_model': 'ir.ui.view',
+ 'res_id': 0,
+ })
+ if media[id]['is_dynamic_svg']:
+ attachment['url'] = '/web_editor/shape/illustration/%s' % slug(attachment)
+ attachments.append(attachment._get_media_info())
+
+ return attachments