@@ -75,6 +75,7 @@ import java.awt.event.MouseListener
7575import java.awt.event.MouseMotionListener
7676import java.awt.font.TextAttribute
7777import java.awt.font.TextAttribute.UNDERLINE_ON
78+ import java.net.SocketTimeoutException
7879import javax.swing.Icon
7980import javax.swing.JTable
8081import javax.swing.JTextField
@@ -214,12 +215,12 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
214215 tfUrl = textField().resizableColumn().horizontalAlign(HorizontalAlign .FILL ).gap(RightGap .SMALL ).bindText(localWizardModel::coderURL).applyToComponent {
215216 addActionListener {
216217 poller?.cancel()
217- askTokenAndOpenSession()
218+ askTokenAndOpenSession(true )
218219 }
219220 }.component
220221 button(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.connect.text" )) {
221222 poller?.cancel()
222- askTokenAndOpenSession()
223+ askTokenAndOpenSession(true )
223224 }.applyToComponent {
224225 background = WelcomeScreenUIManager .getMainAssociatedComponentBackground()
225226 }
@@ -316,25 +317,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
316317 localWizardModel.coderURL = url
317318 localWizardModel.token = token
318319 tfUrl?.text = url
319-
320- poller?.cancel()
321- try {
322- coderClient.initClientSession(url.toURL(), token)
323- loginAndLoadWorkspace(token)
324- } catch (e: Exception ) {
325- when (e) {
326- is AuthenticationResponseException -> {
327- // probably the token is expired
328- askTokenAndOpenSession()
329- }
330-
331- else -> {
332- logger.warn(" An exception was encountered while opening ${localWizardModel.coderURL} . Reason: ${e.message} " )
333- localWizardModel.token = " "
334- }
335- }
336-
337- }
320+ loginAndLoadWorkspace(token, true )
338321 }
339322 }
340323 updateWorkspaceActions()
@@ -372,49 +355,44 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
372355 ActivityTracker .getInstance().inc()
373356 }
374357
375- private fun askTokenAndOpenSession () {
358+ private fun askTokenAndOpenSession (openBrowser : Boolean ) {
376359 // force bindings to be filled
377360 component.apply ()
378361
379- val pastedToken = askToken()
362+ val pastedToken = askToken(openBrowser )
380363 if (pastedToken.isNullOrBlank()) {
381364 return
382365 }
383- loginAndLoadWorkspace(pastedToken)
366+ // False so that subsequent authentication failures do not keep opening
367+ // the browser as it was already opened earlier.
368+ loginAndLoadWorkspace(pastedToken, false )
384369 }
385370
386- private fun loginAndLoadWorkspace (token : String ) {
387- try {
388- coderClient.initClientSession(localWizardModel.coderURL.toURL(), token)
389- if (! CoderSemVer .isValidVersion(coderClient.buildVersion)) {
390- notificationBanner.apply {
391- component.isVisible = true
392- showWarning(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.invalid.coder.version" , coderClient.buildVersion))
393- }
394- } else {
395- val coderVersion = CoderSemVer .parse(coderClient.buildVersion)
396- if (! coderVersion.isInClosedRange(CoderSupportedVersions .minCompatibleCoderVersion, CoderSupportedVersions .maxCompatibleCoderVersion)) {
397- notificationBanner.apply {
398- component.isVisible = true
399- showWarning(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.unsupported.coder.version" , coderClient.buildVersion))
400- }
401- }
371+ private fun loginAndLoadWorkspace (token : String , openBrowser : Boolean ) {
372+ LifetimeDefinition ().launchUnderBackgroundProgress(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.cli.downloader.dialog.title" ), canBeCancelled = false , isIndeterminate = true ) {
373+ this .indicator.apply {
374+ text = " Authenticating..."
402375 }
403- } catch (e: AuthenticationResponseException ) {
404- logger.error(" Could not authenticate on ${localWizardModel.coderURL} . Reason $e " )
405- return
406- }
407- appPropertiesService.setValue(CODER_URL_KEY , localWizardModel.coderURL)
408- appPropertiesService.setValue(SESSION_TOKEN , token)
409- val cliManager = CoderCLIManager (localWizardModel.coderURL.toURL(), coderClient.buildVersion)
410376
411- localWizardModel.apply {
412- this .token = token
413- buildVersion = coderClient.buildVersion
414- localCliPath = cliManager.localCli.toAbsolutePath().toString()
415- }
377+ try {
378+ authenticate(token)
379+ } catch (e: AuthenticationResponseException ) {
380+ logger.error(" Unable to authenticate to ${localWizardModel.coderURL} ; has your token expired?" , e)
381+ askTokenAndOpenSession(openBrowser)
382+ return @launchUnderBackgroundProgress
383+ } catch (e: SocketTimeoutException ) {
384+ logger.error(" Unable to connect to ${localWizardModel.coderURL} ; is it up?" , e)
385+ return @launchUnderBackgroundProgress
386+ }
387+
388+ val cliManager = CoderCLIManager (localWizardModel.coderURL.toURL(), coderClient.buildVersion)
389+
390+ localWizardModel.apply {
391+ this .token = token
392+ buildVersion = coderClient.buildVersion
393+ localCliPath = cliManager.localCli.toAbsolutePath().toString()
394+ }
416395
417- LifetimeDefinition ().launchUnderBackgroundProgress(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.cli.downloader.dialog.title" ), canBeCancelled = false , isIndeterminate = true ) {
418396 this .indicator.apply {
419397 isIndeterminate = false
420398 text = " Retrieving Workspaces..."
@@ -458,15 +436,18 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
458436 }
459437 }
460438
461- private fun askToken (): String? {
462- BrowserUtil .browse(localWizardModel.coderURL.toURL().withPath(" /login?redirect=%2Fcli-auth" ))
439+ private fun askToken (openBrowser : Boolean ): String? {
440+ val getTokenUrl = localWizardModel.coderURL.toURL().withPath(" /login?redirect=%2Fcli-auth" )
441+ if (openBrowser) {
442+ BrowserUtil .browse(getTokenUrl)
443+ }
463444 return invokeAndWaitIfNeeded(ModalityState .any()) {
464445 lateinit var sessionTokenTextField: JBTextField
465446
466447 val panel = panel {
467448 row {
468- label (CoderGatewayBundle .message(" gateway.connector.view.login.token.label" ))
469- sessionTokenTextField = textField().applyToComponent {
449+ browserLink (CoderGatewayBundle .message(" gateway.connector.view.login.token.label" ), getTokenUrl.toString( ))
450+ sessionTokenTextField = textField().bindText(localWizardModel::token). applyToComponent {
470451 minimumSize = Dimension (320 , - 1 )
471452 }.component
472453 }
@@ -491,6 +472,33 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
491472 }
492473 }
493474
475+ /* *
476+ * Check that the token is valid for the URL in the wizard and throw if not.
477+ * On success store the URL and token and display warning banners if
478+ * versions do not match.
479+ */
480+ private fun authenticate (token : String ) {
481+ coderClient.initClientSession(localWizardModel.coderURL.toURL(), token)
482+
483+ if (! CoderSemVer .isValidVersion(coderClient.buildVersion)) {
484+ notificationBanner.apply {
485+ component.isVisible = true
486+ showWarning(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.invalid.coder.version" , coderClient.buildVersion))
487+ }
488+ } else {
489+ val coderVersion = CoderSemVer .parse(coderClient.buildVersion)
490+ if (! coderVersion.isInClosedRange(CoderSupportedVersions .minCompatibleCoderVersion, CoderSupportedVersions .maxCompatibleCoderVersion)) {
491+ notificationBanner.apply {
492+ component.isVisible = true
493+ showWarning(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.unsupported.coder.version" , coderClient.buildVersion))
494+ }
495+ }
496+ }
497+
498+ appPropertiesService.setValue(CODER_URL_KEY , localWizardModel.coderURL)
499+ appPropertiesService.setValue(SESSION_TOKEN , token)
500+ }
501+
494502 private suspend fun loadWorkspaces () {
495503 val ws = withContext(Dispatchers .IO ) {
496504 val timeBeforeRequestingWorkspaces = System .currentTimeMillis()
@@ -809,4 +817,4 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
809817 companion object {
810818 val logger = Logger .getInstance(CoderWorkspacesStepView ::class .java.simpleName)
811819 }
812- }
820+ }
0 commit comments