diff --git a/src/main/kotlin/com/coder/toolbox/views/AuthWizardPage.kt b/src/main/kotlin/com/coder/toolbox/views/AuthWizardPage.kt index ad0a6de..ca92ed7 100644 --- a/src/main/kotlin/com/coder/toolbox/views/AuthWizardPage.kt +++ b/src/main/kotlin/com/coder/toolbox/views/AuthWizardPage.kt @@ -20,7 +20,7 @@ class AuthWizardPage( ) : CoderPage(context, context.i18n.ptrl("Authenticate to Coder")) { private val shouldAutoLogin = MutableStateFlow(initialAutoLogin) - private val signInStep = SignInStep(context) + private val signInStep = SignInStep(context, this::notify) private val tokenStep = TokenStep(context) private val connectStep = ConnectStep(context, shouldAutoLogin, this::notify, this::displaySteps, onConnect) diff --git a/src/main/kotlin/com/coder/toolbox/views/SignInStep.kt b/src/main/kotlin/com/coder/toolbox/views/SignInStep.kt index ffab7ae..488045e 100644 --- a/src/main/kotlin/com/coder/toolbox/views/SignInStep.kt +++ b/src/main/kotlin/com/coder/toolbox/views/SignInStep.kt @@ -1,6 +1,7 @@ package com.coder.toolbox.views import com.coder.toolbox.CoderToolboxContext +import com.coder.toolbox.util.toURL import com.coder.toolbox.views.state.AuthWizardState import com.jetbrains.toolbox.api.localization.LocalizableString import com.jetbrains.toolbox.api.ui.components.LabelField @@ -9,6 +10,7 @@ import com.jetbrains.toolbox.api.ui.components.TextField import com.jetbrains.toolbox.api.ui.components.TextType import com.jetbrains.toolbox.api.ui.components.ValidationErrorField import kotlinx.coroutines.flow.update +import java.net.MalformedURLException /** * A page with a field for providing the Coder deployment URL. @@ -16,7 +18,8 @@ import kotlinx.coroutines.flow.update * Populates with the provided URL, at which point the user can accept or * enter their own. */ -class SignInStep(private val context: CoderToolboxContext) : WizardStep { +class SignInStep(private val context: CoderToolboxContext, private val notify: (String, Throwable) -> Unit) : + WizardStep { private val urlField = TextField(context.i18n.ptrl("Deployment URL"), "", TextType.General) private val descriptionField = LabelField(context.i18n.pnotr("")) private val errorField = ValidationErrorField(context.i18n.pnotr("")) @@ -53,12 +56,28 @@ class SignInStep(private val context: CoderToolboxContext) : WizardStep { } else { url } - + try { + validateRawUrl(url) + } catch (e: MalformedURLException) { + notify("URL is invalid", e) + return false + } context.secrets.lastDeploymentURL = url AuthWizardState.goToNextStep() return true } + /** + * Throws [MalformedURLException] if the given string violates RFC-2396 + */ + private fun validateRawUrl(url: String) { + try { + url.toURL() + } catch (e: Exception) { + throw MalformedURLException(e.message) + } + } + override fun onBack() { // it's the first step. Can't go anywhere back from here }