Skip to content

Commit 694c49b

Browse files
Merge main into feature/q-lsp-chat
2 parents 810c815 + 1d79d77 commit 694c49b

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ package software.aws.toolkits.jetbrains.services.amazonq.lsp.auth
55

66
import com.intellij.openapi.Disposable
77
import com.intellij.openapi.project.Project
8+
import com.intellij.util.concurrency.AppExecutorUtil
89
import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage
910
import software.aws.toolkits.core.TokenConnectionSettings
11+
import software.aws.toolkits.core.utils.getLogger
12+
import software.aws.toolkits.core.utils.warn
1013
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
1114
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
1215
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManagerListener
1316
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
17+
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState
1418
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProvider
1519
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProviderListener
1620
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
@@ -26,6 +30,9 @@ import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfileSe
2630
import software.aws.toolkits.jetbrains.utils.isQConnected
2731
import software.aws.toolkits.jetbrains.utils.isQExpired
2832
import java.util.concurrent.CompletableFuture
33+
import java.util.concurrent.ScheduledExecutorService
34+
import java.util.concurrent.ScheduledFuture
35+
import java.util.concurrent.TimeUnit
2936

3037
class DefaultAuthCredentialsService(
3138
private val project: Project,
@@ -34,7 +41,12 @@ class DefaultAuthCredentialsService(
3441
) : AuthCredentialsService,
3542
BearerTokenProviderListener,
3643
ToolkitConnectionManagerListener,
37-
QRegionProfileSelectedListener {
44+
QRegionProfileSelectedListener,
45+
Disposable {
46+
47+
private val scheduler: ScheduledExecutorService = AppExecutorUtil.getAppScheduledExecutorService()
48+
private var tokenSyncTask: ScheduledFuture<*>? = null
49+
private val tokenSyncIntervalSeconds = 10L
3850

3951
init {
4052
project.messageBus.connect(serverInstance).apply {
@@ -49,6 +61,47 @@ class DefaultAuthCredentialsService(
4961
updateConfiguration()
5062
}
5163
}
64+
65+
// Start periodic token sync
66+
startPeriodicTokenSync()
67+
}
68+
69+
private fun startPeriodicTokenSync() {
70+
tokenSyncTask = scheduler.scheduleWithFixedDelay(
71+
{
72+
try {
73+
if (isQConnected(project)) {
74+
if (isQExpired(project)) {
75+
val manager = ToolkitConnectionManager.getInstance(project)
76+
val connection = manager.activeConnectionForFeature(QConnection.getInstance()) ?: return@scheduleWithFixedDelay
77+
78+
// Try to refresh the token if it's in NEEDS_REFRESH state
79+
val tokenProvider = (connection.getConnectionSettings() as? TokenConnectionSettings)
80+
?.tokenProvider
81+
?.delegate
82+
?.let { it as? BearerTokenProvider } ?: return@scheduleWithFixedDelay
83+
84+
if (tokenProvider.state() == BearerTokenAuthState.NEEDS_REFRESH) {
85+
try {
86+
tokenProvider.resolveToken()
87+
// Now that the token is refreshed, update it in Flare
88+
updateTokenFromActiveConnection()
89+
} catch (e: Exception) {
90+
LOG.warn(e) { "Failed to refresh bearer token" }
91+
}
92+
}
93+
} else {
94+
updateTokenFromActiveConnection()
95+
}
96+
}
97+
} catch (e: Exception) {
98+
LOG.warn(e) { "Failed to sync bearer token to Flare" }
99+
}
100+
},
101+
tokenSyncIntervalSeconds,
102+
tokenSyncIntervalSeconds,
103+
TimeUnit.SECONDS
104+
)
52105
}
53106

54107
override fun updateTokenCredentials(accessToken: String, encrypted: Boolean): CompletableFuture<ResponseMessage> {
@@ -134,4 +187,13 @@ class DefaultAuthCredentialsService(
134187
server.updateConfiguration(payload)
135188
} ?: (CompletableFuture.failedFuture(IllegalStateException("LSP Server not running")))
136189
}
190+
191+
override fun dispose() {
192+
tokenSyncTask?.cancel(false)
193+
tokenSyncTask = null
194+
}
195+
196+
companion object {
197+
private val LOG = getLogger<DefaultAuthCredentialsService>()
198+
}
137199
}

0 commit comments

Comments
 (0)