From e729f920139f0c65902be2d6b2c32466b08375e8 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 20 Oct 2025 17:54:52 +0000
Subject: [PATCH] =Form updates
---
inc/integrations/Integrations.php | 93 ++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 88 insertions(+), 5 deletions(-)
diff --git a/inc/integrations/Integrations.php b/inc/integrations/Integrations.php
index 76f0c56..5f47ff6 100644
--- a/inc/integrations/Integrations.php
+++ b/inc/integrations/Integrations.php
@@ -35,6 +35,7 @@
protected array $apiEndpoints = []; // Valid endpoint paths for this service
protected string $apiVersion = ''; // API version string (e.g., 'v2', '2024-01-01')
+ protected int $refresh_interval = 0; //seconds before expiry to refresh tokens. 0 to disable
/**
* OAuth Configuration
@@ -806,7 +807,9 @@
// Retry with backoff for server errors
if ($attempt < $this->maxRetries && !$this->isClientError($e)) {
- sleep($this->retryDelays[$attempt - 1] ?? 5);
+ $delay = pow(2, $attempt) * 1000000; // 2^attempt seconds in microseconds
+ $jitter = rand(0, $delay * 0.3); // Add 0-30% jitter
+ usleep($delay + $jitter);
} else {
break;
}
@@ -1341,10 +1344,21 @@
}
if (!empty($this->credentials)) {
- if ($this->isOAuthService && $this->hasOAuthCredentials() && !$this->isOAuthValid()) {
- $this->logDebug('OAuth token expired, attempting refresh');
- if (!$this->refreshOAuthToken()) {
- $this->logError('Failed to refresh OAuth token');
+ if ($this->isOAuthService && $this->hasOAuthCredentials()) {
+ // Check if token is expired first
+ if (!$this->isOAuthValid()) {
+ $this->logDebug('OAuth token expired, attempting refresh');
+ if (!$this->refreshOAuthToken()) {
+ $this->logError('Failed to refresh expired OAuth token');
+ }
+ }
+ // Check if we should proactively refresh (before expiry)
+ elseif ($this->shouldRefreshToken()) {
+ $this->logDebug('OAuth token should be refreshed proactively');
+ if (!$this->refreshOAuthToken()) {
+ $this->logError('Failed to proactively refresh OAuth token');
+ // Not critical - token is still valid
+ }
}
}
$this->initialize();
@@ -1786,6 +1800,75 @@
}
/**
+ * Check if token should be proactively refreshed
+ * Different from isOAuthValid() which checks if token is actually expired
+ */
+ protected function shouldRefreshToken(): bool
+ {
+ if (!$this->isOAuthService || $this->refresh_interval === 0) {
+ return false;
+ }
+
+ // If no expiry info, we can't proactively refresh
+ if (empty($this->credentials['expires_at'])) {
+ return false;
+ }
+
+ $expires_at = intval($this->credentials['expires_at']);
+ $time_until_expiry = $expires_at - time();
+
+ // Refresh if we're within the refresh interval window
+ return $time_until_expiry > 0 && $time_until_expiry <= $this->refresh_interval;
+ }
+ /**
+ * Get time until token refresh is recommended
+ * Useful for displaying in admin UI
+ */
+ public function getTimeUntilRefresh(): ?int
+ {
+ if ($this->refresh_interval === 0 || empty($this->credentials['expires_at'])) {
+ return null;
+ }
+
+ $expires_at = intval($this->credentials['expires_at']);
+ $refresh_at = $expires_at - $this->refresh_interval;
+ $time_until_refresh = $refresh_at - time();
+
+ return max(0, $time_until_refresh);
+ }
+
+ /**
+ * Get token freshness status
+ * Returns: 'fresh', 'should_refresh', 'expired', or 'no_expiry_info'
+ */
+ public function getTokenStatus(): string
+ {
+ if (!$this->isOAuthService) {
+ return 'not_oauth';
+ }
+
+ if (empty($this->credentials['access_token'])) {
+ return 'no_token';
+ }
+
+ if (empty($this->credentials['expires_at'])) {
+ return 'no_expiry_info';
+ }
+
+ $expires_at = intval($this->credentials['expires_at']);
+ $now = time();
+
+ if ($expires_at <= $now) {
+ return 'expired';
+ }
+
+ if ($this->shouldRefreshToken()) {
+ return 'should_refresh';
+ }
+
+ return 'fresh';
+ }
+ /**
* Refresh OAuth token
*/
protected function refreshOAuthToken(): bool
--
Gitblit v1.10.0