diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fae586..e4eaf18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- simplified storage for last used url and token + ## 0.6.6 - 2025-09-24 ### Changed diff --git a/gradle.properties b/gradle.properties index da96b92..dc031f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version=0.6.6 +version=0.7.0 group=com.coder.toolbox name=coder-toolbox \ No newline at end of file diff --git a/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt b/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt index d65484c..ed4854c 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt @@ -7,7 +7,6 @@ import com.coder.toolbox.sdk.ex.APIResponseException import com.coder.toolbox.sdk.v2.models.WorkspaceStatus import com.coder.toolbox.util.CoderProtocolHandler import com.coder.toolbox.util.DialogUi -import com.coder.toolbox.util.toURL import com.coder.toolbox.util.waitForTrue import com.coder.toolbox.util.withPath import com.coder.toolbox.views.Action @@ -364,8 +363,8 @@ class CoderRemoteProvider( if (shouldDoAutoSetup()) { try { CoderCliSetupContext.apply { - url = context.secrets.lastDeploymentURL.toURL() - token = context.secrets.lastToken + url = context.deploymentUrl + token = context.secrets.tokenFor(context.deploymentUrl) } CoderCliSetupWizardState.goToStep(WizardStep.CONNECT) return CoderCliSetupWizardPage( @@ -399,14 +398,15 @@ class CoderRemoteProvider( * Auto-login only on first the firs run if there is a url & token configured or the auth * should be done via certificates. */ - private fun shouldDoAutoSetup(): Boolean = firstRun && (context.secrets.canAutoLogin || !settings.requireTokenAuth) + private fun shouldDoAutoSetup(): Boolean = firstRun && (canAutoLogin() || !settings.requireTokenAuth) + + fun canAutoLogin(): Boolean = !context.secrets.tokenFor(context.deploymentUrl).isNullOrBlank() private fun onConnect(client: CoderRestClient, cli: CoderCLIManager) { // Store the URL and token for use next time. - context.secrets.lastDeploymentURL = client.url.toString() + context.settingsStore.updateLastUsedUrl(client.url) if (context.settingsStore.requireTokenAuth) { - context.secrets.lastToken = client.token ?: "" - context.secrets.storeTokenFor(client.url, context.secrets.lastToken) + context.secrets.storeTokenFor(client.url, client.token ?: "") context.logger.info("Deployment URL and token were stored and will be available for automatic connection") } else { context.logger.info("Deployment URL was stored and will be available for automatic connection") diff --git a/src/main/kotlin/com/coder/toolbox/CoderToolboxContext.kt b/src/main/kotlin/com/coder/toolbox/CoderToolboxContext.kt index baac820..ac3cbcc 100644 --- a/src/main/kotlin/com/coder/toolbox/CoderToolboxContext.kt +++ b/src/main/kotlin/com/coder/toolbox/CoderToolboxContext.kt @@ -36,17 +36,15 @@ data class CoderToolboxContext( * * In order of preference: * - * 1. Last used URL. - * 2. URL in settings. - * 3. CODER_URL. - * 4. URL in global cli config. + * 1. Last used URL from the settings. + * 2. Last used URL from the secrets store. + * 3. Default URL */ val deploymentUrl: URL get() { - if (this.secrets.lastDeploymentURL.isNotBlank()) { - return this.secrets.lastDeploymentURL.toURL() - } - return this.settingsStore.defaultURL.toURL() + return settingsStore.lastDeploymentURL?.takeIf { it.isNotBlank() }?.toURL() + ?: secrets.lastDeploymentURL.takeIf { it.isNotBlank() }?.toURL() + ?: settingsStore.defaultURL.toURL() } suspend fun logAndShowError(title: String, error: String) { diff --git a/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt b/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt index 0000ea6..9ac6438 100644 --- a/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt +++ b/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt @@ -8,6 +8,12 @@ import java.util.Locale.getDefault * Read-only interface for accessing Coder settings */ interface ReadOnlyCoderSettings { + + /** + * The last used deployment URL. + */ + val lastDeploymentURL: String? + /** * The default URL to show in the connection window. */ diff --git a/src/main/kotlin/com/coder/toolbox/store/CoderSecretsStore.kt b/src/main/kotlin/com/coder/toolbox/store/CoderSecretsStore.kt index a807b69..a5466b4 100644 --- a/src/main/kotlin/com/coder/toolbox/store/CoderSecretsStore.kt +++ b/src/main/kotlin/com/coder/toolbox/store/CoderSecretsStore.kt @@ -8,24 +8,11 @@ import java.net.URL * Provides Coder secrets backed by the secrets store service. */ class CoderSecretsStore(private val store: PluginSecretStore) { - private fun get(key: String): String = store[key] ?: "" - - private fun set(key: String, value: String) { - if (value.isBlank()) { - store.clear(key) - } else { - store[key] = value - } - } - - var lastDeploymentURL: String - get() = get("last-deployment-url") - set(value) = set("last-deployment-url", value) - var lastToken: String - get() = get("last-token") - set(value) = set("last-token", value) - val canAutoLogin: Boolean - get() = lastDeploymentURL.isNotBlank() && lastToken.isNotBlank() + @Deprecated( + message = "The URL is now stored the JSON backed settings store. Use CoderSettingsStore#lastDeploymentURL", + replaceWith = ReplaceWith("context.settingsStore.lastDeploymentURL") + ) + val lastDeploymentURL: String = store["last-deployment-url"] ?: "" fun tokenFor(url: URL): String? = store[url.host] diff --git a/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt b/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt index f770da8..66706ca 100644 --- a/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt +++ b/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt @@ -36,6 +36,7 @@ class CoderSettingsStore( ) : ReadOnlyTLSSettings // Properties implementation + override val lastDeploymentURL: String? get() = store[LAST_USED_URL] override val defaultURL: String get() = store[DEFAULT_URL] ?: "https://dev.coder.com" override val binarySource: String? get() = store[BINARY_SOURCE] override val binaryDirectory: String? get() = store[BINARY_DIRECTORY] @@ -155,6 +156,10 @@ class CoderSettingsStore( fun readOnly(): ReadOnlyCoderSettings = this // Write operations + fun updateLastUsedUrl(url: URL) { + store[LAST_USED_URL] = url.toString() + } + fun updateBinarySource(source: String) { store[BINARY_SOURCE] = source } diff --git a/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt b/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt index 5f8f5af..555c6b5 100644 --- a/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt +++ b/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt @@ -2,7 +2,7 @@ package com.coder.toolbox.store internal const val CODER_SSH_CONFIG_OPTIONS = "CODER_SSH_CONFIG_OPTIONS" -internal const val CODER_URL = "CODER_URL" +internal const val LAST_USED_URL = "lastDeploymentURL" internal const val DEFAULT_URL = "defaultURL" diff --git a/src/main/kotlin/com/coder/toolbox/views/DeploymentUrlStep.kt b/src/main/kotlin/com/coder/toolbox/views/DeploymentUrlStep.kt index be3d4d0..27e53f9 100644 --- a/src/main/kotlin/com/coder/toolbox/views/DeploymentUrlStep.kt +++ b/src/main/kotlin/com/coder/toolbox/views/DeploymentUrlStep.kt @@ -63,8 +63,8 @@ class DeploymentUrlStep( errorField.textState.update { context.i18n.pnotr("") } - urlField.textState.update { - context.secrets.lastDeploymentURL + urlField.contentState.update { + context.deploymentUrl.toString() } signatureFallbackStrategyField.checkedState.update {