Files
odoo_source/addons/bus/models/ir_websocket.py
T
Julien Castiaux ad9bd90d7b [FIX] core, *: BaseModel overrides signatures
*: base, account, crm, hr, hr_attendance, test_access_rights

The various public methods of the ORM can be override in other models,
those overrides sometime don't implement the exact same signature as the
original method in the ORM. In this work we sanitize all the overrides
to ensure a better compatibility. The background objective is to make it
possible to call any public method using kwarg: `search(domain=[...])`.

* `search`, the first parameter was renamed from `args` to `domain` in
  0e9adf7 but the overrides were not updated.
* `invalidate_models` and `invalidate_recordset`, a new `flush=True`
  parameter was introduced in 9c3b9a4 but the overrides were not
  updated.
* `update`, there is a clash between the `update` method responsible for
  writing on a record and `update` in bus responsible to update the user
  presence. The bus method has been renamed so it doesn't clash with the
  ORM.

This sanitization comes with a new linter that verifies that all
overrides of BaseModel public methods share a compatible signature. The
linter has been disabled for `create`, `write` and `default_get` as too
many overrides don't respect the signature of BaseModel.

closes odoo/odoo#106999

Related: odoo/enterprise#34991
Signed-off-by: Julien Castiaux <juc@odoo.com>
2022-12-15 12:36:56 +01:00

61 lines
2.5 KiB
Python

from odoo import models
from odoo.http import SessionExpiredException
from odoo.service import security
from ..models.bus import dispatch
from ..websocket import wsrequest
class IrWebsocket(models.AbstractModel):
_name = 'ir.websocket'
_description = 'websocket message handling'
def _get_im_status(self, im_status_ids_by_model):
im_status = {}
if 'res.partner' in im_status_ids_by_model:
im_status['Partner'] = self.env['res.partner'].with_context(active_test=False).search_read(
[('id', 'in', im_status_ids_by_model['res.partner'])],
['im_status']
)
return im_status
def _build_bus_channel_list(self, channels):
"""
Return the list of channels to subscribe to. Override this
method to add channels in addition to the ones the client
sent.
:param channels: The channel list sent by the client.
"""
channels.append('broadcast')
return channels
def _subscribe(self, data):
if not all(isinstance(c, str) for c in data['channels']):
raise ValueError("bus.Bus only string channels are allowed.")
last_known_notification_id = self.env['bus.bus'].sudo().search([], limit=1, order='id desc').id or 0
if data['last'] > last_known_notification_id:
data['last'] = 0
channels = set(self._build_bus_channel_list(data['channels']))
dispatch.subscribe(channels, data['last'], self.env.registry.db_name, wsrequest.ws)
def _update_bus_presence(self, inactivity_period, im_status_ids_by_model):
if self.env.user and not self.env.user._is_public():
self.env['bus.presence'].update_presence(
inactivity_period,
identity_field='user_id',
identity_value=self.env.uid
)
im_status_notification = self._get_im_status(im_status_ids_by_model)
if im_status_notification:
self.env['bus.bus']._sendone(self.env.user.partner_id, 'mail.record/insert', im_status_notification)
@classmethod
def _authenticate(cls):
if wsrequest.session.uid is not None:
if not security.check_session(wsrequest.session, wsrequest.env):
wsrequest.session.logout(keep_db=True)
raise SessionExpiredException()
else:
public_user = wsrequest.env.ref('base.public_user')
wsrequest.update_env(user=public_user.id)