@@ -62,7 +62,14 @@ import { ObjectScriptExplorerProvider } from "./explorer/explorer";
62
62
import { WorkspaceNode } from "./explorer/models/workspaceNode" ;
63
63
import { FileSystemProvider } from "./providers/FileSystemPovider/FileSystemProvider" ;
64
64
import { WorkspaceSymbolProvider } from "./providers/WorkspaceSymbolProvider" ;
65
- import { currentWorkspaceFolder , outputChannel , portFromDockerCompose , terminalWithDocker , notNull } from "./utils" ;
65
+ import {
66
+ connectionTarget ,
67
+ currentWorkspaceFolder ,
68
+ outputChannel ,
69
+ portFromDockerCompose ,
70
+ terminalWithDocker ,
71
+ notNull ,
72
+ } from "./utils" ;
66
73
import { ObjectScriptDiagnosticProvider } from "./providers/ObjectScriptDiagnosticProvider" ;
67
74
import { DocumentRangeFormattingEditProvider } from "./providers/DocumentRangeFormattingEditProvider" ;
68
75
@@ -96,7 +103,7 @@ export const config = (setting?: string, workspaceFolderName?: string): vscode.W
96
103
) {
97
104
workspaceFolderName = vscode . workspace . workspaceFolders [ 0 ] . name ;
98
105
}
99
- let prefix ;
106
+ let prefix : string ;
100
107
const workspaceFolder = vscode . workspace . workspaceFolders . find (
101
108
( el ) => el . name . toLowerCase ( ) === workspaceFolderName . toLowerCase ( )
102
109
) ;
@@ -145,17 +152,19 @@ let reporter: TelemetryReporter = null;
145
152
146
153
let connectionSocket : WebSocket ;
147
154
148
- export const checkConnection = ( clearCookies = false ) : void => {
149
- const workspaceFolder = currentWorkspaceFolder ( ) ;
155
+ let serverManagerApi : any ;
156
+
157
+ export function checkConnection ( clearCookies = false , uri ?: vscode . Uri ) : void {
158
+ const { apiTarget, configName } = connectionTarget ( uri ) ;
150
159
if ( clearCookies ) {
151
160
/// clean-up cached values
152
- workspaceState . update ( workspaceFolder + ":host" , undefined ) ;
153
- workspaceState . update ( workspaceFolder + ":port" , undefined ) ;
154
- workspaceState . update ( workspaceFolder + ":password" , undefined ) ;
155
- workspaceState . update ( workspaceFolder + ":apiVersion" , undefined ) ;
156
- workspaceState . update ( workspaceFolder + ":docker" , undefined ) ;
161
+ workspaceState . update ( configName + ":host" , undefined ) ;
162
+ workspaceState . update ( configName + ":port" , undefined ) ;
163
+ workspaceState . update ( configName + ":password" , undefined ) ;
164
+ workspaceState . update ( configName + ":apiVersion" , undefined ) ;
165
+ workspaceState . update ( configName + ":docker" , undefined ) ;
157
166
}
158
- let api = new AtelierAPI ( workspaceFolder ) ;
167
+ let api = new AtelierAPI ( apiTarget , false ) ;
159
168
const { active, host = "" , port = 0 , ns = "" } = api . config ;
160
169
let connInfo = `${ host } :${ port } [${ ns } ]` ;
161
170
if ( ! host . length || ! port || ! ns . length ) {
@@ -168,9 +177,9 @@ export const checkConnection = (clearCookies = false): void => {
168
177
panel . text = `${ packageJson . displayName } - Disabled` ;
169
178
return ;
170
179
}
171
- if ( ! workspaceState . get ( workspaceFolder + ":port" ) && ! api . externalServer ) {
180
+ if ( ! workspaceState . get ( configName + ":port" ) && ! api . externalServer ) {
172
181
const { port : dockerPort , docker : withDocker } = portFromDockerCompose ( ) ;
173
- workspaceState . update ( workspaceFolder + ":docker" , withDocker ) ;
182
+ workspaceState . update ( configName + ":docker" , withDocker ) ;
174
183
if ( withDocker ) {
175
184
if ( ! dockerPort ) {
176
185
outputChannel . appendLine (
@@ -181,8 +190,8 @@ export const checkConnection = (clearCookies = false): void => {
181
190
}
182
191
terminalWithDocker ( ) ;
183
192
if ( dockerPort !== port ) {
184
- workspaceState . update ( workspaceFolder + ":host" , "localhost" ) ;
185
- workspaceState . update ( workspaceFolder + ":port" , dockerPort ) ;
193
+ workspaceState . update ( configName + ":host" , "localhost" ) ;
194
+ workspaceState . update ( configName + ":port" , dockerPort ) ;
186
195
}
187
196
connInfo = `localhost:${ dockerPort } [${ ns } ]` ;
188
197
}
@@ -194,10 +203,15 @@ export const checkConnection = (clearCookies = false): void => {
194
203
panel . text = `${ connInfo } - Connected` ;
195
204
return ;
196
205
}
197
- api = new AtelierAPI ( workspaceFolder ) ;
206
+
207
+ // Why must this be recreated here?
208
+ api = new AtelierAPI ( apiTarget , false ) ;
209
+
198
210
if ( ! api . config . host || ! api . config . port || ! api . config . ns ) {
199
- outputChannel . appendLine ( "host, port and ns must be specified." ) ;
211
+ const message = "host, port and ns must be specified." ;
212
+ outputChannel . appendLine ( message ) ;
200
213
panel . text = `${ packageJson . displayName } - ERROR` ;
214
+ panel . tooltip = message ;
201
215
return ;
202
216
}
203
217
api
@@ -222,32 +236,39 @@ export const checkConnection = (clearCookies = false): void => {
222
236
. catch ( ( error ) => {
223
237
let message = error . message ;
224
238
if ( error instanceof StatusCodeError && error . statusCode === 401 ) {
225
- setTimeout (
226
- ( ) =>
239
+ setTimeout ( ( ) => {
240
+ const username = api . config . username ;
241
+ if ( username === "" ) {
242
+ vscode . window . showErrorMessage ( `Anonymous access rejected by ${ connInfo } .` ) ;
243
+ if ( ! api . externalServer ) {
244
+ vscode . window . showErrorMessage ( "Connection has been disabled." ) ;
245
+ disableConnection ( configName ) ;
246
+ }
247
+ } else {
227
248
vscode . window
228
249
. showInputBox ( {
229
250
password : true ,
230
- placeHolder : "Not Authorized, please enter password to connect to: " + connInfo ,
251
+ placeHolder : `Not Authorized. Enter password to connect as user '${ username } ' to ${ connInfo } ` ,
252
+ prompt : ! api . externalServer ? "If no password is entered the connection will be disabled." : "" ,
231
253
ignoreFocusOut : true ,
232
254
} )
233
255
. then ( ( password ) => {
234
256
if ( password ) {
235
- workspaceState . update ( currentWorkspaceFolder ( ) + ":password" , password ) ;
236
- checkConnection ( ) ;
237
- } else {
238
- vscode . workspace . getConfiguration ( ) . update ( "objectscript.conn.active" , false ) ;
257
+ workspaceState . update ( configName + ":password" , password ) ;
258
+ checkConnection ( false , uri ) ;
259
+ } else if ( ! api . externalServer ) {
260
+ disableConnection ( configName ) ;
239
261
}
240
- } ) ,
241
- 1000
242
- ) ;
262
+ } ) ;
263
+ }
264
+ } , 1000 ) ;
243
265
message = "Not Authorized" ;
244
266
outputChannel . appendLine (
245
- `Authorization error: please check your username/password in the settings,
246
- and if you have sufficient privileges on the server.`
267
+ `Authorization error: Check your credentials in Settings, and that you have sufficient privileges on the /api/atelier web application on ${ connInfo } `
247
268
) ;
248
269
} else {
249
- outputChannel . appendLine ( " Error: " + message ) ;
250
- outputChannel . appendLine ( "Please check your network settings in the settings." ) ;
270
+ outputChannel . appendLine ( ` Error: ${ message } ` ) ;
271
+ outputChannel . appendLine ( `Check your server details in Settings ( ${ connInfo } ).` ) ;
251
272
}
252
273
console . error ( error ) ;
253
274
panel . text = `${ connInfo } - ERROR` ;
@@ -257,44 +278,70 @@ export const checkConnection = (clearCookies = false): void => {
257
278
. finally ( ( ) => {
258
279
explorerProvider . refresh ( ) ;
259
280
} ) ;
260
- } ;
281
+ }
282
+
283
+ // Set objectscript.conn.active = false at WorkspaceFolder level if objectscript.conn is defined there,
284
+ // else set it false at Workspace level
285
+ function disableConnection ( configName : string ) {
286
+ const connConfig : vscode . WorkspaceConfiguration = config ( "" , configName ) ;
287
+ const target : vscode . ConfigurationTarget = connConfig . inspect ( "conn" ) . workspaceFolderValue
288
+ ? vscode . ConfigurationTarget . WorkspaceFolder
289
+ : vscode . ConfigurationTarget . Workspace ;
290
+ const targetConfig : any =
291
+ connConfig . inspect ( "conn" ) . workspaceFolderValue || connConfig . inspect ( "conn" ) . workspaceValue ;
292
+ return connConfig . update ( "conn" , { ...targetConfig , active : false } , target ) ;
293
+ }
261
294
262
- async function serverManager ( ) : Promise < void > {
295
+ // Promise to return the API of the servermanager
296
+ async function serverManager ( ) : Promise < any > {
263
297
const extId = "intersystems-community.servermanager" ;
298
+ let extension = vscode . extensions . getExtension ( extId ) ;
264
299
const ignore =
265
300
config ( "ignoreInstallServerManager" ) ||
266
301
vscode . workspace . getConfiguration ( "intersystems.servers" ) . get ( "/ignore" , false ) ;
267
- if ( ignore || vscode . extensions . getExtension ( extId ) ) {
268
- return ;
302
+ if ( ! extension ) {
303
+ if ( ignore ) {
304
+ return ;
305
+ }
306
+ await vscode . window
307
+ . showInformationMessage (
308
+ "The InterSystems® Server Manager extension is recommended to help you define connections and store passwords securely in your keychain." ,
309
+ "Install" ,
310
+ "Skip" ,
311
+ "Ignore"
312
+ )
313
+ . then ( async ( action ) => {
314
+ switch ( action ) {
315
+ case "Install" :
316
+ await vscode . commands . executeCommand ( "workbench.extensions.search" , `@tag:"intersystems"` ) ;
317
+ await vscode . commands . executeCommand ( "extension.open" , extId ) ;
318
+ await vscode . commands . executeCommand ( "workbench.extensions.installExtension" , extId ) ;
319
+ extension = vscode . extensions . getExtension ( extId ) ;
320
+ break ;
321
+ case "Ignore" :
322
+ config ( ) . update ( "ignoreInstallServerManager" , true , vscode . ConfigurationTarget . Global ) ;
323
+ break ;
324
+ case "Skip" :
325
+ default :
326
+ }
327
+ } ) ;
328
+ }
329
+ if ( extension ) {
330
+ if ( ! extension . isActive ) {
331
+ await extension . activate ( ) ;
332
+ }
333
+ return extension . exports ;
269
334
}
270
- return vscode . window
271
- . showInformationMessage (
272
- "The InterSystems® Server Manager extension is recommended to help you define connections." ,
273
- "Install" ,
274
- "Skip" ,
275
- "Ignore"
276
- )
277
- . then ( async ( action ) => {
278
- switch ( action ) {
279
- case "Install" :
280
- await vscode . commands . executeCommand ( "workbench.extensions.search" , `@tag:"intersystems"` ) ;
281
- await vscode . commands . executeCommand ( "extension.open" , extId ) ;
282
- await vscode . commands . executeCommand ( "workbench.extensions.installExtension" , extId ) ;
283
- break ;
284
- case "Ignore" :
285
- config ( ) . update ( "ignoreInstallServerManager" , true , vscode . ConfigurationTarget . Global ) ;
286
- break ;
287
- case "Skip" :
288
- default :
289
- }
290
- } ) ;
291
335
}
292
336
293
337
export async function activate ( context : vscode . ExtensionContext ) : Promise < void > {
294
338
if ( ! packageJson . version . includes ( "SNAPSHOT" ) ) {
295
339
reporter = new TelemetryReporter ( extensionId , extensionVersion , aiKey ) ;
296
340
}
297
341
342
+ // Get api for servermanager extension, perhaps offering to install it
343
+ serverManagerApi = await serverManager ( ) ;
344
+
298
345
const languages = packageJson . contributes . languages . map ( ( lang ) => lang . id ) ;
299
346
workspaceState = context . workspaceState ;
300
347
extensionContext = context ;
@@ -305,7 +352,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
305
352
fileSystemProvider = new FileSystemProvider ( ) ;
306
353
307
354
explorerProvider = new ObjectScriptExplorerProvider ( ) ;
308
- // vscode.window.registerTreeDataProvider("ObjectScriptExplorer", explorerProvider);
309
355
vscode . window . createTreeView ( "ObjectScriptExplorer" , {
310
356
treeDataProvider : explorerProvider ,
311
357
showCollapseAll : true ,
@@ -322,7 +368,17 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
322
368
panel . command = "vscode-objectscript.serverActions" ;
323
369
panel . show ( ) ;
324
370
325
- checkConnection ( true ) ;
371
+ // Check once (flushing cookies) each connection used by the workspace(s)
372
+ const toCheck = new Map < string , vscode . Uri > ( ) ;
373
+ vscode . workspace . workspaceFolders . map ( ( workspaceFolder ) => {
374
+ const uri = workspaceFolder . uri ;
375
+ const { configName } = connectionTarget ( uri ) ;
376
+ toCheck . set ( configName , uri ) ;
377
+ } ) ;
378
+ toCheck . forEach ( function ( uri ) {
379
+ checkConnection ( true , uri ) ;
380
+ } ) ;
381
+
326
382
vscode . workspace . onDidChangeConfiguration ( ( { affectsConfiguration } ) => {
327
383
if ( affectsConfiguration ( "objectscript.conn" ) ) {
328
384
checkConnection ( true ) ;
@@ -597,9 +653,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
597
653
...proposed
598
654
) ;
599
655
reporter && reporter . sendTelemetryEvent ( "extensionActivated" ) ;
600
-
601
- // offer to install servermanager extension
602
- await serverManager ( ) ;
603
656
}
604
657
605
658
export function deactivate ( ) : void {
0 commit comments