@@ -12,6 +12,8 @@ import Log from './common/logger';
12
12
import { arrayEquals } from './common/utils' ;
13
13
import { Disposable } from './common/dispose' ;
14
14
import TelemetryReporter from './telemetryReporter' ;
15
+ import { UserFlowTelemetry } from './common/telemetry' ;
16
+ import { NotificationService } from './notification' ;
15
17
16
18
interface SessionData {
17
19
id : string ;
@@ -28,35 +30,30 @@ export default class GitpodAuthenticationProvider extends Disposable implements
28
30
private _sessionChangeEmitter = new vscode . EventEmitter < vscode . AuthenticationProviderAuthenticationSessionsChangeEvent > ( ) ;
29
31
private _logger : Log ;
30
32
private _telemetry : TelemetryReporter ;
31
- private _gitpodServer : GitpodServer ;
32
- private _keychain : Keychain ;
33
33
34
- private _serviceUrl : string ;
34
+ private _gitpodServer ! : GitpodServer ;
35
+ private _keychain ! : Keychain ;
36
+ private _serviceUrl ! : string ;
35
37
36
38
private _sessionsPromise : Promise < vscode . AuthenticationSession [ ] > ;
37
39
38
- constructor ( private readonly context : vscode . ExtensionContext , logger : Log , telemetry : TelemetryReporter ) {
40
+ private readonly flow : Readonly < UserFlowTelemetry > = { flow : 'auth' } ;
41
+
42
+ constructor (
43
+ private readonly context : vscode . ExtensionContext ,
44
+ logger : Log ,
45
+ telemetry : TelemetryReporter ,
46
+ private readonly notifications : NotificationService
47
+ ) {
39
48
super ( ) ;
40
49
41
50
this . _logger = logger ;
42
51
this . _telemetry = telemetry ;
43
52
44
- const gitpodHost = vscode . workspace . getConfiguration ( 'gitpod' ) . get < string > ( 'host' ) ! ;
45
- const gitpodHostUrl = new URL ( gitpodHost ) ;
46
- this . _serviceUrl = gitpodHostUrl . toString ( ) . replace ( / \/ $ / , '' ) ;
47
- this . _gitpodServer = new GitpodServer ( this . _serviceUrl , this . _logger ) ;
48
- this . _keychain = new Keychain ( this . context , `gitpod.auth.${ gitpodHostUrl . hostname } ` , this . _logger ) ;
49
- this . _logger . info ( `Started authentication provider for ${ gitpodHost } ` ) ;
53
+ this . reconcile ( ) ;
50
54
this . _register ( vscode . workspace . onDidChangeConfiguration ( e => {
51
55
if ( e . affectsConfiguration ( 'gitpod.host' ) ) {
52
- const gitpodHost = vscode . workspace . getConfiguration ( 'gitpod' ) . get < string > ( 'host' ) ! ;
53
- const gitpodHostUrl = new URL ( gitpodHost ) ;
54
- this . _serviceUrl = gitpodHostUrl . toString ( ) . replace ( / \/ $ / , '' ) ;
55
- this . _gitpodServer . dispose ( ) ;
56
- this . _gitpodServer = new GitpodServer ( this . _serviceUrl , this . _logger ) ;
57
- this . _keychain = new Keychain ( this . context , `gitpod.auth.${ gitpodHostUrl . hostname } ` , this . _logger ) ;
58
- this . _logger . info ( `Started authentication provider for ${ gitpodHost } ` ) ;
59
-
56
+ this . reconcile ( ) ;
60
57
this . checkForUpdates ( ) ;
61
58
}
62
59
} ) ) ;
@@ -68,6 +65,17 @@ export default class GitpodAuthenticationProvider extends Disposable implements
68
65
this . _register ( this . context . secrets . onDidChange ( ( ) => this . checkForUpdates ( ) ) ) ;
69
66
}
70
67
68
+ private reconcile ( ) : void {
69
+ const gitpodHost = vscode . workspace . getConfiguration ( 'gitpod' ) . get < string > ( 'host' ) ! ;
70
+ const gitpodHostUrl = new URL ( gitpodHost ) ;
71
+ this . _serviceUrl = gitpodHostUrl . toString ( ) . replace ( / \/ $ / , '' ) ;
72
+ Object . assign ( this . flow , { gitpodHost : this . _serviceUrl } ) ;
73
+ this . _gitpodServer ?. dispose ( ) ;
74
+ this . _gitpodServer = new GitpodServer ( this . _serviceUrl , this . _logger , this . notifications ) ;
75
+ this . _keychain = new Keychain ( this . context , `gitpod.auth.${ gitpodHostUrl . hostname } ` , this . _logger ) ;
76
+ this . _logger . info ( `Started authentication provider for ${ gitpodHost } ` ) ;
77
+ }
78
+
71
79
get onDidChangeSessions ( ) {
72
80
return this . _sessionChangeEmitter . event ;
73
81
}
@@ -213,6 +221,7 @@ export default class GitpodAuthenticationProvider extends Disposable implements
213
221
}
214
222
215
223
public async createSession ( scopes : string [ ] ) : Promise < vscode . AuthenticationSession > {
224
+ const flow = { ...this . flow } ;
216
225
try {
217
226
// For the Gitpod scope list, order doesn't matter so we immediately sort the scopes
218
227
const sortedScopes = scopes . sort ( ) ;
@@ -221,15 +230,13 @@ export default class GitpodAuthenticationProvider extends Disposable implements
221
230
if ( sortedScopes . length !== sortedFilteredScopes . length ) {
222
231
this . _logger . warn ( `Creating session with only valid scopes ${ sortedFilteredScopes . join ( ',' ) } , original scopes were ${ sortedScopes . join ( ',' ) } ` ) ;
223
232
}
224
-
225
- this . _telemetry . sendRawTelemetryEvent ( 'gitpod_desktop_auth' , {
226
- kind : 'login' ,
227
- scopes : JSON . stringify ( sortedFilteredScopes ) ,
228
- } ) ;
233
+ flow . scopes = JSON . stringify ( sortedFilteredScopes ) ;
234
+ this . _telemetry . sendUserFlowStatus ( 'login' , flow ) ;
229
235
230
236
const scopeString = sortedFilteredScopes . join ( ' ' ) ;
231
- const token = await this . _gitpodServer . login ( scopeString ) ;
237
+ const token = await this . _gitpodServer . login ( scopeString , flow ) ;
232
238
const session = await this . tokenToSession ( token , sortedFilteredScopes ) ;
239
+ flow . userId = session . account . id ;
233
240
234
241
const sessions = await this . _sessionsPromise ;
235
242
const sessionIndex = sessions . findIndex ( s => s . id === session . id || arrayEquals ( [ ...s . scopes ] . sort ( ) , sortedFilteredScopes ) ) ;
@@ -244,19 +251,16 @@ export default class GitpodAuthenticationProvider extends Disposable implements
244
251
245
252
this . _logger . info ( 'Login success!' ) ;
246
253
247
- this . _telemetry . sendRawTelemetryEvent ( 'gitpod_desktop_auth ', { kind : 'login_successful' } ) ;
254
+ this . _telemetry . sendUserFlowStatus ( 'login_successful ', flow ) ;
248
255
249
256
return session ;
250
257
} catch ( e ) {
251
258
// If login was cancelled, do not notify user.
252
259
if ( e === 'Cancelled' || e . message === 'Cancelled' ) {
253
- this . _telemetry . sendRawTelemetryEvent ( 'gitpod_desktop_auth ', { kind : 'login_cancelled' } ) ;
260
+ this . _telemetry . sendUserFlowStatus ( 'login_cancelled ', flow ) ;
254
261
throw e ;
255
262
}
256
-
257
- this . _telemetry . sendRawTelemetryEvent ( 'gitpod_desktop_auth' , { kind : 'login_failed' } ) ;
258
-
259
- vscode . window . showErrorMessage ( `Sign in failed: ${ e } ` ) ;
263
+ this . notifications . showErrorMessage ( `Sign in failed: ${ e } ` , { flow, id : 'login_failed' } ) ;
260
264
this . _logger . error ( e ) ;
261
265
throw e ;
262
266
}
@@ -273,15 +277,16 @@ export default class GitpodAuthenticationProvider extends Disposable implements
273
277
}
274
278
275
279
public async removeSession ( id : string ) {
280
+ const flow = { ...this . flow } ;
276
281
try {
277
- this . _telemetry . sendRawTelemetryEvent ( 'gitpod_desktop_auth' , { kind : 'logout' } ) ;
278
-
282
+ this . _telemetry . sendUserFlowStatus ( 'logout' , flow ) ;
279
283
this . _logger . info ( `Logging out of ${ id } ` ) ;
280
284
281
285
const sessions = await this . _sessionsPromise ;
282
286
const sessionIndex = sessions . findIndex ( session => session . id === id ) ;
283
287
if ( sessionIndex > - 1 ) {
284
288
const session = sessions [ sessionIndex ] ;
289
+ flow . userId = session . account . id ;
285
290
sessions . splice ( sessionIndex , 1 ) ;
286
291
287
292
await this . storeSessions ( sessions ) ;
@@ -290,10 +295,9 @@ export default class GitpodAuthenticationProvider extends Disposable implements
290
295
} else {
291
296
this . _logger . error ( 'Session not found' ) ;
292
297
}
298
+ this . _telemetry . sendUserFlowStatus ( 'logout_successful' , flow ) ;
293
299
} catch ( e ) {
294
- this . _telemetry . sendRawTelemetryEvent ( 'gitpod_desktop_auth' , { kind : 'logout_failed' } ) ;
295
-
296
- vscode . window . showErrorMessage ( `Sign out failed: ${ e } ` ) ;
300
+ this . notifications . showErrorMessage ( `Sign out failed: ${ e } ` , { flow, id : 'logout_failed' } ) ;
297
301
this . _logger . error ( e ) ;
298
302
throw e ;
299
303
}
0 commit comments