This commit is contained in:
gsinghpal
2026-05-30 20:59:59 -04:00
parent 55da42e91f
commit 5c1f60b3b8
17 changed files with 147 additions and 56 deletions

View File

@@ -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()