From 00bf73cd4ab00e13e91593d901ad0099f0cd8691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 12 Feb 2019 11:14:44 +0000 Subject: [PATCH] [IMP] website_profile: add a specific route to access avatar of users Purpose of this commit is to give a specific route to access users image used as avatar in profile and various frontend applications. Indeed current web/image controller basically checks record access rights with current user. However in some cases we want to display user avatars even if current user cannot read user records, which is generally the case. Indeed res.users is a private and technical model. To solve that issue we add a controller for avatar. Basically published and frontend active user avatars are available. This commit is linked to task ID 1936153 and PR #30770. --- addons/website_profile/__init__.py | 1 + addons/website_profile/controllers/main.py | 59 +++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/addons/website_profile/__init__.py b/addons/website_profile/__init__.py index 8c67f893b37..632e0b78318 100644 --- a/addons/website_profile/__init__.py +++ b/addons/website_profile/__init__.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import controllers from . import models from . import controllers diff --git a/addons/website_profile/controllers/main.py b/addons/website_profile/controllers/main.py index b1a29efe708..92c69ae4c34 100644 --- a/addons/website_profile/controllers/main.py +++ b/addons/website_profile/controllers/main.py @@ -2,18 +2,34 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import base64 +import werkzeug import werkzeug.exceptions import werkzeug.urls import werkzeug.wrappers -from odoo import http +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): + # Profile # --------------------------------------------------- + + def _check_avatar_access(self, user_id, **post): + """ Base condition to see user avatar independently form access rights + is to see published users having karma, meaning they participated to + frontend applications like forum or elearning. """ + try: + user = request.env['res.users'].sudo().browse(user_id).exists() + except: + return False + if user: + return user.website_published and user.karma > 0 + return False + 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 \ @@ -41,6 +57,47 @@ class WebsiteProfile(http.Controller): 'edit_button_url_param': '', } + @http.route([ + '/profile/avatar/', + ], 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): + 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, + default_mimetype='image/png') + else: + status, headers, content = request.env['ir.http'].binary_content( + model='res.users', id=user_id, field=fname, + 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: + 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, 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 + @http.route(['/profile/user/'], type='http', auth="public", website=True) def view_user_profile(self, user_id, **post): user = self._check_user_profile_access(user_id)