changes
This commit is contained in:
@@ -58,6 +58,12 @@ class FusionTaskSyncConfig(models.Model):
|
||||
active = fields.Boolean(default=True)
|
||||
last_sync = fields.Datetime('Last Successful Sync', readonly=True)
|
||||
last_sync_error = fields.Text('Last Error', readonly=True)
|
||||
remote_uid = fields.Integer(
|
||||
'Remote User ID', readonly=True, copy=False,
|
||||
help='Cached uid from the last successful authenticate(). Reused for '
|
||||
'execute_kw so we do not re-authenticate on every RPC (each '
|
||||
'authenticate writes a login-audit row on the remote). Cleared on '
|
||||
'auth failure or when the credentials change.')
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# JSON-RPC helpers (uses /jsonrpc dispatch, muted on receiving side)
|
||||
@@ -92,25 +98,50 @@ class FusionTaskSyncConfig(models.Model):
|
||||
_logger.warning("Task sync: timeout connecting to %s", self.url)
|
||||
return None
|
||||
|
||||
def _authenticate(self):
|
||||
"""Authenticate with the remote instance and return the uid."""
|
||||
def _authenticate(self, force=False):
|
||||
"""Return the remote uid.
|
||||
|
||||
Reuses the cached ``remote_uid`` so we do NOT call ``authenticate()``
|
||||
on every RPC — each authenticate triggers ``_login`` →
|
||||
``_update_last_login`` on the remote, which writes a login-audit row.
|
||||
``execute_kw`` re-checks the API key on every call, so reusing the uid
|
||||
is safe; it just skips the audit-row-producing handshake. Pass
|
||||
``force=True`` to bypass the cache (e.g. the Test Connection button).
|
||||
"""
|
||||
self.ensure_one()
|
||||
if self.remote_uid and not force:
|
||||
return self.remote_uid
|
||||
uid = self._jsonrpc('common', 'authenticate',
|
||||
[self.database, self.username, self.api_key, {}])
|
||||
if not uid:
|
||||
_logger.error("Task sync: authentication failed for %s", self.name)
|
||||
return uid
|
||||
if uid != self.remote_uid:
|
||||
self.sudo().write({'remote_uid': uid})
|
||||
return uid
|
||||
|
||||
def _rpc(self, model, method, args, kwargs=None):
|
||||
"""Execute a method on the remote instance via execute_kw."""
|
||||
"""Execute a method on the remote instance via execute_kw.
|
||||
|
||||
Uses the cached uid; on a remote error (e.g. the cached uid went
|
||||
stale) it clears the cache, re-authenticates once, and retries.
|
||||
"""
|
||||
self.ensure_one()
|
||||
uid = self._authenticate()
|
||||
if not uid:
|
||||
return None
|
||||
call_args = [self.database, uid, self.api_key, model, method, args]
|
||||
if kwargs:
|
||||
call_args.append(kwargs)
|
||||
return self._jsonrpc('object', 'execute_kw', call_args)
|
||||
for attempt in (1, 2):
|
||||
uid = self._authenticate(force=(attempt == 2))
|
||||
if not uid:
|
||||
return None
|
||||
call_args = [self.database, uid, self.api_key, model, method, args]
|
||||
if kwargs:
|
||||
call_args.append(kwargs)
|
||||
try:
|
||||
return self._jsonrpc('object', 'execute_kw', call_args)
|
||||
except UserError:
|
||||
if attempt == 2:
|
||||
raise
|
||||
# uid may be stale — drop the cache and retry with a fresh auth
|
||||
self.sudo().write({'remote_uid': False})
|
||||
return None
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Tech sync ID helpers
|
||||
@@ -173,7 +204,7 @@ class FusionTaskSyncConfig(models.Model):
|
||||
def action_test_connection(self):
|
||||
"""Test the connection to the remote instance."""
|
||||
self.ensure_one()
|
||||
uid = self._authenticate()
|
||||
uid = self._authenticate(force=True)
|
||||
if uid:
|
||||
remote_map = self._get_remote_tech_map()
|
||||
local_map = self._get_local_tech_map()
|
||||
|
||||
Reference in New Issue
Block a user