@@ -12,6 +12,7 @@ import { CoderApi } from "./api/coderApi";
12
12
import { needToken } from "./api/utils" ;
13
13
import { type CliManager } from "./core/cliManager" ;
14
14
import { type ServiceContainer } from "./core/container" ;
15
+ import { type ContextManager } from "./core/contextManager" ;
15
16
import { type MementoManager } from "./core/mementoManager" ;
16
17
import { type PathResolver } from "./core/pathResolver" ;
17
18
import { type SecretsManager } from "./core/secretsManager" ;
@@ -32,6 +33,7 @@ export class Commands {
32
33
private readonly mementoManager :MementoManager ;
33
34
private readonly secretsManager :SecretsManager ;
34
35
private readonly cliManager :CliManager ;
36
+ private readonly contextManager :ContextManager ;
35
37
// These will only be populated when actively connected to a workspace and are
36
38
// used in commands. Because commands can be executed by the user, it is not
37
39
// possible to pass in arguments, so we have to store the current workspace
@@ -53,6 +55,7 @@ export class Commands {
53
55
this . mementoManager = serviceContainer . getMementoManager ( ) ;
54
56
this . secretsManager = serviceContainer . getSecretsManager ( ) ;
55
57
this . cliManager = serviceContainer . getCliManager ( ) ;
58
+ this . contextManager = serviceContainer . getContextManager ( ) ;
56
59
}
57
60
58
61
/**
@@ -189,6 +192,11 @@ export class Commands {
189
192
label ?:string ;
190
193
autoLogin ?:boolean ;
191
194
} ) :Promise < void > {
195
+ if ( this . contextManager . get ( "coder.authenticated" ) ) {
196
+ return ;
197
+ }
198
+ this . logger . info ( "Logging in" ) ;
199
+
192
200
const url = await this . maybeAskUrl ( args ?. url ) ;
193
201
if ( ! url ) {
194
202
return ; // The user aborted.
@@ -219,13 +227,9 @@ export class Commands {
219
227
await this . secretsManager . setSessionToken ( res . token ) ;
220
228
221
229
// These contexts control various menu items and the sidebar.
222
- await vscode . commands . executeCommand (
223
- "setContext" ,
224
- "coder.authenticated" ,
225
- true ,
226
- ) ;
230
+ this . contextManager . set ( "coder.authenticated" , true ) ;
227
231
if ( res . user . roles . find ( ( role ) => role . name === "owner" ) ) {
228
- await vscode . commands . executeCommand ( "setContext" , "coder.isOwner" , true ) ;
232
+ this . contextManager . set ( "coder.isOwner" , true ) ;
229
233
}
230
234
231
235
vscode . window
@@ -245,6 +249,7 @@ export class Commands {
245
249
246
250
// Fetch workspaces for the new deployment.
247
251
vscode . commands . executeCommand ( "coder.refreshWorkspaces" ) ;
252
+ this . secretsManager . triggerLoginStateChange ( "login" ) ;
248
253
}
249
254
250
255
/**
@@ -378,6 +383,10 @@ export class Commands {
378
383
}
379
384
380
385
public async forceLogout ( ) :Promise < void > {
386
+ if ( ! this . contextManager . get ( "coder.authenticated" ) ) {
387
+ return ;
388
+ }
389
+ this . logger . info ( "Logging out" ) ;
381
390
// Clear from the REST client. An empty url will indicate to other parts of
382
391
// the code that we are logged out.
383
392
this . restClient . setHost ( "" ) ;
@@ -387,11 +396,7 @@ export class Commands {
387
396
await this . mementoManager . setUrl ( undefined ) ;
388
397
await this . secretsManager . setSessionToken ( undefined ) ;
389
398
390
- await vscode . commands . executeCommand (
391
- "setContext" ,
392
- "coder.authenticated" ,
393
- false ,
394
- ) ;
399
+ this . contextManager . set ( "coder.authenticated" , false ) ;
395
400
vscode . window
396
401
. showInformationMessage ( "You've been logged out of Coder!" , "Login" )
397
402
. then ( ( action ) => {
@@ -402,6 +407,7 @@ export class Commands {
402
407
403
408
// This will result in clearing the workspace list.
404
409
vscode . commands . executeCommand ( "coder.refreshWorkspaces" ) ;
410
+ this . secretsManager . triggerLoginStateChange ( "logout" ) ;
405
411
}
406
412
407
413
/**