Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c512e66

Browse files
Merge pull request #183 from coder/asher/existing-token
Read URL and token from config
2 parents 288a8a4 + d353e6a commit c512e66

File tree

4 files changed

+90
-17
lines changed

4 files changed

+90
-17
lines changed

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
### Added
88

99
- support for Gateway 2023
10+
- ability to use existing tokens rather than request a new one
1011

1112
### Fixed
1213

‎src/main/kotlin/com/coder/gateway/models/CoderWorkspacesWizardModel.kt‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ data class CoderWorkspacesWizardModel(
55
var token: String = "",
66
var buildVersion: String = "",
77
var localCliPath: String = "",
8-
var selectedWorkspace: WorkspaceAgentModel? = null
9-
)
8+
var selectedWorkspace: WorkspaceAgentModel? = null,
9+
var useExistingToken: Boolean = false
10+
)

‎src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt‎

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,7 @@ import com.intellij.ui.RelativeFont
4646
import com.intellij.ui.ToolbarDecorator
4747
import com.intellij.ui.components.JBTextField
4848
import com.intellij.ui.components.dialog
49-
import com.intellij.ui.dsl.builder.AlignX
50-
import com.intellij.ui.dsl.builder.AlignY
51-
import com.intellij.ui.dsl.builder.BottomGap
52-
import com.intellij.ui.dsl.builder.RightGap
53-
import com.intellij.ui.dsl.builder.TopGap
54-
import com.intellij.ui.dsl.builder.bindText
55-
import com.intellij.ui.dsl.builder.panel
49+
import com.intellij.ui.dsl.builder.*
5650
import com.intellij.ui.table.TableView
5751
import com.intellij.util.ui.ColumnInfo
5852
import com.intellij.util.ui.JBFont
@@ -76,8 +70,12 @@ import java.awt.event.MouseListener
7670
import java.awt.event.MouseMotionListener
7771
import java.awt.font.TextAttribute
7872
import java.awt.font.TextAttribute.UNDERLINE_ON
73+
import java.nio.file.Files
74+
import java.nio.file.Path
75+
import java.nio.file.Paths
7976
import java.net.SocketTimeoutException
8077
import javax.swing.Icon
78+
import javax.swing.JCheckBox
8179
import javax.swing.JTable
8280
import javax.swing.JTextField
8381
import javax.swing.ListSelectionModel
@@ -100,6 +98,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
10098
private val appPropertiesService: PropertiesComponent = service()
10199

102100
private var tfUrl: JTextField? = null
101+
private var cbExistingToken: JCheckBox? = null
103102
private var listTableModelOfWorkspaces = ListTableModel<WorkspaceAgentModel>(
104103
WorkspaceIconColumnInfo(""),
105104
WorkspaceNameColumnInfo("Name"),
@@ -201,13 +200,13 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
201200
font = JBFont.h3().asBold()
202201
icon = CoderIcons.LOGO_16
203202
}
204-
}.topGap(TopGap.SMALL).bottomGap(BottomGap.MEDIUM)
203+
}.topGap(TopGap.SMALL)
205204
row {
206205
cell(ComponentPanelBuilder.createCommentComponent(CoderGatewayBundle.message("gateway.connector.view.coder.workspaces.comment"), false, -1, true))
207206
}
208207
row {
209208
browserLink(CoderGatewayBundle.message("gateway.connector.view.login.documentation.action"), "https://coder.com/docs/coder-oss/latest/workspaces")
210-
}.bottomGap(BottomGap.MEDIUM)
209+
}
211210
row(CoderGatewayBundle.message("gateway.connector.view.login.url.label")) {
212211
tfUrl = textField().resizableColumn().align(AlignX.FILL).gap(RightGap.SMALL).bindText(localWizardModel::coderURL).applyToComponent {
213212
addActionListener {
@@ -225,6 +224,17 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
225224
}
226225
cell()
227226
}
227+
row {
228+
cbExistingToken = checkBox(CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label"))
229+
.bindSelected(localWizardModel::useExistingToken)
230+
.component
231+
}
232+
row {
233+
cell(ComponentPanelBuilder.createCommentComponent(
234+
CoderGatewayBundle.message("gateway.connector.view.login.existing-token.tooltip",
235+
CoderGatewayBundle.message("gateway.connector.view.login.existing-token.label")),
236+
false, -1, true))
237+
}
228238
row {
229239
scrollCell(toolbar.createPanel().apply {
230240
add(notificationBanner.component.apply { isVisible = false }, "South")
@@ -315,18 +325,71 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
315325
if (localWizardModel.coderURL.isNotBlank() && localWizardModel.token.isNotBlank()) {
316326
triggerWorkspacePolling(true)
317327
} else {
318-
val url = appPropertiesService.getValue(CODER_URL_KEY)
319-
val token = appPropertiesService.getValue(SESSION_TOKEN)
320-
if (!url.isNullOrBlank() && !token.isNullOrBlank()) {
328+
val (url, token) = readStorageOrConfig()
329+
if (!url.isNullOrBlank()) {
321330
localWizardModel.coderURL = url
322-
localWizardModel.token = token
323331
tfUrl?.text = url
332+
}
333+
if (!token.isNullOrBlank()) {
334+
localWizardModel.token = token
335+
}
336+
if (!url.isNullOrBlank() && !token.isNullOrBlank()) {
324337
loginAndLoadWorkspace(token, true)
325338
}
326339
}
327340
updateWorkspaceActions()
328341
}
329342

343+
/**
344+
* Return the URL and token from storage or the CLI config.
345+
*/
346+
private fun readStorageOrConfig(): Pair<String?, String?> {
347+
val url = appPropertiesService.getValue(CODER_URL_KEY)
348+
val token = appPropertiesService.getValue(SESSION_TOKEN)
349+
if (!url.isNullOrBlank() && !token.isNullOrBlank()) {
350+
return url to token
351+
}
352+
return readConfig()
353+
}
354+
355+
/**
356+
* Return the URL and token from the CLI config.
357+
*/
358+
private fun readConfig(): Pair<String?, String?> {
359+
val configDir = getConfigDir()
360+
logger.info("Reading config from $configDir")
361+
try {
362+
val url = Files.readString(configDir.resolve("url"))
363+
val token = Files.readString(configDir.resolve("session"))
364+
return url to token
365+
} catch (e: Exception) {
366+
return null to null // Probably has not configured the CLI yet.
367+
}
368+
}
369+
370+
/**
371+
* Return the config directory used by the CLI.
372+
*/
373+
private fun getConfigDir(): Path {
374+
var dir = System.getenv("CODER_CONFIG_DIR")
375+
if (!dir.isNullOrBlank()) {
376+
return Path.of(dir)
377+
}
378+
// The Coder CLI uses https://github.com/kirsle/configdir so this should
379+
// match how it behaves.
380+
return when(getOS()) {
381+
OS.WINDOWS -> Paths.get(System.getenv("APPDATA"), "coderv2")
382+
OS.MAC -> Paths.get(System.getenv("HOME"), "Library/Application Support/coderv2")
383+
else -> {
384+
dir = System.getenv("XDG_CACHE_HOME")
385+
if (!dir.isNullOrBlank()) {
386+
return Paths.get(dir, "coderv2")
387+
}
388+
return Paths.get(System.getenv("HOME"), ".config/coderv2")
389+
}
390+
}
391+
}
392+
330393
private fun updateWorkspaceActions() {
331394
goToDashboardAction.isEnabled = coderClient.isReady
332395
createWorkspaceAction.isEnabled = coderClient.isReady
@@ -442,8 +505,14 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
442505

443506
private fun askToken(openBrowser: Boolean): String? {
444507
val getTokenUrl = localWizardModel.coderURL.toURL().withPath("/login?redirect=%2Fcli-auth")
445-
if (openBrowser) {
508+
if (openBrowser&&!localWizardModel.useExistingToken) {
446509
BrowserUtil.browse(getTokenUrl)
510+
} else if (localWizardModel.useExistingToken) {
511+
val (url, token) = readConfig()
512+
if (url == localWizardModel.coderURL && !token.isNullOrBlank()) {
513+
logger.info("Injecting valid token from CLI config")
514+
localWizardModel.token = token
515+
}
447516
}
448517
var tokenFromUser: String? = null
449518
ApplicationManager.getApplication().invokeAndWait({

‎src/main/resources/messages/CoderGatewayBundle.properties‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ gateway.connector.description=Connects to a Coder Workspace dev environment so t
33
gateway.connector.action.text=Connect to Coder
44
gateway.connector.view.login.documentation.action=Learn more about Coder
55
gateway.connector.view.login.url.label=URL:
6+
gateway.connector.view.login.existing-token.label=Use existing token
7+
gateway.connector.view.login.existing-token.tooltip=Checking "{0}" will prevent the browser from being launched for generating a new token. Additionally, if a token is already configured for this URL via the CLI it will appear as the default and can be used as-is or replaced.
68
gateway.connector.view.login.token.dialog=Paste your token here:
79
gateway.connector.view.login.token.label=Session Token:
810
gateway.connector.view.coder.workspaces.header.text=Coder Workspaces
@@ -28,4 +30,4 @@ gateway.connector.recentconnections.title=Recent Coder Workspaces
2830
gateway.connector.recentconnections.new.wizard.button.tooltip=Open a new Coder Workspace
2931
gateway.connector.recentconnections.remove.button.tooltip=Remove from Recent Connections
3032
gateway.connector.recentconnections.terminal.button.tooltip=Open SSH Web Terminal
31-
gateway.connector.coder.connection.provider.title=Connecting to Coder workspace...
33+
gateway.connector.coder.connection.provider.title=Connecting to Coder workspace...

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /