Skip to content

Commit 2970c67

Browse files
committed
TODO
1 parent fcba274 commit 2970c67

12 files changed

+137
-75
lines changed

.idea/misc.xml

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/ide/jetbrains/toolbox/build.gradle.kts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License.AGPL.txt in the project root for license information.
4+
15
import com.github.jk1.license.filter.ExcludeTransitiveDependenciesFilter
26
import com.github.jk1.license.render.JsonReportRenderer
37
import org.jetbrains.intellij.pluginRepository.PluginRepositoryFactory
@@ -34,7 +38,7 @@ dependencies {
3438
implementation("com.connectrpc:connect-kotlin:0.6.0")
3539
// Java specific dependencies.
3640
implementation("com.connectrpc:connect-kotlin-google-java-ext:0.6.0")
37-
implementation("com.google.protobuf:protobuf-java:4.26.0")
41+
implementation("com.google.protobuf:protobuf-java:4.27.2")
3842
// WebSocket
3943
compileOnly("javax.websocket:javax.websocket-api:1.1")
4044
compileOnly("org.eclipse.jetty.websocket:websocket-api:9.4.54.v20240208")

components/ide/jetbrains/toolbox/src/main/kotlin/io/gitpod/toolbox/auth/GitpodAuthManager.kt

+28-39
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,44 @@ class GitpodAuthManager {
6060
manager.addEventListener {
6161
when (it.type) {
6262
AuthEvent.Type.LOGIN -> {
63-
logger.info("account ${it.accountId} logged in")
63+
logger.debug("account ${it.accountId} logged in")
64+
resetCurrentAccount(it.accountId)
6465
loginListeners.forEach { it() }
6566
}
67+
6668
AuthEvent.Type.LOGOUT -> {
67-
logger.info("account ${it.accountId} logged out")
69+
logger.debug("account ${it.accountId} logged out")
70+
resetCurrentAccount(it.accountId)
6871
logoutListeners.forEach { it() }
6972
}
7073
}
7174
}
7275
}
7376

77+
private fun resetCurrentAccount(accountId: String) {
78+
val account = manager.accountsWithStatus.find { it.account.id == accountId }?.account ?: return
79+
logger.debug("reset settings for ${account.getHost()}")
80+
Utils.gitpodSettings.resetSettings(account.getHost())
81+
}
82+
7483
fun getCurrentAccount(): GitpodAccount? {
75-
return manager.accountsWithStatus.firstOrNull()?.account
84+
return manager.accountsWithStatus.find { it.account.getHost() === Utils.gitpodSettings.gitpodHost }?.account
85+
}
86+
87+
fun loginWithHost(host: String): Boolean {
88+
if (getCurrentAccount()?.getHost() == host) {
89+
// TODO: validate token is still available
90+
return true
91+
}
92+
val account = manager.accountsWithStatus.find { it.account.getHost() == host }?.account
93+
if (account != null) {
94+
Utils.gitpodSettings.gitpodHost = host
95+
loginListeners.forEach { it() }
96+
// TODO: validate token is still available
97+
return true
98+
}
99+
Utils.openUrl(this.getOAuthLoginUrl(host))
100+
return false
76101
}
77102

78103
fun logout() {
@@ -135,48 +160,12 @@ class GitpodAccount(
135160
private val name: String,
136161
private val host: String
137162
) : Account {
138-
private val orgSelectedListeners: MutableList<(String) -> Unit> = mutableListOf()
139-
private val logger = LoggerFactory.getLogger(javaClass)
140163

141164
override fun getId() = id
142165
override fun getFullName() = name
143166
fun getCredentials() = credentials
144167
fun getHost() = host
145168

146-
private fun getStoreKey(key: String) = "USER:${id}:${key}"
147-
148-
var organizationId: String?
149-
get() = Utils.settingStore[getStoreKey("ORG")]
150-
set(value){
151-
if (value == null) {
152-
return
153-
}
154-
Utils.settingStore[getStoreKey("ORG")] = value
155-
orgSelectedListeners.forEach { it(value) }
156-
}
157-
158-
var preferEditor: String?
159-
get() = Utils.settingStore[getStoreKey("EDITOR")]
160-
set(value){
161-
if (value == null) {
162-
return
163-
}
164-
Utils.settingStore[getStoreKey("EDITOR")] = value
165-
}
166-
167-
var preferWorkspaceClass: String?
168-
get() = Utils.settingStore[getStoreKey("WS_CLS")]
169-
set(value){
170-
if (value == null) {
171-
return
172-
}
173-
Utils.settingStore[getStoreKey("WS_CLS")] = value
174-
}
175-
176-
fun onOrgSelected(listener: (String) -> Unit) {
177-
orgSelectedListeners.add(listener)
178-
}
179-
180169
fun encode(): String {
181170
return Json.encodeToString(this)
182171
}

components/ide/jetbrains/toolbox/src/main/kotlin/io/gitpod/toolbox/auth/GitpodOrganizationPage.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ class GitpodOrganizationPage(val authManager: GitpodAuthManager, val publicApi:
2929
val options = mutableListOf<AutocompleteItem>()
3030
options.addAll(organizations.map { org ->
3131
MenuItem(org.name, null, null) {
32-
authManager.getCurrentAccount()?.organizationId = org.id
32+
Utils.gitpodSettings.organizationId = org.id
3333
Utils.toolboxUi.hideUiPage(this)
3434
}
3535
})
36-
val orgName = organizations.find { it.id == authManager.getCurrentAccount()?.organizationId }?.name ?: ""
36+
val orgName = organizations.find { it.id == Utils.gitpodSettings.organizationId }?.name ?: ""
3737
AutocompleteTextField("Organization", orgName, options, 1.0f) {
3838
if (it.isNullOrEmpty()) {
3939
ValidationResult.Invalid("Organization is required")

components/ide/jetbrains/toolbox/src/main/kotlin/io/gitpod/toolbox/gateway/GitpodRemoteProvider.kt

+27-23
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ import io.gitpod.toolbox.auth.GitpodLoginPage
1616
import io.gitpod.toolbox.auth.GitpodOrganizationPage
1717
import io.gitpod.toolbox.components.GitpodIcon
1818
import io.gitpod.toolbox.components.SimpleButton
19+
import io.gitpod.toolbox.service.ConnectParams
1920
import io.gitpod.toolbox.service.GitpodPublicApiManager
2021
import io.gitpod.toolbox.service.Utils
22+
import io.gitpod.toolbox.service.getConnectParams
2123
import kotlinx.coroutines.launch
2224
import org.slf4j.LoggerFactory
2325
import java.net.URI
24-
import java.net.URLEncoder
2526

2627
class GitpodRemoteProvider(
2728
private val consumer: RemoteEnvironmentConsumer,
@@ -36,24 +37,29 @@ class GitpodRemoteProvider(
3637
private val environmentMap = mutableMapOf<String, GitpodRemoteProviderEnvironment>()
3738

3839
private val openInToolboxUriHandler = GitpodOpenInToolboxUriHandler { connectParams ->
40+
if (!authManger.loginWithHost(connectParams.gitpodHost)) {
41+
// TODO: store connectParams locally so that user doesn't need another dashboard click?
42+
return@GitpodOpenInToolboxUriHandler
43+
}
3944
Utils.toolboxUi.showPluginEnvironmentsPage()
40-
setEnvironmentVisibility(connectParams.workspaceId)
45+
setEnvironmentVisibility(connectParams)
4146
}
4247

4348
// TODO: multiple host support
44-
private fun setEnvironmentVisibility(workspaceId: String) {
49+
private fun setEnvironmentVisibility(connectParams: ConnectParams) {
50+
val workspaceId = connectParams.workspaceId
4551
logger.info("setEnvironmentVisibility $workspaceId")
4652
Utils.toolboxUi.showWindow()
4753
val env = environmentMap[workspaceId]
4854
if (env != null) {
4955
env.markActive()
50-
Utils.clientHelper.setAutoConnectOnEnvironmentReady(workspaceId, "GO-233.15026.17", "/workspace/empty")
56+
Utils.clientHelper.setAutoConnectOnEnvironmentReady(connectParams.uniqueID, "GO-241.18034.61", "/workspace/template-golang-cli")
5157
} else {
52-
GitpodRemoteProviderEnvironment(authManger, workspaceId, publicApi).apply {
58+
GitpodRemoteProviderEnvironment(authManger, connectParams, publicApi).apply {
5359
environmentMap[workspaceId] = this
5460
this.markActive()
5561
consumer.consumeEnvironments(listOf(this))
56-
Utils.clientHelper.setAutoConnectOnEnvironmentReady(workspaceId, "GO-233.15026.17", "/workspace/empty")
62+
Utils.clientHelper.setAutoConnectOnEnvironmentReady(workspaceId, "GO-241.18034.61", "/workspace/template-golang-cli")
5763
}
5864
}
5965
}
@@ -76,21 +82,14 @@ class GitpodRemoteProvider(
7682
if (workspaces.isEmpty()) {
7783
return@collect
7884
}
79-
// TODO: Remove me
80-
workspaces.forEach{
81-
val host = URLEncoder.encode("https://exp-migration.preview.gitpod-dev.com", "UTF-8")
82-
val workspaceId = URLEncoder.encode(it.id, "UTF-8")
83-
val debugWorkspace = "false"
84-
val newUri = "jetbrains://gateway/io.gitpod.toolbox.gateway/open-in-toolbox?host=${host}&workspaceId=${workspaceId}&debugWorkspace=${debugWorkspace}"
85-
logger.info("workspace ${it.id} $newUri")
86-
}
8785
consumer.consumeEnvironments(workspaces.map {
88-
val env = environmentMap[it.id]
86+
val connectParams = it.getConnectParams()
87+
val env = environmentMap[connectParams.uniqueID]
8988
if (env != null) {
9089
env
9190
} else {
92-
val newEnv = GitpodRemoteProviderEnvironment(authManger, it.id, publicApi)
93-
environmentMap[it.id] = newEnv
91+
val newEnv = GitpodRemoteProviderEnvironment(authManger, connectParams, publicApi)
92+
environmentMap[connectParams.uniqueID] = newEnv
9493
newEnv
9594
}
9695
})
@@ -99,9 +98,9 @@ class GitpodRemoteProvider(
9998
}
10099

101100
private fun startup() {
102-
val account = authManger.getCurrentAccount() ?: return
101+
authManger.getCurrentAccount() ?: return
103102
publicApi.setup()
104-
val orgId = account.organizationId
103+
val orgId = Utils.gitpodSettings.organizationId
105104
logger.info("user logged in, current selected org: $orgId")
106105
if (orgId != null) {
107106
Utils.dataManager.startWatchWorkspaces(publicApi)
@@ -111,14 +110,19 @@ class GitpodRemoteProvider(
111110
Utils.toolboxUi.showUiPage(organizationPage)
112111
}
113112
}
114-
authManger.getCurrentAccount()?.onOrgSelected {
115-
Utils.dataManager.startWatchWorkspaces(publicApi)
113+
Utils.gitpodSettings.onSettingsChanged { key, _ ->
114+
when (key) {
115+
GitpodSettings.SettingKey.ORGANIZATION_ID.name -> {
116+
Utils.dataManager.startWatchWorkspaces(publicApi)
117+
}
118+
}
116119
}
117120
}
118121

119122
override fun getOverrideUiPage(): UiPage? {
120-
logger.info("getOverrideUiPage")
121-
authManger.getCurrentAccount() ?: return loginPage
123+
val account = authManger.getCurrentAccount()
124+
logger.info("get override ui page for ${account?.getHost()}")
125+
account ?: return loginPage
122126
return null
123127
}
124128

components/ide/jetbrains/toolbox/src/main/kotlin/io/gitpod/toolbox/gateway/GitpodRemoteProviderEnvironment.kt

+7-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import io.gitpod.publicapi.v1.WorkspaceOuterClass
1414
import io.gitpod.publicapi.v1.WorkspaceOuterClass.WorkspacePhase
1515
import io.gitpod.toolbox.auth.GitpodAuthManager
1616
import io.gitpod.toolbox.components.SimpleButton
17+
import io.gitpod.toolbox.service.ConnectParams
1718
import io.gitpod.toolbox.service.GitpodPublicApiManager
1819
import io.gitpod.toolbox.service.Utils
1920
import kotlinx.coroutines.channels.BufferOverflow
@@ -24,15 +25,15 @@ import java.util.concurrent.CompletableFuture
2425

2526
class GitpodRemoteProviderEnvironment(
2627
private val authManager: GitpodAuthManager,
27-
private val workspaceId: String,
28+
private val connectParams: ConnectParams,
2829
private val publicApi: GitpodPublicApiManager,
2930
) : AbstractRemoteProviderEnvironment() {
3031
private val logger = LoggerFactory.getLogger(javaClass)
3132
private val actionList = Utils.observablePropertiesFactory.emptyObservableList<ActionDescription>();
3233
private val contentsViewFuture: CompletableFuture<EnvironmentContentsView> = CompletableFuture.completedFuture(
3334
GitpodSSHEnvironmentContentsView(
3435
authManager,
35-
workspaceId,
36+
connectParams,
3637
publicApi,
3738
)
3839
)
@@ -53,9 +54,9 @@ class GitpodRemoteProviderEnvironment(
5354
}
5455

5556
init {
56-
logger.info("==================GitpodRemoteProviderEnvironment.init $workspaceId")
57+
logger.info("==================GitpodRemoteProviderEnvironment.init ${connectParams.uniqueID}")
5758
Utils.coroutineScope.launch {
58-
Utils.dataManager.watchWorkspaceStatus(workspaceId) {
59+
Utils.dataManager.watchWorkspaceStatus(connectParams.workspaceId) {
5960
lastPhase = it.phase
6061
lastWSEnvState.tryEmit(WorkspaceEnvState(it.phase, isMarkActive))
6162
}
@@ -88,8 +89,8 @@ class GitpodRemoteProviderEnvironment(
8889
}
8990
}
9091

91-
override fun getId(): String = workspaceId
92-
override fun getName(): String = workspaceId
92+
override fun getId(): String = connectParams.uniqueID
93+
override fun getName(): String = connectParams.resolvedWorkspaceId
9394

9495
override fun getContentsView(): CompletableFuture<EnvironmentContentsView> = contentsViewFuture
9596

components/ide/jetbrains/toolbox/src/main/kotlin/io/gitpod/toolbox/gateway/GitpodSSHEnvironmentContentsView.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.jetbrains.toolbox.gateway.environments.ManualEnvironmentContentsView
88
import com.jetbrains.toolbox.gateway.environments.SshEnvironmentContentsView
99
import com.jetbrains.toolbox.gateway.ssh.SshConnectionInfo
1010
import io.gitpod.toolbox.auth.GitpodAuthManager
11+
import io.gitpod.toolbox.service.ConnectParams
1112
import io.gitpod.toolbox.service.GitpodConnectionProvider
1213
import io.gitpod.toolbox.service.GitpodPublicApiManager
1314
import io.gitpod.toolbox.service.Utils
@@ -17,7 +18,7 @@ import java.util.concurrent.CompletableFuture
1718

1819
class GitpodSSHEnvironmentContentsView(
1920
private val authManager: GitpodAuthManager,
20-
private val workspaceId: String,
21+
private val connectParams: ConnectParams,
2122
private val publicApi: GitpodPublicApiManager,
2223
) : SshEnvironmentContentsView, ManualEnvironmentContentsView {
2324
private var cancel = {}
@@ -27,7 +28,7 @@ class GitpodSSHEnvironmentContentsView(
2728

2829
override fun getConnectionInfo(): CompletableFuture<SshConnectionInfo> {
2930
return Utils.coroutineScope.future {
30-
val provider = GitpodConnectionProvider(authManager, workspaceId, publicApi)
31+
val provider = GitpodConnectionProvider(authManager, connectParams, publicApi)
3132
val (connInfo, cancel) = provider.connect()
3233
this@GitpodSSHEnvironmentContentsView.cancel = cancel
3334
return@future connInfo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) 2024 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License.AGPL.txt in the project root for license information.
4+
5+
package io.gitpod.toolbox.gateway
6+
7+
import io.gitpod.toolbox.service.Utils
8+
import org.slf4j.LoggerFactory
9+
10+
class GitpodSettings {
11+
private val logger = LoggerFactory.getLogger(javaClass)
12+
private val settingsChangedListeners: MutableList<(String, String) -> Unit> = mutableListOf()
13+
14+
private fun getStoreKey(key: SettingKey) = "GITPOD_SETTINGS:${key.name}"
15+
16+
private fun updateSetting(key: SettingKey, value: String) {
17+
logger.debug("updateSetting ${key.name}=$value")
18+
Utils.settingStore[getStoreKey(key)] = value
19+
settingsChangedListeners.forEach { it(key.name, value) }
20+
}
21+
22+
fun onSettingsChanged(listener: (String, String) -> Unit) {
23+
settingsChangedListeners.add(listener)
24+
}
25+
26+
var organizationId: String?
27+
get() {
28+
val value = Utils.settingStore[getStoreKey(SettingKey.ORGANIZATION_ID)]
29+
return if (value.isNullOrBlank()) null else value
30+
}
31+
set(value) {
32+
updateSetting(SettingKey.ORGANIZATION_ID, value ?: "")
33+
}
34+
35+
fun resetSettings(host: String = "gitpod.io") {
36+
logger.info("=============reset for $host")
37+
gitpodHost = host
38+
organizationId = ""
39+
}
40+
41+
var gitpodHost: String
42+
get() = Utils.settingStore[getStoreKey(SettingKey.GITPOD_HOST)] ?: "gitpod.io"
43+
set(value) {
44+
updateSetting(SettingKey.GITPOD_HOST, value)
45+
}
46+
47+
enum class SettingKey {
48+
ORGANIZATION_ID,
49+
GITPOD_HOST
50+
}
51+
}

components/ide/jetbrains/toolbox/src/main/kotlin/io/gitpod/toolbox/service/DataManager.kt

+4
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,7 @@ class DataManager {
8383
}
8484
}
8585
}
86+
87+
fun WorkspaceOuterClass.Workspace.getConnectParams(): ConnectParams {
88+
return ConnectParams("exp-migration.preview.gitpod-dev.com", id, false)
89+
}

0 commit comments

Comments
 (0)