Files
odoo_source/addons/bus/controllers/websocket.py
T
Xavier-Do ca8dc2d9b4 [IMP] base, website: small refactoring
Mainly to simplify website overrides and general api

closes odoo/odoo#121376

Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2023-06-10 11:14:12 +02:00

72 lines
3.3 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
import json
from werkzeug.exceptions import ServiceUnavailable
from odoo.http import Controller, request, route, SessionExpiredException
from odoo.addons.base.models.assetsbundle import AssetsBundle
from ..models.bus import channel_with_db
from ..websocket import WebsocketConnectionHandler
class WebsocketController(Controller):
@route('/websocket', type="http", auth="public", cors='*', websocket=True)
def websocket(self):
"""
Handle the websocket handshake, upgrade the connection if
successfull.
"""
is_headful_browser = request.httprequest.user_agent and 'Headless' not in request.httprequest.user_agent.string
if request.registry.in_test_mode() and is_headful_browser:
# Prevent browsers from interfering with the unittests
raise ServiceUnavailable()
return WebsocketConnectionHandler.open_connection(request)
@route('/websocket/health', type='http', auth='none', save_session=False)
def health(self):
data = json.dumps({
'status': 'pass',
})
headers = [('Content-Type', 'application/json'),
('Cache-Control', 'no-store')]
return request.make_response(data, headers)
@route('/websocket/peek_notifications', type='json', auth='public', cors='*')
def peek_notifications(self, channels, last, is_first_poll=False):
if not all(isinstance(c, str) for c in channels):
raise ValueError("bus.Bus only string channels are allowed.")
if is_first_poll:
# Used to detect when the current session is expired.
request.session['is_websocket_session'] = True
elif 'is_websocket_session' not in request.session:
raise SessionExpiredException()
channels = list(set(
channel_with_db(request.db, c)
for c in request.env['ir.websocket']._build_bus_channel_list(channels)
))
last_known_notification_id = request.env['bus.bus'].sudo().search([], limit=1, order='id desc').id or 0
if last > last_known_notification_id:
last = 0
notifications = request.env['bus.bus']._poll(channels, last)
return {'channels': channels, 'notifications': notifications}
@route('/websocket/update_bus_presence', type='json', auth='public', cors='*')
def update_bus_presence(self, inactivity_period, im_status_ids_by_model):
if 'is_websocket_session' not in request.session:
raise SessionExpiredException()
request.env['ir.websocket']._update_bus_presence(int(inactivity_period), im_status_ids_by_model)
return {}
@route('/bus/websocket_worker_bundle', type='http', auth='public', cors='*')
def get_websocket_worker_bundle(self, v=None): # pylint: disable=unused-argument
"""
:param str v: Version of the worker, frontend only argument used to
prevent new worker versions to be loaded from the browser cache.
"""
bundle = 'bus.websocket_worker_assets'
asset = request.env["ir.qweb"]._get_asset_bundle(bundle)
stream = request.env['ir.binary']._get_stream_from(asset.js(
is_minified="assets" not in request.session.debug
))
return stream.get_response()