diff options
| author | Thibault Delavallée <tde@odoo.com> | 2019-02-15 11:39:20 +0000 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2019-02-15 17:45:41 +0000 |
| commit | 1bb7b242c00a726bc5186b45dd97b37c4b988328 (patch) | |
| tree | 2fe373e604cd8188522e93db2a50fa2940742328 | |
| parent | e7b3535884640724a062db042c83a9d5ebca3c78 (diff) | |
[FIX] website_profile, website_slides: clean user avatar controller and add one for slides
Purpose of this commit is to
* clean user avatar controller and its calls;
* extract default image computation;
* add a controller to get slide image even when not having access to the slide
as all slide name and images are displayed even if not available to the
current user;
Commit linked to task ID 1941250 and PR #31133.
| -rw-r--r-- | addons/website_profile/controllers/main.py | 42 | ||||
| -rw-r--r-- | addons/website_profile/views/website_profile.xml | 2 | ||||
| -rw-r--r-- | addons/website_slides/controllers/main.py | 35 | ||||
| -rw-r--r-- | addons/website_slides/views/website_slides_templates.xml | 11 | ||||
| -rw-r--r-- | addons/website_slides/views/website_slides_templates_homepage.xml | 13 |
5 files changed, 67 insertions, 36 deletions
diff --git a/addons/website_profile/controllers/main.py b/addons/website_profile/controllers/main.py index 92c69ae4c34..c0d6a278a0b 100644 --- a/addons/website_profile/controllers/main.py +++ b/addons/website_profile/controllers/main.py @@ -10,7 +10,6 @@ import werkzeug.wrappers from odoo import http, modules, tools from odoo.http import request from odoo.osv import expression -from odoo.tools import limited_image_resize class WebsiteProfile(http.Controller): @@ -30,6 +29,20 @@ class WebsiteProfile(http.Controller): return user.website_published and user.karma > 0 return False + def _get_default_avatar(self, field, headers, width, height): + img_path = modules.get_module_resource('web', 'static/src/img', 'placeholder.png') + with open(img_path, 'rb') as f: + image = f.read() + content = base64.b64encode(image) + dictheaders = dict(headers) if headers else {} + dictheaders['Content-Type'] = 'image/png' + headers = list(dictheaders.items()) + if not (width or height): + suffix = field.split('_')[-1] if '_' in field else 'large' + if suffix in ('small', 'medium', 'large', 'big'): + content = getattr(tools, 'image_resize_image_%s' % suffix)(content) + return content + def _check_user_profile_access(self, user_id): user_sudo = request.env['res.users'].sudo().browse(user_id) if user_sudo.karma == 0 or not user_sudo.website_published or \ @@ -60,16 +73,18 @@ class WebsiteProfile(http.Controller): @http.route([ '/profile/avatar/<int:user_id>', ], type='http', auth="public", website=True, sitemap=False) - def get_user_profile_avatar(self, user_id=0, width=0, height=0, crop=False, avoid_if_small=False, upper_limit=False, **post): + def get_user_profile_avatar(self, user_id, field='image_large', width=0, height=0, crop=False, avoid_if_small=False, upper_limit=False, **post): + if field not in ('image_small', 'image_medium', 'image_large'): + return werkzeug.exceptions.Forbidden() + can_sudo = self._check_avatar_access(user_id, **post) - fname = post.get('field', 'image_medium') if can_sudo: status, headers, content = request.env['ir.http'].sudo().binary_content( - model='res.users', id=user_id, field=fname, + model='res.users', id=user_id, field=field, default_mimetype='image/png') else: status, headers, content = request.env['ir.http'].binary_content( - model='res.users', id=user_id, field=fname, + model='res.users', id=user_id, field=field, default_mimetype='image/png') if status == 301: return request.env['ir.http']._response_by_status(status, headers, content) @@ -77,19 +92,9 @@ class WebsiteProfile(http.Controller): return werkzeug.wrappers.Response(status=304) if not content: - img_path = modules.get_module_resource('web', 'static/src/img', 'placeholder.png') - with open(img_path, 'rb') as f: - image = f.read() - content = base64.b64encode(image) - dictheaders = dict(headers) if headers else {} - dictheaders['Content-Type'] = 'image/png' - headers = list(dictheaders.items()) - if not (width or height): - suffix = fname.split('_')[-1] - if suffix in ('small', 'medium', 'big'): - content = getattr(tools, 'image_resize_image_%s' % suffix)(content) - - content = limited_image_resize( + content = self._get_default_avatar(field, headers, width, height) + + content = tools.limited_image_resize( content, width=width, height=height, crop=crop, upper_limit=upper_limit, avoid_if_small=avoid_if_small) image_base64 = base64.b64decode(content) @@ -159,6 +164,7 @@ class WebsiteProfile(http.Controller): ranks = ranks.sorted(key=lambda b: b.karma_min) values = { 'ranks': ranks, + 'user': request.env.user, } return request.render("website_profile.rank_main", values) diff --git a/addons/website_profile/views/website_profile.xml b/addons/website_profile/views/website_profile.xml index 06562d0e697..471cbe6a3f8 100644 --- a/addons/website_profile/views/website_profile.xml +++ b/addons/website_profile/views/website_profile.xml @@ -299,7 +299,7 @@ Ranks & Badges </h1> <p> - Do not stop learning with Odoo. Collects points on the forum or the eLearning platform. Those points will make you reach new ranks. + Do not stop learning with <t t-esc="user.company_id.name"/>. Collects points on the forum or the eLearning platform. Those points will make you reach new ranks. </p> <p> <b>How do I earn badges?</b> When you finish a course, reach milestones, you're awarded badges. diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 6a75730daa0..ba36df3fd00 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -6,7 +6,7 @@ import itertools import logging import werkzeug -from odoo import http, _ +from odoo import http, modules, tools, _ from odoo.exceptions import AccessError, UserError from odoo.http import request from odoo.osv import expression @@ -14,7 +14,6 @@ from odoo.osv import expression from odoo.addons.http_routing.models.ir_http import slug from odoo.addons.website_profile.controllers.main import WebsiteProfile from odoo.addons.website.models.ir_http import sitemap_qs2dom -from odoo.tools import html2plaintext _logger = logging.getLogger(__name__) @@ -267,7 +266,7 @@ class WebsiteSlides(WebsiteProfile): 'message_post_hash': channel._sign_token(request.env.user.partner_id.id), 'message_post_pid': request.env.user.partner_id.id, 'last_message_id': last_message_data.get('id'), - 'last_message': html2plaintext(last_message_data.get('body', '')), + 'last_message': tools.html2plaintext(last_message_data.get('body', '')), 'last_rating_value': last_message_data.get('rating_value'), }) @@ -362,6 +361,36 @@ class WebsiteSlides(WebsiteProfile): return request.redirect('/web/login?redirect=/slides/slide/%s' % (slide.id)) return request.render("website.403") + @http.route('/slides/slide/<int:slide_id>/get_image', type='http', auth="public", website=True, sitemap=False) + def slide_get_image(self, slide_id, field='image_medium', width=0, height=0, crop=False, avoid_if_small=False, upper_limit=False): + # Protect infographics by limiting access to 256px (large) images + if field not in ('image_small', 'image_medium', 'image_large'): + return werkzeug.exceptions.Forbidden() + + slide = request.env['slide.slide'].sudo().browse(slide_id).exists() + if not slide: + raise werkzeug.exceptions.NotFound() + + status, headers, content = request.env['ir.http'].sudo().binary_content( + model='slide.slide', id=slide.id, field=field, + default_mimetype='image/png') + if status == 301: + return request.env['ir.http']._response_by_status(status, headers, content) + if status == 304: + return werkzeug.wrappers.Response(status=304) + + if not content: + content = self._get_default_avatar(field, headers, width, height) + + content = tools.limited_image_resize( + content, width=width, height=height, crop=crop, upper_limit=upper_limit, avoid_if_small=avoid_if_small) + + image_base64 = base64.b64decode(content) + headers.append(('Content-Length', len(image_base64))) + response = request.make_response(image_base64, headers) + response.status_code = status + return response + # JSONRPC @http.route('/slides/slide/like', type='json', auth="user", website=True) def slide_like(self, slide_id, upvote): diff --git a/addons/website_slides/views/website_slides_templates.xml b/addons/website_slides/views/website_slides_templates.xml index af82d23701c..abb22345538 100644 --- a/addons/website_slides/views/website_slides_templates.xml +++ b/addons/website_slides/views/website_slides_templates.xml @@ -268,7 +268,9 @@ </div> <div class="row" t-if="slide_promoted"> <div class="col-4"> - <img class="img img-fluid" t-att-src="'/web/image/slide.slide/%s/image' % slide_promoted.id"/> + <img class="img img-fluid" style="" + t-att-src="'/slides/slide/%s/get_image?field=image_large' % slide_promoted.id" + t-att-alt="slide_promoted.name"/> </div> <div class="col-8"> <div class="row"> @@ -318,10 +320,9 @@ <div class="row o_wslides_row mt8"> <div class="col-lg-3 col-md-6 col-12" t-foreach="slides" t-as="slide"> <div class="card o_wslides_lesson_card"> - <img class="card-img-top img-fuild" - style="max-height: 160px;" - t-att-src="'/web/image/slide.slide/%s/image_large' % slide.id if slide.image else '/website_slides/static/src/img/channel-default.jpg'" - t-att-alt="channel.name"/> + <img class="card-img-top img-fuild" style="max-height: 160px;" + t-att-src="'/slides/slide/%s/get_image?field=image_large' % slide.id" + t-att-alt="slide.name"/> <div class="card-body"> <h5 class="card-title" t-att-title="slide.name"> <t t-if="slide.is_preview or channel.is_member or is_slides_publisher"> diff --git a/addons/website_slides/views/website_slides_templates_homepage.xml b/addons/website_slides/views/website_slides_templates_homepage.xml index b41b75eb73e..cafcc9aa71a 100644 --- a/addons/website_slides/views/website_slides_templates_homepage.xml +++ b/addons/website_slides/views/website_slides_templates_homepage.xml @@ -312,7 +312,6 @@ <div class="col-2"> <t t-call="website_slides.slides_misc_user_image"> <t t-set="user" t-value="achievement.user_id"/> - <t t-set="record" t-value="channels_popular[:1]"/> </t> </div> <div class="col"> @@ -353,9 +352,7 @@ <span class="font-weight-bold text-muted o_wslides_home_circled" t-esc="counter"/> </div> <div class="col-2"> - <t t-call="website_slides.slides_misc_user_image"> - <t t-set="record" t-value="channels_popular[:1]"/> - </t> + <t t-call="website_slides.slides_misc_user_image"/> </div> <div class="col"> <span class="font-weight-bold" t-esc="user.name"/> @@ -370,9 +367,7 @@ <div class="o_wslides_home_aside"> <div class="row mt16 o_wslides_home_aside_title align-items-center"> <div class="col"> - <t t-call="website_slides.slides_misc_user_image"> - <t t-set="record" t-value="channels_popular[:1]"/> - </t> + <t t-call="website_slides.slides_misc_user_image"/> <a t-att-href="'/slides'" class="float-right">Edit</a> <h4 t-esc="user.name" class="font-weight-bold"/> <hr/> @@ -407,10 +402,10 @@ </div> </template> -<template id='slides_misc_user_image' name="Float Time"> +<template id='slides_misc_user_image' name="User Avatar"> <img t-att-class="img_class if img_class else 'rounded-circle float-left'" t-att-style="img_style if img_style else 'max-height: 32px;'" - t-att-src="'/profile/avatar/%s?field=image_medium%s' % (user.id, '&res_model=%s&res_id=%s' % (record._name, record.id) if record else '')" + t-att-src="'/profile/avatar/%s?field=image_medium' % user.id" t-att-alt="user.name"/> </template> |
