Movatterモバイル変換


[0]ホーム

URL:


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

Commitdb3ea7d

Browse files
authored
fix: show login screen when token expires during workspace polling (#83)
- in fact we will now jump to the login screen for any error other thansocket timeout because of an OS wake-up- this patch also contains a re-work of the REST API exception. Coderbackend sends very detailed messages with the reason for the http callsto be rejected. We now un-marshall those responses and fill theexception system with better details.
1 parent6f604bb commitdb3ea7d

File tree

6 files changed

+197
-63
lines changed

6 files changed

+197
-63
lines changed

‎CHANGELOG.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,21 @@
22

33
##Unreleased
44

5+
###Fixed
6+
7+
- login screen is shown instead of an empty list of workspaces when token expired
8+
59
##0.1.4 - 2025-04-11
610

711
###Fixed
812

9-
- SSH connection to a Workspace is no longer established only once
10-
- authorization wizard automatically goes to a previous screen when an error is encountered during connection to Coder deployment
13+
- SSH connection to a Workspace is no longer established only once
14+
- authorization wizard automatically goes to a previous screen when an error is encountered during connection to Coder
15+
deployment
1116

1217
###Changed
1318

14-
- action buttons on the token input step were swapped to achieve better keyboard navigation
19+
- action buttons on the token input step were swapped to achieve better keyboard navigation
1520
- URI`project_path` query parameter was renamed to`folder`
1621

1722
##0.1.3 - 2025-04-09

‎src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.coder.toolbox
22

33
importcom.coder.toolbox.cli.CoderCLIManager
44
importcom.coder.toolbox.sdk.CoderRestClient
5+
importcom.coder.toolbox.sdk.ex.APIResponseException
56
importcom.coder.toolbox.sdk.v2.models.WorkspaceStatus
67
importcom.coder.toolbox.util.CoderProtocolHandler
78
importcom.coder.toolbox.util.DialogUi
@@ -60,7 +61,7 @@ class CoderRemoteProvider(
6061
// If we have an error in the polling we store it here before going back to
6162
// sign-in page, so we can display it there. This is mainly because there
6263
// does not seem to be a mechanism to show errors on the environment list.
63-
privatevarpollError:Exception?=null
64+
privatevarerrorBuffer= mutableListOf<Throwable>()
6465

6566
// On the first load, automatically log in if we can.
6667
privatevar firstRun=true
@@ -141,14 +142,21 @@ class CoderRemoteProvider(
141142
client.setupSession()
142143
}else {
143144
context.logger.error(ex,"workspace polling error encountered")
144-
pollError= ex
145+
errorBuffer.add(ex)
145146
logout()
146147
break
147148
}
149+
}catch (ex:APIResponseException) {
150+
context.logger.error(ex,"error in contacting${client.url} while polling the available workspaces")
151+
errorBuffer.add(ex)
152+
logout()
153+
goToEnvironmentsPage()
154+
break
148155
}catch (ex:Exception) {
149156
context.logger.error(ex,"workspace polling error encountered")
150-
pollError= ex
157+
errorBuffer.add(ex)
151158
logout()
159+
goToEnvironmentsPage()
152160
break
153161
}
154162

@@ -300,15 +308,14 @@ class CoderRemoteProvider(
300308
if (client==null) {
301309
// When coming back to the application, authenticate immediately.
302310
val autologin= shouldDoAutoLogin()
303-
var autologinEx:Exception?=null
304311
context.secrets.lastToken.let { lastToken->
305312
context.secrets.lastDeploymentURL.let { lastDeploymentURL->
306313
if (autologin&& lastDeploymentURL.isNotBlank()&& (lastToken.isNotBlank()||!settings.requireTokenAuth)) {
307314
try {
308315
AuthWizardState.goToStep(WizardStep.LOGIN)
309316
returnAuthWizardPage(context,true, ::onConnect)
310317
}catch (ex:Exception) {
311-
autologinEx= ex
318+
errorBuffer.add(ex)
312319
}
313320
}
314321
}
@@ -317,11 +324,12 @@ class CoderRemoteProvider(
317324

318325
// Login flow.
319326
val authWizard=AuthWizardPage(context,false, ::onConnect)
320-
// We might have tried and failed to automatically log in.
321-
autologinEx?.let { authWizard.notify("Error logging in", it) }
322327
// We might have navigated here due to a polling error.
323-
pollError?.let { authWizard.notify("Error fetching workspaces", it) }
324-
328+
errorBuffer.forEach {
329+
authWizard.notify("Error encountered", it)
330+
}
331+
// and now reset the errors, otherwise we show it every time on the screen
332+
errorBuffer.clear()
325333
return authWizard
326334
}
327335
returnnull
@@ -336,7 +344,7 @@ class CoderRemoteProvider(
336344
// Currently we always remember, but this could be made an option.
337345
context.secrets.rememberMe=true
338346
this.client= client
339-
pollError=null
347+
errorBuffer.clear()
340348
pollJob?.cancel()
341349
pollJob= poll(client, cli)
342350
goToEnvironmentsPage()

‎src/main/kotlin/com/coder/toolbox/sdk/CoderRestClient.kt

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.coder.toolbox.sdk.convertors.OSConverter
77
importcom.coder.toolbox.sdk.convertors.UUIDConverter
88
importcom.coder.toolbox.sdk.ex.APIResponseException
99
importcom.coder.toolbox.sdk.v2.CoderV2RestFacade
10+
importcom.coder.toolbox.sdk.v2.models.ApiErrorResponse
1011
importcom.coder.toolbox.sdk.v2.models.BuildInfo
1112
importcom.coder.toolbox.sdk.v2.models.CreateWorkspaceBuildRequest
1213
importcom.coder.toolbox.sdk.v2.models.Template
@@ -24,6 +25,7 @@ import com.coder.toolbox.util.getOS
2425
importcom.squareup.moshi.Moshi
2526
importokhttp3.Credentials
2627
importokhttp3.OkHttpClient
28+
importretrofit2.Response
2729
importretrofit2.Retrofit
2830
importretrofit2.converter.moshi.MoshiConverterFactory
2931
importjava.net.HttpURLConnection
@@ -55,6 +57,7 @@ open class CoderRestClient(
5557
privatevalpluginVersion:String ="development",
5658
) {
5759
privateval settings= context.settingsStore.readOnly()
60+
privatelateinitvar moshi:Moshi
5861
privatelateinitvar httpClient:OkHttpClient
5962
privatelateinitvar retroRestClient:CoderV2RestFacade
6063

@@ -66,7 +69,7 @@ open class CoderRestClient(
6669
}
6770

6871
funsetupSession() {
69-
valmoshi=
72+
moshi=
7073
Moshi.Builder()
7174
.add(ArchConverter())
7275
.add(InstantConverter())
@@ -152,7 +155,7 @@ open class CoderRestClient(
152155
suspendfunme():User {
153156
val userResponse= retroRestClient.me()
154157
if (!userResponse.isSuccessful) {
155-
throwAPIResponseException("authenticate", url, userResponse)
158+
throwAPIResponseException("authenticate", url, userResponse.code(), userResponse.parseErrorBody(moshi))
156159
}
157160

158161
return userResponse.body()!!
@@ -165,7 +168,12 @@ open class CoderRestClient(
165168
suspendfunworkspaces():List<Workspace> {
166169
val workspacesResponse= retroRestClient.workspaces("owner:me")
167170
if (!workspacesResponse.isSuccessful) {
168-
throwAPIResponseException("retrieve workspaces", url, workspacesResponse)
171+
throwAPIResponseException(
172+
"retrieve workspaces",
173+
url,
174+
workspacesResponse.code(),
175+
workspacesResponse.parseErrorBody(moshi)
176+
)
169177
}
170178

171179
return workspacesResponse.body()!!.workspaces
@@ -178,7 +186,12 @@ open class CoderRestClient(
178186
suspendfunworkspace(workspaceID:UUID):Workspace {
179187
val workspacesResponse= retroRestClient.workspace(workspaceID)
180188
if (!workspacesResponse.isSuccessful) {
181-
throwAPIResponseException("retrieve workspace", url, workspacesResponse)
189+
throwAPIResponseException(
190+
"retrieve workspace",
191+
url,
192+
workspacesResponse.code(),
193+
workspacesResponse.parseErrorBody(moshi)
194+
)
182195
}
183196

184197
return workspacesResponse.body()!!
@@ -209,15 +222,25 @@ open class CoderRestClient(
209222
val resourcesResponse=
210223
retroRestClient.templateVersionResources(workspace.latestBuild.templateVersionID)
211224
if (!resourcesResponse.isSuccessful) {
212-
throwAPIResponseException("retrieve resources for${workspace.name}", url, resourcesResponse)
225+
throwAPIResponseException(
226+
"retrieve resources for${workspace.name}",
227+
url,
228+
resourcesResponse.code(),
229+
resourcesResponse.parseErrorBody(moshi)
230+
)
213231
}
214232
return resourcesResponse.body()!!
215233
}
216234

217235
suspendfunbuildInfo():BuildInfo {
218236
val buildInfoResponse= retroRestClient.buildInfo()
219237
if (!buildInfoResponse.isSuccessful) {
220-
throwAPIResponseException("retrieve build information", url, buildInfoResponse)
238+
throwAPIResponseException(
239+
"retrieve build information",
240+
url,
241+
buildInfoResponse.code(),
242+
buildInfoResponse.parseErrorBody(moshi)
243+
)
221244
}
222245
return buildInfoResponse.body()!!
223246
}
@@ -228,7 +251,12 @@ open class CoderRestClient(
228251
privatesuspendfuntemplate(templateID:UUID):Template {
229252
val templateResponse= retroRestClient.template(templateID)
230253
if (!templateResponse.isSuccessful) {
231-
throwAPIResponseException("retrieve template with ID$templateID", url, templateResponse)
254+
throwAPIResponseException(
255+
"retrieve template with ID$templateID",
256+
url,
257+
templateResponse.code(),
258+
templateResponse.parseErrorBody(moshi)
259+
)
232260
}
233261
return templateResponse.body()!!
234262
}
@@ -240,7 +268,12 @@ open class CoderRestClient(
240268
val buildRequest=CreateWorkspaceBuildRequest(null,WorkspaceTransition.START)
241269
val buildResponse= retroRestClient.createWorkspaceBuild(workspace.id, buildRequest)
242270
if (buildResponse.code()!=HttpURLConnection.HTTP_CREATED) {
243-
throwAPIResponseException("start workspace${workspace.name}", url, buildResponse)
271+
throwAPIResponseException(
272+
"start workspace${workspace.name}",
273+
url,
274+
buildResponse.code(),
275+
buildResponse.parseErrorBody(moshi)
276+
)
244277
}
245278
return buildResponse.body()!!
246279
}
@@ -251,7 +284,12 @@ open class CoderRestClient(
251284
val buildRequest=CreateWorkspaceBuildRequest(null,WorkspaceTransition.STOP)
252285
val buildResponse= retroRestClient.createWorkspaceBuild(workspace.id, buildRequest)
253286
if (buildResponse.code()!=HttpURLConnection.HTTP_CREATED) {
254-
throwAPIResponseException("stop workspace${workspace.name}", url, buildResponse)
287+
throwAPIResponseException(
288+
"stop workspace${workspace.name}",
289+
url,
290+
buildResponse.code(),
291+
buildResponse.parseErrorBody(moshi)
292+
)
255293
}
256294
return buildResponse.body()!!
257295
}
@@ -263,7 +301,12 @@ open class CoderRestClient(
263301
val buildRequest=CreateWorkspaceBuildRequest(null,WorkspaceTransition.DELETE,false)
264302
val buildResponse= retroRestClient.createWorkspaceBuild(workspace.id, buildRequest)
265303
if (buildResponse.code()!=HttpURLConnection.HTTP_CREATED) {
266-
throwAPIResponseException("delete workspace${workspace.name}", url, buildResponse)
304+
throwAPIResponseException(
305+
"delete workspace${workspace.name}",
306+
url,
307+
buildResponse.code(),
308+
buildResponse.parseErrorBody(moshi)
309+
)
267310
}
268311
}
269312

@@ -283,7 +326,12 @@ open class CoderRestClient(
283326
CreateWorkspaceBuildRequest(template.activeVersionID,WorkspaceTransition.START)
284327
val buildResponse= retroRestClient.createWorkspaceBuild(workspace.id, buildRequest)
285328
if (buildResponse.code()!=HttpURLConnection.HTTP_CREATED) {
286-
throwAPIResponseException("update workspace${workspace.name}", url, buildResponse)
329+
throwAPIResponseException(
330+
"update workspace${workspace.name}",
331+
url,
332+
buildResponse.code(),
333+
buildResponse.parseErrorBody(moshi)
334+
)
287335
}
288336
return buildResponse.body()!!
289337
}
@@ -296,3 +344,13 @@ open class CoderRestClient(
296344
}
297345
}
298346
}
347+
348+
privatefunResponse<*>.parseErrorBody(moshi:Moshi):ApiErrorResponse? {
349+
val errorBody=this.errorBody()?:returnnull
350+
returntry {
351+
val adapter= moshi.adapter(ApiErrorResponse::class.java)
352+
adapter.fromJson(errorBody.string())
353+
}catch (e:Exception) {
354+
null
355+
}
356+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp