[IMP] mail: add decorator to extract guest

This PR adds the `add_guest_to_context` decorator in order to provide a generic
way to extract the guest from a request. It will be used to unified guest
extraction from cookie/param based on its provenance (external livechat/public
page).

This is better than the `pre_dispatch` method since it can be applied to
specific routes instead of adding this logic to every request.

part of task-3332628

closes odoo/odoo#130052

Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
This commit is contained in:
tsm-odoo
2023-08-09 13:20:53 +02:00
parent 8d039cafe3
commit cdc35aed74
17 changed files with 142 additions and 45 deletions
@@ -32,6 +32,7 @@ export const busService = {
let isUsingSharedWorker = browser.SharedWorker && !isIosApp();
const startTs = new Date().getTime();
const connectionInitializedDeferred = new Deferred();
let context = {};
/**
* Send a message to the worker.
@@ -170,6 +171,23 @@ export const busService = {
send("start");
isActive = true;
},
get context() {
return context;
},
/**
* Update the context to be sent with every websocket
* message.
*
* @param {object} newContext
*/
async updateContext(newContext) {
context = newContext;
if (!worker) {
startWorker();
await connectionInitializedDeferred;
}
send("update_context", context);
},
deleteChannel: (channel) => send("delete_channel", channel),
forceUpdateChannels: () => send("force_update_channels"),
trigger: bus.trigger.bind(bus),
@@ -11,7 +11,7 @@ import { debounce } from "@bus/workers/websocket_worker_utils";
/**
* Type of action that can be sent from the client to the worker.
*
* @typedef {'add_channel' | 'delete_channel' | 'force_update_channels' | 'initialize_connection' | 'send' | 'leave' | 'stop' | 'start' } WorkerAction
* @typedef {'add_channel' | 'delete_channel' | 'force_update_channels' | 'initialize_connection' | 'send' | 'leave' | 'stop' | 'start' | 'update_context'} WorkerAction
*/
export const WEBSOCKET_CLOSE_CODES = Object.freeze({
@@ -34,7 +34,7 @@ export const WEBSOCKET_CLOSE_CODES = Object.freeze({
});
// Should be incremented on every worker update in order to force
// update of the worker in browser cache.
export const WORKER_VERSION = "1.0.5";
export const WORKER_VERSION = "1.0.6";
const INITIAL_RECONNECT_DELAY = 1000;
const MAXIMUM_RECONNECT_DELAY = 60000;
@@ -61,6 +61,8 @@ export class WebsocketWorker {
this.lastChannelSubscription = null;
this.lastNotificationId = 0;
this.messageWaitQueue = [];
// Context to be attached to each websocket request
this._context = {};
this._forceUpdateChannels = debounce(this._forceUpdateChannels, 300, true);
this._onWebsocketClose = this._onWebsocketClose.bind(this);
@@ -143,6 +145,9 @@ export class WebsocketWorker {
return this._forceUpdateChannels();
case "initialize_connection":
return this._initializeConnection(client, data);
case "update_context":
this._context = data;
break;
}
}
@@ -392,9 +397,12 @@ export class WebsocketWorker {
* If the websocket is not open, enqueue the message and send it
* upon the next reconnection.
*
* @param {any} message Message to send to the server.
* @param {{event_name: string, data: any }} message Message to send to the server.
*/
_sendToServer(message) {
if (Object.keys(this._context).length > 0) {
message.context = this._context;
}
const payload = JSON.stringify(message);
if (!this._isWebsocketConnected()) {
this.messageWaitQueue.push(payload);
+13 -2
View File
@@ -756,6 +756,7 @@ class WebsocketRequest:
f'Invalid JSON data, {exc.args[0]}'
) from exc
data = jsonrequest.get('data')
context = jsonrequest.get('context')
self.session = self._get_session()
try:
@@ -770,11 +771,11 @@ class WebsocketRequest:
self.env = api.Environment(cr, self.session.uid, self.session.context)
threading.current_thread().uid = self.env.uid
service_model.retrying(
functools.partial(self._serve_ir_websocket, event_name, data),
functools.partial(self._serve_ir_websocket, event_name, data, context),
self.env,
)
def _serve_ir_websocket(self, event_name, data):
def _serve_ir_websocket(self, event_name, data, context=None):
"""
Delegate most of the processing to the ir.websocket model
which is extensible by applications. Directly call the
@@ -783,6 +784,8 @@ class WebsocketRequest:
"""
ir_websocket = self.env['ir.websocket']
ir_websocket._authenticate()
if context:
self.update_context(**context)
if event_name == 'subscribe':
ir_websocket._subscribe(data)
if event_name == 'update_presence':
@@ -800,6 +803,14 @@ class WebsocketRequest:
"""
Request.update_env(self, user, context, su)
def update_context(self, **overrides):
"""
Override the environment context of the current request with the
values of ``overrides``. To replace the entire context, please
use :meth:`~update_env` instead.
"""
self.update_env(context=dict(self.env.context, **overrides))
class WebsocketConnectionHandler:
SUPPORTED_VERSIONS = {'13'}
+3
View File
@@ -6,10 +6,12 @@ from odoo import _, http
from odoo.exceptions import AccessError
from odoo.http import request
from odoo.tools import consteq
from ..models.discuss.mail_guest import add_guest_to_context
class AttachmentController(http.Controller):
@http.route("/mail/attachment/upload", methods=["POST"], type="http", auth="public")
@add_guest_to_context
def mail_attachment_upload(self, ufile, thread_id, thread_model, is_pending=False, **kwargs):
env = request.env["ir.attachment"]._get_upload_env(thread_model, thread_id)
vals = {
@@ -41,6 +43,7 @@ class AttachmentController(http.Controller):
return request.make_json_response(attachmentData)
@http.route("/mail/attachment/delete", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_attachment_delete(self, attachment_id, access_token=None):
attachment_sudo = request.env["ir.attachment"].browse(int(attachment_id)).sudo().exists()
guest = request.env["mail.guest"]._get_guest_from_context()
@@ -4,6 +4,7 @@ from werkzeug.exceptions import NotFound
from odoo import http
from odoo.http import request
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class BinaryController(http.Controller):
@@ -13,6 +14,7 @@ class BinaryController(http.Controller):
type="http",
auth="public",
)
@add_guest_to_context
def discuss_channel_partner_avatar_128(self, channel_id, partner_id, **kwargs):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context(channel_id=channel_id)
partner_sudo = channel_member_sudo.env["res.partner"].browse(partner_id).exists()
@@ -35,6 +37,7 @@ class BinaryController(http.Controller):
@http.route(
"/discuss/channel/<int:channel_id>/guest/<int:guest_id>/avatar_128", methods=["GET"], type="http", auth="public"
)
@add_guest_to_context
def discuss_channel_guest_avatar_128(self, channel_id, guest_id, **kwargs):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context(channel_id=channel_id)
guest_sudo = channel_member_sudo.env["mail.guest"].browse(guest_id).exists()
@@ -57,6 +60,7 @@ class BinaryController(http.Controller):
@http.route(
"/discuss/channel/<int:channel_id>/attachment/<int:attachment_id>", methods=["GET"], type="http", auth="public"
)
@add_guest_to_context
def discuss_channel_attachment(self, channel_id, attachment_id, download=None, **kwargs):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=int(channel_id))
domain = [
@@ -75,6 +79,7 @@ class BinaryController(http.Controller):
type="http",
auth="public",
)
@add_guest_to_context
def discuss_channel_avatar_128(self, channel_id, **kwargs):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=channel_id)
domain = [("id", "=", channel_id)]
@@ -96,6 +101,7 @@ class BinaryController(http.Controller):
type="http",
auth="public",
)
@add_guest_to_context
def fetch_image(self, channel_id, attachment_id, width=0, height=0, **kwargs):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=channel_id)
domain = [
@@ -6,15 +6,18 @@ from odoo import http
from odoo.exceptions import UserError
from odoo.http import request
from odoo.tools import consteq
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class ChannelController(http.Controller):
@http.route("/discuss/channel/members", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def discuss_channel_members(self, channel_id, known_member_ids):
channel_member = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=channel_id)
return channel_member.channel_id.sudo().load_more_members(known_member_ids)
@http.route("/discuss/channel/add_guest_as_member", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def discuss_channel_add_guest_as_member(self, channel_id, channel_uuid):
channel_sudo = request.env["discuss.channel"].browse(int(channel_id)).sudo().exists()
if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, channel_uuid):
@@ -42,11 +45,13 @@ class ChannelController(http.Controller):
channel.write({"image_128": data})
@http.route("/discuss/channel/info", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def discuss_channel_info(self, channel_id):
member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context(channel_id=int(channel_id))
return member_sudo.channel_id._channel_info()
@http.route("/discuss/channel/messages", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def discuss_channel_messages(self, channel_id, before=None, after=None, limit=30, around=None):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=int(channel_id))
domain = [
@@ -60,16 +65,19 @@ class ChannelController(http.Controller):
return messages.message_format()
@http.route("/discuss/channel/pinned_messages", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def discuss_channel_pins(self, channel_id):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=int(channel_id))
return channel_member_sudo.channel_id.pinned_message_ids.sorted(key="pinned_at", reverse=True).message_format()
@http.route("/discuss/channel/set_last_seen_message", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def discuss_channel_mark_as_seen(self, channel_id, last_message_id, allow_older=False):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=int(channel_id))
return channel_member_sudo.channel_id._channel_seen(last_message_id, allow_older=allow_older)
@http.route("/discuss/channel/notify_typing", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def discuss_channel_notify_typing(self, channel_id, is_typing):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=int(channel_id))
channel_member_sudo._notify_typing(is_typing)
@@ -10,6 +10,7 @@ from odoo.exceptions import UserError
from odoo.http import request
from odoo.tools import consteq
from odoo.tools.misc import get_lang
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class PublicPageController(http.Controller):
@@ -22,6 +23,7 @@ class PublicPageController(http.Controller):
type="http",
auth="public",
)
@add_guest_to_context
def discuss_channel_chat_from_token(self, create_token, channel_name=None):
return self._response_discuss_channel_from_token(create_token=create_token, channel_name=channel_name)
@@ -34,12 +36,14 @@ class PublicPageController(http.Controller):
type="http",
auth="public",
)
@add_guest_to_context
def discuss_channel_meet_from_token(self, create_token, channel_name=None):
return self._response_discuss_channel_from_token(
create_token=create_token, channel_name=channel_name, default_display_mode="video_full_screen"
)
@http.route("/chat/<int:channel_id>/<string:invitation_token>", methods=["GET"], type="http", auth="public")
@add_guest_to_context
def discuss_channel_invitation(self, channel_id, invitation_token):
channel_sudo = request.env["discuss.channel"].browse(channel_id).sudo().exists()
if not channel_sudo or not channel_sudo.uuid or not consteq(channel_sudo.uuid, invitation_token):
@@ -47,6 +51,7 @@ class PublicPageController(http.Controller):
return self._response_discuss_channel_invitation(channel_sudo=channel_sudo)
@http.route("/discuss/channel/<int:channel_id>", methods=["GET"], type="http", auth="public")
@add_guest_to_context
def discuss_channel(self, channel_id):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=int(channel_id))
return self._response_discuss_public_template(channel_sudo=channel_member_sudo.channel_id)
+7
View File
@@ -5,10 +5,12 @@ from collections import defaultdict
from odoo import http
from odoo.http import request
from odoo.tools import file_open
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class RtcController(http.Controller):
@http.route("/mail/rtc/session/notify_call_members", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def session_call_notify(self, peer_notifications):
"""Sends content to other session of the same channel, only works if the user is the user of that session.
This is used to send peer to peer information between sessions.
@@ -33,6 +35,7 @@ class RtcController(http.Controller):
session_sudo._notify_peers(notifications)
@http.route("/mail/rtc/session/update_and_broadcast", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def session_update_and_broadcast(self, session_id, values):
"""Update a RTC session and broadcasts the changes to the members of its channel,
only works of the user is the user of that session.
@@ -52,6 +55,7 @@ class RtcController(http.Controller):
session._update_and_broadcast(values)
@http.route("/mail/rtc/channel/join_call", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def channel_call_join(self, channel_id, check_rtc_session_ids=None):
"""Joins the RTC call of a channel if the user is a member of that channel
:param int channel_id: id of the channel to join
@@ -60,6 +64,7 @@ class RtcController(http.Controller):
return channel_member_sudo._rtc_join_call(check_rtc_session_ids=check_rtc_session_ids)
@http.route("/mail/rtc/channel/leave_call", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def channel_call_leave(self, channel_id):
"""Disconnects the current user from a rtc call and clears any invitation sent to that user on this channel
:param int channel_id: id of the channel from which to disconnect
@@ -68,6 +73,7 @@ class RtcController(http.Controller):
return channel_member_sudo._rtc_leave_call()
@http.route("/mail/rtc/channel/cancel_call_invitation", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def channel_call_cancel_invitation(self, channel_id, member_ids=None):
"""
:param member_ids: members whose invitation is to cancel
@@ -91,6 +97,7 @@ class RtcController(http.Controller):
)
@http.route("/discuss/channel/ping", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def channel_ping(self, channel_id, rtc_session_id=None, check_rtc_session_ids=None):
channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context(channel_id=int(channel_id))
if rtc_session_id:
+2
View File
@@ -4,10 +4,12 @@ from werkzeug.exceptions import NotFound
from odoo import http
from odoo.http import request
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class GuestController(http.Controller):
@http.route("/mail/guest/update_name", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_guest_update_name(self, guest_id, name):
guest = request.env["mail.guest"]._get_guest_from_context()
guest_to_rename_sudo = guest.env["mail.guest"].browse(guest_id).sudo().exists()
+3
View File
@@ -2,10 +2,12 @@
from odoo import http
from odoo.http import request
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class LinkPreviewController(http.Controller):
@http.route("/mail/link_preview", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_link_preview(self, message_id, clear=None):
if not request.env["mail.link.preview"]._is_link_preview_enabled():
return
@@ -20,6 +22,7 @@ class LinkPreviewController(http.Controller):
guest.env["mail.link.preview"].sudo()._create_link_previews(message)
@http.route("/mail/link_preview/delete", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_link_preview_delete(self, link_preview_id):
guest = request.env["mail.guest"]._get_guest_from_context()
link_preview_sudo = guest.env["mail.link.preview"].sudo().search([("id", "=", int(link_preview_id))])
@@ -4,10 +4,12 @@ from werkzeug.exceptions import NotFound
from odoo import http
from odoo.http import request
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class MessageReactionController(http.Controller):
@http.route("/mail/message/reaction", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_message_add_reaction(self, message_id, content, action):
guest_sudo = request.env["mail.guest"]._get_guest_from_context().sudo()
message_sudo = guest_sudo.env["mail.message"].browse(int(message_id)).exists()
+3
View File
@@ -6,6 +6,7 @@ from werkzeug.exceptions import NotFound
from odoo import http
from odoo.http import request
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class ThreadController(http.Controller):
@@ -70,6 +71,7 @@ class ThreadController(http.Controller):
return {"attachment_ids", "body", "message_type", "partner_ids", "subtype_xmlid", "parent_id"}
@http.route("/mail/message/post", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_message_post(self, thread_model, thread_id, post_data, context=None):
guest = request.env["mail.guest"]._get_guest_from_context()
guest.env["ir.attachment"].browse(post_data.get("attachment_ids", []))._check_attachments_access(
@@ -109,6 +111,7 @@ class ThreadController(http.Controller):
return message_data
@http.route("/mail/message/update_content", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_message_update_content(self, message_id, body, attachment_ids, attachment_tokens=None, partner_ids=None):
guest = request.env["mail.guest"]._get_guest_from_context()
guest.env["ir.attachment"].browse(attachment_ids)._check_attachments_access(attachment_tokens)
+2
View File
@@ -4,10 +4,12 @@ from werkzeug.exceptions import NotFound
from odoo import http
from odoo.http import request
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class WebclientController(http.Controller):
@http.route("/mail/init_messaging", methods=["POST"], type="json", auth="public")
@add_guest_to_context
def mail_init_messaging(self):
if not request.env.user.sudo()._is_public():
return request.env.user.sudo(request.env.user.has_group("base.group_portal"))._init_messaging()
+6 -15
View File
@@ -1,6 +1,5 @@
from odoo import models
from odoo.http import request
from odoo.addons.bus.websocket import wsrequest
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
class IrWebsocket(models.AbstractModel):
@@ -17,16 +16,12 @@ class IrWebsocket(models.AbstractModel):
)
return im_status
@add_guest_to_context
def _build_bus_channel_list(self, channels):
# This method can either be called due to an http or a
# websocket request. The request itself is necessary to
# retrieve the current guest. Let's retrieve the proper
# request.
req = request or wsrequest
channels = list(channels) # do not alter original list
guest_sudo = self.env["mail.guest"]._get_guest_from_request(req).sudo()
guest_sudo = self.env["mail.guest"]._get_guest_from_context().sudo()
discuss_channels = self.env["discuss.channel"]
if req.session.uid:
if self.env.uid and not self.env.user._is_public():
discuss_channels = self.env.user.partner_id.channel_ids
elif guest_sudo:
discuss_channels = guest_sudo.channel_ids
@@ -35,15 +30,11 @@ class IrWebsocket(models.AbstractModel):
channels.append(discuss_channel)
return super()._build_bus_channel_list(channels)
@add_guest_to_context
def _update_bus_presence(self, inactivity_period, im_status_ids_by_model):
super()._update_bus_presence(inactivity_period, im_status_ids_by_model)
if not self.env.user or self.env.user._is_public():
# This method can either be called due to an http or a
# websocket request. The request itself is necessary to
# retrieve the current guest. Let's retrieve the proper
# request.
req = request or wsrequest
guest_sudo = self.env["mail.guest"]._get_guest_from_request(req).sudo()
guest_sudo = self.env["mail.guest"]._get_guest_from_context().sudo()
if not guest_sudo:
return
guest_sudo.env["bus.presence"].update_presence(
+52 -16
View File
@@ -2,12 +2,64 @@
import pytz
import uuid
from functools import wraps
from inspect import Parameter, signature
from odoo.tools import consteq
from odoo import _, api, fields, models
from odoo.http import request
from odoo.addons.base.models.res_partner import _tz_get
from odoo.exceptions import UserError
from odoo.addons.bus.models.bus_presence import AWAY_TIMER, DISCONNECTION_TIMER
from odoo.addons.bus.websocket import wsrequest
def add_guest_to_context(func):
""" Decorate a function to extract the guest from the request.
The guest is then available on the context of the current
request.
"""
@wraps(func)
def wrapper(self, *args, **kwargs):
req = request or wsrequest
guest = req.env["mail.guest"]._get_guest_from_context()
guest_token = kwargs.pop("guest_token", None)
if guest:
return func(self, *args, **kwargs)
token = (
guest_token
or req.httprequest.cookies.get(req.env["mail.guest"]._cookie_name)
or req.env.context.get("guest_token", "")
)
parts = token.split(req.env["mail.guest"]._cookie_separator)
if len(parts) == 2:
guest_id, guest_access_token = parts
guest = req.env["mail.guest"].browse(int(guest_id)).sudo().exists()
if not guest or not guest.access_token or not consteq(guest.access_token, guest_access_token):
guest = req.env["mail.guest"]
elif not guest.timezone:
timezone = req.env["mail.guest"]._get_timezone_from_request(req)
if timezone:
guest._update_timezone(timezone)
guest = guest.sudo(False)
req.update_context(guest=guest)
if hasattr(self, "env"):
self.env.context = {**self.env.context, "guest": guest}
return func(self, *args, **kwargs)
# Add the guest_token parameter to the wrapper signature
# so that it is not marked as being ignored. It will be
# popped before calling the wrapped function.
old_sig = signature(wrapper)
params = list(old_sig.parameters.values())
new_param_index = next((
index for index, param in enumerate(params)
if param.kind in [Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD]
), len(params))
new_param = Parameter("guest_token", Parameter.POSITIONAL_OR_KEYWORD, default=None)
params.insert(new_param_index, new_param)
wrapper.__signature__ = old_sig.replace(parameters=params)
return wrapper
class MailGuest(models.Model):
@@ -52,22 +104,6 @@ class MailGuest(models.Model):
return guest.with_context(guest=guest)
return self.env['mail.guest']
def _get_guest_from_request(self, request):
parts = request.httprequest.cookies.get(self._cookie_name, '').split(self._cookie_separator)
if len(parts) != 2:
return self.env['mail.guest']
guest_id, guest_access_token = parts
if not guest_id or not guest_access_token:
return self.env['mail.guest']
guest = self.env['mail.guest'].browse(int(guest_id)).sudo().exists()
if not guest or not guest.access_token or not consteq(guest.access_token, guest_access_token):
return self.env['mail.guest']
if not guest.timezone:
timezone = self._get_timezone_from_request(request)
if timezone:
guest._update_timezone(timezone)
return guest.sudo(False).with_context(guest=guest)
def _get_timezone_from_request(self, request):
timezone = request.httprequest.cookies.get('tz')
return timezone if timezone in pytz.all_timezones else False
+1 -1
View File
@@ -12,7 +12,7 @@ class MailMessage(models.Model):
self.ensure_one()
if self.env.user._is_public():
guest = self.env["mail.guest"]._get_guest_from_context()
return guest and self.model == "discuss.channel" and self.res_id in guest.channel_ids.ids
return guest and self.model == "discuss.channel" and self.res_id in guest.sudo().channel_ids.ids
return super()._validate_access_for_current_persona(operation)
def _message_format_extras(self, format_reply):
-8
View File
@@ -25,11 +25,3 @@ class IrHttp(models.AbstractModel):
'user_context': user_context,
})
return result
@classmethod
def _pre_dispatch(cls, rule, args):
"""Overriden to add the guest to the context if any."""
super()._pre_dispatch(rule, args)
guest = request.env["mail.guest"]._get_guest_from_request(request)
if guest:
request.update_context(guest=guest)