-
Notifications
You must be signed in to change notification settings - Fork 237
/
User.ts
161 lines (135 loc) · 5.83 KB
/
User.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { IUser, IUserContextPlugin } from '../Interfaces/Context/IUser';
import { ITelemetryConfig } from '../Interfaces/ITelemetryConfig';
import { Util } from '@microsoft/applicationinsights-common';
import { IDiagnosticLogger, _InternalMessageId, LoggingSeverity } from '@microsoft/applicationinsights-core-js';
export class User implements IUser, IUserContextPlugin {
static cookieSeparator: string = '|';
static userCookieName: string = 'ai_user';
static authUserCookieName: string = 'ai_authUser';
/**
* The telemetry configuration.
*/
public config: ITelemetryConfig;
/**
* The user ID.
*/
public id: string;
/**
* Authenticated user id
*/
public authenticatedId: string;
/**
* The account ID.
*/
public accountId: string;
/**
* The account acquisition date.
*/
public accountAcquisitionDate: string;
/**
* The user agent string.
*/
public agent: string;
/**
* The store region.
*/
public storeRegion: string;
private _logger: IDiagnosticLogger;
/**
* Sets the authenticated user id and the account id in this session.
*
* @param authenticatedUserId {string} - The authenticated user id. A unique and persistent string that represents each authenticated user in the service.
* @param accountId {string} - An optional string to represent the account associated with the authenticated user.
*/
public setAuthenticatedUserContext(authenticatedUserId: string, accountId?: string, storeInCookie = false) {
// Validate inputs to ensure no cookie control characters.
var isInvalidInput = !this.validateUserInput(authenticatedUserId) || (accountId && !this.validateUserInput(accountId));
if (isInvalidInput) {
this._logger.throwInternal(
LoggingSeverity.WARNING,
_InternalMessageId.SetAuthContextFailedAccountName,
"Setting auth user context failed. " +
"User auth/account id should be of type string, and not contain commas, semi-colons, equal signs, spaces, or vertical-bars.",
true);
return;
}
// Create cookie string.
this.authenticatedId = authenticatedUserId;
var authCookie = this.authenticatedId;
if (accountId) {
this.accountId = accountId;
authCookie = [this.authenticatedId, this.accountId].join(User.cookieSeparator);
}
if (storeInCookie) {
// Set the cookie. No expiration date because this is a session cookie (expires when browser closed).
// Encoding the cookie to handle unexpected unicode characters.
Util.setCookie(this._logger, User.authUserCookieName, encodeURI(authCookie), this.config.cookieDomain());
}
}
/**
* Clears the authenticated user id and the account id from the user context.
* @returns {}
*/
public clearAuthenticatedUserContext() {
this.authenticatedId = null;
this.accountId = null;
Util.deleteCookie(this._logger, User.authUserCookieName);
}
constructor(config: ITelemetryConfig, logger: IDiagnosticLogger) {
this._logger = logger;
//get userId or create new one if none exists
var cookie = Util.getCookie(this._logger, User.userCookieName);
if (cookie) {
var params = cookie.split(User.cookieSeparator);
if (params.length > 0) {
this.id = params[0];
}
}
this.config = config;
if (!this.id) {
this.id = Util.newId();
var date = new Date();
var acqStr = Util.toISOStringForIE8(date);
this.accountAcquisitionDate = acqStr;
// without expiration, cookies expire at the end of the session
// set it to 365 days from now
// 365 * 24 * 60 * 60 * 1000 = 31536000000
date.setTime(date.getTime() + 31536000000);
var newCookie = [this.id, acqStr];
var cookieDomain = this.config.cookieDomain ? this.config.cookieDomain() : undefined;
Util.setCookie(this._logger, User.userCookieName, newCookie.join(User.cookieSeparator) + ';expires=' + date.toUTCString(), cookieDomain);
// If we have an ai_session in local storage this means the user actively removed our cookies.
// We should respect their wishes and clear ourselves from local storage
Util.removeStorage(this._logger, 'ai_session');
}
// We still take the account id from the ctor param for backward compatibility.
// But if the the customer set the accountId through the newer setAuthenticatedUserContext API, we will override it.
this.accountId = config.accountId ? config.accountId() : undefined;
// Get the auth user id and account id from the cookie if exists
// Cookie is in the pattern: <authenticatedId>|<accountId>
var authCookie = Util.getCookie(this._logger, User.authUserCookieName);
if (authCookie) {
authCookie = decodeURI(authCookie);
var authCookieString = authCookie.split(User.cookieSeparator);
if (authCookieString[0]) {
this.authenticatedId = authCookieString[0];
}
if (authCookieString.length > 1 && authCookieString[1]) {
this.accountId = authCookieString[1];
}
}
}
private validateUserInput(id: string): boolean {
// Validate:
// 1. Id is a non-empty string.
// 2. It does not contain special characters for cookies.
if (typeof id !== 'string' ||
!id ||
id.match(/,|;|=| |\|/)) {
return false;
}
return true;
}
}