@@ -40,7 +40,8 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
4040 const storage = new Storage ( output , ctx . globalState , ctx . secrets , ctx . globalStorageUri , ctx . logUri )
4141
4242 // This client tracks the current login and will be used through the life of
43- // the plugin to poll workspaces for the current login.
43+ // the plugin to poll workspaces for the current login, as well as being used
44+ // in commands that operate on the current login.
4445 const url = storage . getUrl ( )
4546 const restClient = await makeCoderSdk ( url || "" , await storage . getSessionToken ( ) , storage )
4647
@@ -57,33 +58,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
5758 myWorkspacesProvider . setVisibility ( event . visible )
5859 } )
5960
60- if ( url ) {
61- restClient
62- . getAuthenticatedUser ( )
63- . then ( async ( user ) => {
64- if ( user && user . roles ) {
65- vscode . commands . executeCommand ( "setContext" , "coder.authenticated" , true )
66- if ( user . roles . find ( ( role ) => role . name === "owner" ) ) {
67- await vscode . commands . executeCommand ( "setContext" , "coder.isOwner" , true )
68- }
69-
70- // Fetch and monitor workspaces, now that we know the client is good.
71- myWorkspacesProvider . fetchAndRefresh ( )
72- allWorkspacesProvider . fetchAndRefresh ( )
73- }
74- } )
75- . catch ( ( error ) => {
76- // This should be a failure to make the request, like the header command
77- // errored.
78- vscodeProposed . window . showErrorMessage ( "Failed to check user authentication: " + error . message )
79- } )
80- . finally ( ( ) => {
81- vscode . commands . executeCommand ( "setContext" , "coder.loaded" , true )
82- } )
83- } else {
84- vscode . commands . executeCommand ( "setContext" , "coder.loaded" , true )
85- }
86-
61+ // Handle vscode:// URIs.
8762 vscode . window . registerUriHandler ( {
8863 handleUri : async ( uri ) => {
8964 const params = new URLSearchParams ( uri . query )
@@ -127,12 +102,15 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
127102 await storage . configureCli ( toSafeHost ( url ) , url , token )
128103
129104 vscode . commands . executeCommand ( "coder.open" , owner , workspace , agent , folder , openRecent )
105+ } else {
106+ throw new Error ( `Unknown path ${ uri . path } ` )
130107 }
131108 } ,
132109 } )
133110
111+ // Register globally available commands. Many of these have visibility
112+ // controlled by contexts, see `when` in the package.json.
134113 const commands = new Commands ( vscodeProposed , restClient , storage )
135-
136114 vscode . commands . registerCommand ( "coder.login" , commands . login . bind ( commands ) )
137115 vscode . commands . registerCommand ( "coder.logout" , commands . logout . bind ( commands ) )
138116 vscode . commands . registerCommand ( "coder.open" , commands . open . bind ( commands ) )
@@ -153,38 +131,71 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
153131 // Since the "onResolveRemoteAuthority:ssh-remote" activation event exists
154132 // in package.json we're able to perform actions before the authority is
155133 // resolved by the remote SSH extension.
156- if ( ! vscodeProposed . env . remoteAuthority ) {
157- return
158- }
159- const remote = new Remote ( vscodeProposed , storage , commands , ctx . extensionMode )
160- try {
161- await remote . setup ( vscodeProposed . env . remoteAuthority )
162- } catch ( ex ) {
163- if ( ex instanceof CertificateError ) {
164- await ex . showModal ( "Failed to open workspace" )
165- } else if ( isAxiosError ( ex ) ) {
166- const msg = getErrorMessage ( ex , "" )
167- const detail = getErrorDetail ( ex )
168- const urlString = axios . getUri ( ex . response ?. config )
169- let path = urlString
170- try {
171- path = new URL ( urlString ) . pathname
172- } catch ( e ) {
173- // ignore, default to full url
134+ if ( vscodeProposed . env . remoteAuthority ) {
135+ const remote = new Remote ( vscodeProposed , storage , commands , ctx . extensionMode )
136+ try {
137+ const details = await remote . setup ( vscodeProposed . env . remoteAuthority )
138+ if ( details ) {
139+ // Authenticate the plugin client which is used in the sidebar to display
140+ // workspaces belonging to this deployment.
141+ restClient . setHost ( details . url )
142+ restClient . setSessionToken ( details . token )
174143 }
175- await vscodeProposed . window . showErrorMessage ( "Failed to open workspace" , {
176- detail : `API ${ ex . response ?. config . method ?. toUpperCase ( ) } to '${ path } ' failed with code ${ ex . response ?. status } .\nMessage: ${ msg } \nDetail: ${ detail } ` ,
177- modal : true ,
178- useCustom : true ,
144+ } catch ( ex ) {
145+ if ( ex instanceof CertificateError ) {
146+ await ex . showModal ( "Failed to open workspace" )
147+ } else if ( isAxiosError ( ex ) ) {
148+ const msg = getErrorMessage ( ex , "" )
149+ const detail = getErrorDetail ( ex )
150+ const urlString = axios . getUri ( ex . response ?. config )
151+ let path = urlString
152+ try {
153+ path = new URL ( urlString ) . pathname
154+ } catch ( e ) {
155+ // ignore, default to full url
156+ }
157+ await vscodeProposed . window . showErrorMessage ( "Failed to open workspace" , {
158+ detail : `API ${ ex . response ?. config . method ?. toUpperCase ( ) } to '${ path } ' failed with code ${ ex . response ?. status } .\nMessage: ${ msg } \nDetail: ${ detail } ` ,
159+ modal : true ,
160+ useCustom : true ,
161+ } )
162+ } else {
163+ await vscodeProposed . window . showErrorMessage ( "Failed to open workspace" , {
164+ detail : ( ex as string ) . toString ( ) ,
165+ modal : true ,
166+ useCustom : true ,
167+ } )
168+ }
169+ // Always close remote session when we fail to open a workspace.
170+ await remote . closeRemote ( )
171+ }
172+ }
173+
174+ // See if the plugin client is authenticated.
175+ if ( restClient . getAxiosInstance ( ) . defaults . baseURL ) {
176+ restClient
177+ . getAuthenticatedUser ( )
178+ . then ( async ( user ) => {
179+ if ( user && user . roles ) {
180+ vscode . commands . executeCommand ( "setContext" , "coder.authenticated" , true )
181+ if ( user . roles . find ( ( role ) => role . name === "owner" ) ) {
182+ await vscode . commands . executeCommand ( "setContext" , "coder.isOwner" , true )
183+ }
184+
185+ // Fetch and monitor workspaces, now that we know the client is good.
186+ myWorkspacesProvider . fetchAndRefresh ( )
187+ allWorkspacesProvider . fetchAndRefresh ( )
188+ }
179189 } )
180- } else {
181- await vscodeProposed . window . showErrorMessage ( "Failed to open workspace" , {
182- detail : ( ex as string ) . toString ( ) ,
183- modal : true ,
184- useCustom : true ,
190+ . catch ( ( error ) => {
191+ // This should be a failure to make the request, like the header command
192+ // errored.
193+ vscode . window . showErrorMessage ( "Failed to check user authentication: " + error . message )
185194 } )
186- }
187- // Always close remote session when we fail to open a workspace.
188- await remote . closeRemote ( )
195+ . finally ( ( ) => {
196+ vscode . commands . executeCommand ( "setContext" , "coder.loaded" , true )
197+ } )
198+ } else {
199+ vscode . commands . executeCommand ( "setContext" , "coder.loaded" , true )
189200 }
190201}
0 commit comments