forked from firebase/firebase-admin-node
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuser-record.ts
More file actions
216 lines (201 loc) · 7.41 KB
/
user-record.ts
File metadata and controls
216 lines (201 loc) · 7.41 KB
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*!
* Copyright 2017 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {deepCopy} from '../utils/deep-copy';
import * as utils from '../utils';
import {AuthClientErrorCode, FirebaseAuthError} from '../utils/error';
/**
* Parses a time stamp string or number and returns the corresponding date if valid.
*
* @param {any} time The unix timestamp string or number in milliseconds.
* @return {string} The corresponding date as a UTC string, if valid.
*/
function parseDate(time: any): string {
try {
const date = new Date(parseInt(time, 10));
if (!isNaN(date.getTime())) {
return date.toUTCString();
}
} catch (e) {
// Do nothing. null will be returned.
}
return null;
}
/** Parameters for update user operation */
export interface UpdateRequest {
displayName?: string;
email?: string;
emailVerified?: boolean;
phoneNumber?: string;
photoURL?: string;
disabled?: boolean;
password?: string;
}
/** Parameters for create user operation */
export interface CreateRequest extends UpdateRequest {
uid?: string;
}
/**
* User metadata class that provides metadata information like user account creation
* and last sign in time.
*
* @param {object} response The server side response returned from the getAccountInfo
* endpoint.
* @constructor
*/
export class UserMetadata {
public readonly creationTime: string;
public readonly lastSignInTime: string;
constructor(response: any) {
// Creation date should always be available but due to some backend bugs there
// were cases in the past where users did not have creation date properly set.
// This included legacy Firebase migrating project users and some anonymous users.
// These bugs have already been addressed since then.
utils.addReadonlyGetter(this, 'creationTime', parseDate(response.createdAt));
utils.addReadonlyGetter(this, 'lastSignInTime', parseDate(response.lastLoginAt));
}
/** @return {object} The plain object representation of the user's metadata. */
public toJSON(): object {
return {
lastSignInTime: this.lastSignInTime,
creationTime: this.creationTime,
};
}
}
/**
* User info class that provides provider user information for different
* Firebase providers like google.com, facebook.com, password, etc.
*
* @param {object} response The server side response returned from the getAccountInfo
* endpoint.
* @constructor
*/
export class UserInfo {
public readonly uid: string;
public readonly displayName: string;
public readonly email: string;
public readonly photoURL: string;
public readonly providerId: string;
public readonly phoneNumber: string;
constructor(response: any) {
// Provider user id and provider id are required.
if (!response.rawId || !response.providerId) {
throw new FirebaseAuthError(
AuthClientErrorCode.INTERNAL_ERROR,
'INTERNAL ASSERT FAILED: Invalid user info response');
}
utils.addReadonlyGetter(this, 'uid', response.rawId);
utils.addReadonlyGetter(this, 'displayName', response.displayName);
utils.addReadonlyGetter(this, 'email', response.email);
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
utils.addReadonlyGetter(this, 'providerId', response.providerId);
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
}
/** @return {object} The plain object representation of the current provider data. */
public toJSON(): object {
return {
uid: this.uid,
displayName: this.displayName,
email: this.email,
photoURL: this.photoURL,
providerId: this.providerId,
phoneNumber: this.phoneNumber,
};
}
}
/**
* User record class that defines the Firebase user object populated from
* the Firebase Auth getAccountInfo response.
*
* @param {any} response The server side response returned from the getAccountInfo
* endpoint.
* @constructor
*/
export class UserRecord {
public readonly uid: string;
public readonly email: string;
public readonly emailVerified: boolean;
public readonly displayName: string;
public readonly photoURL: string;
public readonly phoneNumber: string;
public readonly disabled: boolean;
public readonly metadata: UserMetadata;
public readonly providerData: UserInfo[];
public readonly passwordHash?: string;
public readonly passwordSalt?: string;
public readonly customClaims: object;
public readonly tokensValidAfterTime?: string;
constructor(response: any) {
// The Firebase user id is required.
if (!response.localId) {
throw new FirebaseAuthError(
AuthClientErrorCode.INTERNAL_ERROR,
'INTERNAL ASSERT FAILED: Invalid user response');
}
utils.addReadonlyGetter(this, 'uid', response.localId);
utils.addReadonlyGetter(this, 'email', response.email);
utils.addReadonlyGetter(this, 'emailVerified', !!response.emailVerified);
utils.addReadonlyGetter(this, 'displayName', response.displayName);
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
// If disabled is not provided, the account is enabled by default.
utils.addReadonlyGetter(this, 'disabled', response.disabled || false);
utils.addReadonlyGetter(this, 'metadata', new UserMetadata(response));
const providerData: UserInfo[] = [];
for (const entry of (response.providerUserInfo || [])) {
providerData.push(new UserInfo(entry));
}
utils.addReadonlyGetter(this, 'providerData', providerData);
utils.addReadonlyGetter(this, 'passwordHash', response.passwordHash);
utils.addReadonlyGetter(this, 'passwordSalt', response.salt);
try {
utils.addReadonlyGetter(
this, 'customClaims', JSON.parse(response.customAttributes));
} catch (e) {
// Ignore error.
utils.addReadonlyGetter(this, 'customClaims', undefined);
}
let validAfterTime: string = null;
// Convert validSince first to UTC milliseconds and then to UTC date string.
if (typeof response.validSince !== 'undefined') {
validAfterTime = parseDate(response.validSince * 1000);
}
utils.addReadonlyGetter(this, 'tokensValidAfterTime', validAfterTime);
}
/** @return {object} The plain object representation of the user record. */
public toJSON(): object {
const json: any = {
uid: this.uid,
email: this.email,
emailVerified: this.emailVerified,
displayName: this.displayName,
photoURL: this.photoURL,
phoneNumber: this.phoneNumber,
disabled: this.disabled,
// Convert metadata to json.
metadata: this.metadata.toJSON(),
passwordHash: this.passwordHash,
passwordSalt: this.passwordSalt,
customClaims: deepCopy(this.customClaims),
tokensValidAfterTime: this.tokensValidAfterTime,
};
json.providerData = [];
for (const entry of this.providerData) {
// Convert each provider data to json.
json.providerData.push(entry.toJSON());
}
return json;
}
}