NOW() ORDER BY created_at DESC LIMIT 1', (string) $tenantId ); $row = is_array($result) ? ($result['security_oauth_token_cache'] ?? $result) : null; if (!is_array($row) || !isset($row['access_token_encrypted'])) { return null; } $encrypted = trim((string) $row['access_token_encrypted']); if ($encrypted === '') { return null; } try { return $this->settingsCryptoGateway->decryptString($encrypted); } catch (\Throwable) { return null; } } public function storeToken(int $tenantId, string $accessToken, \DateTimeInterface $expiresAt): bool { if ($tenantId <= 0 || $accessToken === '') { return false; } try { $encrypted = $this->settingsCryptoGateway->encryptString($accessToken); } catch (\Throwable) { return false; } DB::delete('DELETE FROM security_oauth_token_cache WHERE tenant_id = ?', (string) $tenantId); return (bool) DB::insert( 'INSERT INTO security_oauth_token_cache (tenant_id, access_token_encrypted, expires_at) VALUES (?, ?, ?)', (string) $tenantId, $encrypted, $expiresAt->format('Y-m-d H:i:s') ); } /** * Clear all cached tokens — used when the global BC connection changes. * * @api Called from the Security settings page on connection change. */ public function deleteAll(): bool { return (bool) DB::delete('DELETE FROM security_oauth_token_cache WHERE 1=1'); } }