Skip to content

Commit 3ac20d4

Browse files
committed
impl: store last used URL in Toolbox Settings Store
Context: Toolbox can store key/value pairs in two places: - a settings store which is backed by a clear text json file per each plugin - native keystore for sensitive data At the same time some of Coder's clients (ex: Netflix) would like to deploy at scale preconfigured settings for Toolbox. Most of the needed settings are part of json backed store except the last used URL. This PR reworks the code around the last used URL/token and moves the URL in the json backed store, making it easy to configure. At the same time we still support the pair stored in the native keystore for backward compatibility reasons.
1 parent 5d648ef commit 3ac20d4

File tree

8 files changed

+32
-18
lines changed

8 files changed

+32
-18
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Changed
6+
7+
- simplified storage for last used url and token
8+
59
## 0.6.6 - 2025-09-24
610

711
### Changed

src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import com.coder.toolbox.sdk.ex.APIResponseException
77
import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
88
import com.coder.toolbox.util.CoderProtocolHandler
99
import com.coder.toolbox.util.DialogUi
10-
import com.coder.toolbox.util.toURL
1110
import com.coder.toolbox.util.waitForTrue
1211
import com.coder.toolbox.util.withPath
1312
import com.coder.toolbox.views.Action
@@ -364,8 +363,8 @@ class CoderRemoteProvider(
364363
if (shouldDoAutoSetup()) {
365364
try {
366365
CoderCliSetupContext.apply {
367-
url = context.secrets.lastDeploymentURL.toURL()
368-
token = context.secrets.lastToken
366+
url = context.deploymentUrl
367+
token = context.secrets.tokenFor(context.deploymentUrl)
369368
}
370369
CoderCliSetupWizardState.goToStep(WizardStep.CONNECT)
371370
return CoderCliSetupWizardPage(
@@ -399,14 +398,16 @@ class CoderRemoteProvider(
399398
* Auto-login only on first the firs run if there is a url & token configured or the auth
400399
* should be done via certificates.
401400
*/
402-
private fun shouldDoAutoSetup(): Boolean = firstRun && (context.secrets.canAutoLogin || !settings.requireTokenAuth)
401+
private fun shouldDoAutoSetup(): Boolean = firstRun && (canAutoLogin() || !settings.requireTokenAuth)
402+
403+
fun canAutoLogin(): Boolean = !context.secrets.tokenFor(context.deploymentUrl).isNullOrBlank()
403404

404405
private fun onConnect(client: CoderRestClient, cli: CoderCLIManager) {
405406
// Store the URL and token for use next time.
406-
context.secrets.lastDeploymentURL = client.url.toString()
407+
context.settingsStore.updateLastUsedUrl(client.url)
407408
if (context.settingsStore.requireTokenAuth) {
408409
context.secrets.lastToken = client.token ?: ""
409-
context.secrets.storeTokenFor(client.url, context.secrets.lastToken)
410+
context.secrets.storeTokenFor(client.url, client.token ?: "")
410411
context.logger.info("Deployment URL and token were stored and will be available for automatic connection")
411412
} else {
412413
context.logger.info("Deployment URL was stored and will be available for automatic connection")

src/main/kotlin/com/coder/toolbox/CoderToolboxContext.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,15 @@ data class CoderToolboxContext(
3636
*
3737
* In order of preference:
3838
*
39-
* 1. Last used URL.
40-
* 2. URL in settings.
41-
* 3. CODER_URL.
42-
* 4. URL in global cli config.
39+
* 1. Last used URL from the settings.
40+
* 2. Last used URL from the secrets store.
41+
* 3. Default URL
4342
*/
4443
val deploymentUrl: URL
4544
get() {
46-
if (this.secrets.lastDeploymentURL.isNotBlank()) {
45+
if (!this.settingsStore.lastDeploymentURL.isNullOrBlank()) {
46+
return this.settingsStore.lastDeploymentURL!!.toURL()
47+
} else if (this.secrets.lastDeploymentURL.isNotBlank()) {
4748
return this.secrets.lastDeploymentURL.toURL()
4849
}
4950
return this.settingsStore.defaultURL.toURL()

src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ import java.util.Locale.getDefault
88
* Read-only interface for accessing Coder settings
99
*/
1010
interface ReadOnlyCoderSettings {
11+
12+
/**
13+
* The last used deployment URL.
14+
*/
15+
val lastDeploymentURL: String?
16+
1117
/**
1218
* The default URL to show in the connection window.
1319
*/

src/main/kotlin/com/coder/toolbox/store/CoderSecretsStore.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,11 @@ class CoderSecretsStore(private val store: PluginSecretStore) {
1818
}
1919
}
2020

21-
var lastDeploymentURL: String
21+
val lastDeploymentURL: String
2222
get() = get("last-deployment-url")
23-
set(value) = set("last-deployment-url", value)
2423
var lastToken: String
2524
get() = get("last-token")
2625
set(value) = set("last-token", value)
27-
val canAutoLogin: Boolean
28-
get() = lastDeploymentURL.isNotBlank() && lastToken.isNotBlank()
2926

3027
fun tokenFor(url: URL): String? = store[url.host]
3128

src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class CoderSettingsStore(
3636
) : ReadOnlyTLSSettings
3737

3838
// Properties implementation
39+
override val lastDeploymentURL: String? get() = store[LAST_USED_URL]
3940
override val defaultURL: String get() = store[DEFAULT_URL] ?: "https://dev.coder.com"
4041
override val binarySource: String? get() = store[BINARY_SOURCE]
4142
override val binaryDirectory: String? get() = store[BINARY_DIRECTORY]
@@ -155,6 +156,10 @@ class CoderSettingsStore(
155156
fun readOnly(): ReadOnlyCoderSettings = this
156157

157158
// Write operations
159+
fun updateLastUsedUrl(url: URL) {
160+
store[LAST_USED_URL] = url.toString()
161+
}
162+
158163
fun updateBinarySource(source: String) {
159164
store[BINARY_SOURCE] = source
160165
}

src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.coder.toolbox.store
22

33
internal const val CODER_SSH_CONFIG_OPTIONS = "CODER_SSH_CONFIG_OPTIONS"
44

5-
internal const val CODER_URL = "CODER_URL"
5+
internal const val LAST_USED_URL = "lastDeploymentURL"
66

77
internal const val DEFAULT_URL = "defaultURL"
88

src/main/kotlin/com/coder/toolbox/views/DeploymentUrlStep.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ class DeploymentUrlStep(
6363
errorField.textState.update {
6464
context.i18n.pnotr("")
6565
}
66-
urlField.textState.update {
67-
context.secrets.lastDeploymentURL
66+
urlField.contentState.update {
67+
context.deploymentUrl.toString()
6868
}
6969

7070
signatureFallbackStrategyField.checkedState.update {

0 commit comments

Comments
 (0)