summaryrefslogtreecommitdiff
path: root/addons/web_editor/controllers
diff options
context:
space:
mode:
authorSamuel Degueldre <sad@odoo.com>2020-08-12 10:15:51 +0000
committerSamuel Degueldre <sad@odoo.com>2020-09-16 07:01:15 +0000
commit7a1308b426f94b33e2bd55e5d58e661067e26ff3 (patch)
tree651d7c12b8175c995247eb9a6b520e4faf46687e /addons/web_editor/controllers
parenta2cee3e630634004b8aeeb0869aedadf99913647 (diff)
[IMP] web_editor, *: make media-dialog search odoo media-library
*: website, web_unsplash, website_blog We have recently created an odoo media library that exposes a public API for searching for open-source media, including dynamic SVGs that can be used with the dynamic background-shape system to create illustrations whose colors can be changed by the user. This commit adds the corresponding client-side functionalty: search for the images in the media-library, creating a corresponding attachment when selected, as well as an option to customize the colors of the dynamic SVGs. In the process, adaptations have been made in the web_unsplash module to avoid duplicating code and to adapt code that was making assumptions that are no longer valid. To make new users more aware of this feature, all default images have been hidden from the media-dialog, so that the user is prompted so search for images. Some tests and tours that were relying on having default images in the media-dialog (eg in website_blog) have been adapted to match. task-2316651 Linked to: odoo/iap-apps#235 closes odoo/odoo#56479 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Diffstat (limited to 'addons/web_editor/controllers')
-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