@@ -7,6 +7,7 @@ import { User } from "@gitpod/gitpod-protocol";
7
7
import { Request } from "express" ;
8
8
import { IAnalyticsWriter } from "@gitpod/gitpod-protocol/lib/analytics" ;
9
9
import { SubscriptionService } from "@gitpod/gitpod-payment-endpoint/lib/accounting" ;
10
+ import * as crypto from "crypto" ;
10
11
11
12
export async function trackLogin (
12
13
user : User ,
@@ -17,11 +18,13 @@ export async function trackLogin(
17
18
) {
18
19
// make new complete identify call for each login
19
20
await fullIdentify ( user , request , analytics , subscriptionService ) ;
21
+ const ip = request . ips [ 0 ] ;
22
+ const ua = request . headers [ "user-agent" ] ;
20
23
21
24
// track the login
22
25
analytics . track ( {
23
26
userId : user . id ,
24
- anonymousId : stripCookie ( request . cookies . ajs_anonymous_id ) ,
27
+ anonymousId : getAnonymousId ( request ) || createCookielessId ( ip , ua ) ,
25
28
event : "login" ,
26
29
properties : {
27
30
loginContext : authHost ,
@@ -32,11 +35,13 @@ export async function trackLogin(
32
35
export async function trackSignup ( user : User , request : Request , analytics : IAnalyticsWriter ) {
33
36
// make new complete identify call for each signup
34
37
await fullIdentify ( user , request , analytics ) ;
38
+ const ip = request . ips [ 0 ] ;
39
+ const ua = request . headers [ "user-agent" ] ;
35
40
36
41
// track the signup
37
42
analytics . track ( {
38
43
userId : user . id ,
39
- anonymousId : stripCookie ( request . cookies . ajs_anonymous_id ) ,
44
+ anonymousId : getAnonymousId ( request ) || createCookielessId ( ip , ua ) ,
40
45
event : "signup" ,
41
46
properties : {
42
47
auth_provider : user . identities [ 0 ] . authProviderId ,
@@ -46,6 +51,26 @@ export async function trackSignup(user: User, request: Request, analytics: IAnal
46
51
} ) ;
47
52
}
48
53
54
+ export function createCookielessId ( ip ?: string , ua ?: string ) : string | number | undefined {
55
+ if ( ! ip || ! ua ) {
56
+ return "unidentified-user" ; //use placeholder if we cannot resolve IP and user agent
57
+ }
58
+ const date = new Date ( ) ;
59
+ const today = `${ date . getDate ( ) } /${ date . getMonth ( ) } /${ date . getFullYear ( ) } ` ;
60
+ return crypto
61
+ . createHash ( "sha512" )
62
+ . update ( ip + ua + today )
63
+ . digest ( "hex" ) ;
64
+ }
65
+
66
+ export function maskIp ( ip ?: string ) {
67
+ if ( ! ip ) {
68
+ return ;
69
+ }
70
+ const octets = ip . split ( "." ) ;
71
+ return octets ?. length == 4 ? octets . slice ( 0 , 3 ) . concat ( [ "0" ] ) . join ( "." ) : undefined ;
72
+ }
73
+
49
74
async function fullIdentify (
50
75
user : User ,
51
76
request : Request ,
@@ -54,18 +79,19 @@ async function fullIdentify(
54
79
) {
55
80
// makes a full identify call for authenticated users
56
81
const coords = request . get ( "x-glb-client-city-lat-long" ) ?. split ( ", " ) ;
57
- const ip = request . get ( "x-forwarded-for" ) ?. split ( "," ) [ 0 ] ;
82
+ const ip = request . ips [ 0 ] ;
83
+ const ua = request . headers [ "user-agent" ] ;
58
84
var subscriptionIDs : string [ ] = [ ] ;
59
85
const subscriptions = await subscriptionService ?. getNotYetCancelledSubscriptions ( user , new Date ( ) . toISOString ( ) ) ;
60
86
if ( subscriptions ) {
61
87
subscriptionIDs = subscriptions . filter ( ( sub ) => ! ! sub . planId ) . map ( ( sub ) => sub . planId ! ) ;
62
88
}
63
89
analytics . identify ( {
64
- anonymousId : stripCookie ( request . cookies . ajs_anonymous_id ) ,
90
+ anonymousId : getAnonymousId ( request ) || createCookielessId ( ip , ua ) ,
65
91
userId : user . id ,
66
92
context : {
67
93
ip : ip ? maskIp ( ip ) : undefined ,
68
- userAgent : request . get ( "User-Agent" ) ,
94
+ userAgent : ua ,
69
95
location : {
70
96
city : request . get ( "x-glb-client-city" ) ,
71
97
country : request . get ( "x-glb-client-region" ) ,
@@ -87,9 +113,11 @@ async function fullIdentify(
87
113
} ) ;
88
114
}
89
115
90
- function maskIp ( ip : string ) {
91
- const octets = ip . split ( "." ) ;
92
- return octets ?. length == 4 ? octets . slice ( 0 , 3 ) . concat ( [ "0" ] ) . join ( "." ) : undefined ;
116
+ function getAnonymousId ( request : Request ) {
117
+ if ( ! ( request . cookies [ "gp-analytical" ] === "true" ) ) {
118
+ return ;
119
+ }
120
+ return stripCookie ( request . cookies . ajs_anonymous_id ) ;
93
121
}
94
122
95
123
function resolveIdentities ( user : User ) {
0 commit comments