backend-manager 2.5.71 → 2.5.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/manager/functions/core/actions/api/admin/backup.js +2 -1
- package/src/manager/functions/core/actions/api/admin/firestore-write.js +7 -0
- package/src/manager/functions/core/actions/api/admin/get-stats.js +9 -2
- package/src/manager/functions/core/actions/api/admin/sync-users.js +4 -0
- package/src/manager/functions/core/actions/api/user/oauth2.js +67 -63
- package/src/manager/functions/core/actions/api/user/regenerate-api-keys.js +1 -0
- package/src/manager/functions/core/actions/api/user/sign-out-all-sessions.js +5 -6
- package/src/manager/functions/core/actions/api/user/sign-up.js +44 -33
- package/src/manager/functions/core/actions/api/user/submit-feedback.js +2 -1
- package/src/manager/functions/core/actions/api.js +18 -0
- package/src/manager/functions/core/events/auth/on-create.js +35 -9
- package/src/manager/functions/core/events/auth/on-delete.js +7 -6
- package/src/manager/helpers/metadata.js +32 -0
- package/src/manager/helpers/subscription-resolver.js +4 -1
- package/src/manager/helpers/user.js +14 -1
- package/src/manager/index.js +8 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.73",
|
|
4
4
|
"description": "Quick tools for developing Firebase functions",
|
|
5
5
|
"main": "src/manager/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@google-cloud/storage": "^5.20.5",
|
|
32
32
|
"@sendgrid/mail": "^7.7.0",
|
|
33
33
|
"@sentry/node": "^6.19.7",
|
|
34
|
-
"backend-assistant": "^1.0.
|
|
34
|
+
"backend-assistant": "^1.0.4",
|
|
35
35
|
"busboy": "^1.6.0",
|
|
36
36
|
"chalk": "^4.1.2",
|
|
37
37
|
"cors": "^2.8.5",
|
|
@@ -92,7 +92,8 @@ Module.prototype._setMetaStats = function (error, meta) {
|
|
|
92
92
|
error: error,
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
}
|
|
95
|
+
},
|
|
96
|
+
metadata: Manager.Metadata().set({tag: 'admin:backup'}),
|
|
96
97
|
}, {merge: true})
|
|
97
98
|
.catch(e => {
|
|
98
99
|
assistant.errorManager(e, {code: 500, sentry: false, send: false, log: true});
|
|
@@ -15,6 +15,7 @@ Module.prototype.main = function () {
|
|
|
15
15
|
payload.data.payload.document = payload.data.payload.document || {};
|
|
16
16
|
payload.data.payload.options = payload.data.payload.options || {};
|
|
17
17
|
payload.data.payload.options.merge = typeof payload.data.payload.options.merge === 'undefined' ? true : payload.data.payload.options.merge;
|
|
18
|
+
payload.data.payload.options.metadataTag = typeof payload.data.payload.options.metadataTag === 'undefined' ? 'admin:firestore-write' : payload.data.payload.options.metadataTag;
|
|
18
19
|
|
|
19
20
|
// Perform checks
|
|
20
21
|
if (!payload.user.roles.admin) {
|
|
@@ -23,6 +24,12 @@ Module.prototype.main = function () {
|
|
|
23
24
|
return reject(assistant.errorManager(`Path parameter required.`, {code: 400, sentry: false, send: false, log: false}).error)
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
// Set metadata
|
|
28
|
+
payload.data.payload.document.metadata = Manager.Metadata().set({tag: payload.data.payload.options.metadataTag})
|
|
29
|
+
|
|
30
|
+
// Delete metadataTag
|
|
31
|
+
delete payload.data.payload.options.metadataTag;
|
|
32
|
+
|
|
26
33
|
// Write to Firestore
|
|
27
34
|
await self.libraries.admin.firestore().doc(payload.data.payload.path)
|
|
28
35
|
.set(payload.data.payload.document, payload.data.payload.options)
|
|
@@ -100,7 +100,7 @@ Module.prototype.updateStats = function (existingData) {
|
|
|
100
100
|
return reject(error);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
// Fetch new stats
|
|
103
|
+
// Fetch new notification stats
|
|
104
104
|
await self.getAllNotifications()
|
|
105
105
|
.then(r => {
|
|
106
106
|
_.set(update, 'notifications.total', r)
|
|
@@ -109,6 +109,7 @@ Module.prototype.updateStats = function (existingData) {
|
|
|
109
109
|
error = new Error(`Failed getting notifications: ${e}`);
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
+
// Fetch new subscription stats
|
|
112
113
|
await self.getAllSubscriptions()
|
|
113
114
|
.then(r => {
|
|
114
115
|
_.set(update, 'subscriptions', r)
|
|
@@ -120,7 +121,8 @@ Module.prototype.updateStats = function (existingData) {
|
|
|
120
121
|
if (error) {
|
|
121
122
|
return reject(error);
|
|
122
123
|
}
|
|
123
|
-
|
|
124
|
+
|
|
125
|
+
// Count users online (in old gathering)
|
|
124
126
|
await gatheringOnline
|
|
125
127
|
.once('value')
|
|
126
128
|
.then((snap) => {
|
|
@@ -133,6 +135,7 @@ Module.prototype.updateStats = function (existingData) {
|
|
|
133
135
|
error = new Error(`Failed getting online users: ${e}`);
|
|
134
136
|
})
|
|
135
137
|
|
|
138
|
+
// Count users online (in new session)
|
|
136
139
|
await sessionsApp
|
|
137
140
|
.once('value')
|
|
138
141
|
.then((snap) => {
|
|
@@ -149,6 +152,10 @@ Module.prototype.updateStats = function (existingData) {
|
|
|
149
152
|
return reject(error);
|
|
150
153
|
}
|
|
151
154
|
|
|
155
|
+
// Set metadata
|
|
156
|
+
update.metadata = self.Manager.Metadata().set({tag: 'admin:get-stats'})
|
|
157
|
+
|
|
158
|
+
// Update stats
|
|
152
159
|
await stats
|
|
153
160
|
.set(update, { merge: true })
|
|
154
161
|
.catch(function (e) {
|
|
@@ -72,6 +72,10 @@ Module.prototype.main = function () {
|
|
|
72
72
|
|
|
73
73
|
const finalData = merge(newUser.properties, data);
|
|
74
74
|
|
|
75
|
+
// Set metadata
|
|
76
|
+
finalData.metadata = Manager.Metadata().set({tag: 'admin:sync-users'});
|
|
77
|
+
|
|
78
|
+
// Save to database
|
|
75
79
|
await self.libraries.admin.firestore().doc(`users/${account.uid}`)
|
|
76
80
|
.set(finalData, {merge: true})
|
|
77
81
|
.then(r => {
|
|
@@ -224,24 +224,25 @@ Module.prototype.processState_tokenize = function (newUrl, user) {
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
const storeResponse = await self.libraries.admin.firestore().doc(`users/${user.auth.uid}`)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
227
|
+
.set({
|
|
228
|
+
oauth2: {
|
|
229
|
+
[payload.data.payload.provider]: {
|
|
230
|
+
code: _.omit(
|
|
231
|
+
_.merge({}, payload.data.payload),
|
|
232
|
+
self.omittedPayloadFields,
|
|
233
|
+
),
|
|
234
|
+
token: tokenizeResponse,
|
|
235
|
+
identity: verifiedIdentity,
|
|
236
|
+
updated: {
|
|
237
|
+
timestamp: assistant.meta.startTime.timestamp,
|
|
238
|
+
timestampUNIX: assistant.meta.startTime.timestampUNIX,
|
|
239
|
+
}
|
|
239
240
|
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
241
|
+
},
|
|
242
|
+
metadata: Manager.Metadata().set({tag: 'user:oauth2'}),
|
|
243
|
+
}, { merge: true })
|
|
244
|
+
.then(r => r)
|
|
245
|
+
.catch(e => e)
|
|
245
246
|
|
|
246
247
|
assistant.log('storeResponse', user.auth.uid, storeResponse, {environment: 'production'});
|
|
247
248
|
|
|
@@ -313,20 +314,21 @@ Module.prototype.processState_refresh = function (newUrl, user) {
|
|
|
313
314
|
// }
|
|
314
315
|
|
|
315
316
|
const storeResponse = await self.libraries.admin.firestore().doc(`users/${user.auth.uid}`)
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
317
|
+
.set({
|
|
318
|
+
oauth2: {
|
|
319
|
+
[payload.data.payload.provider]: {
|
|
320
|
+
token: refreshResponse,
|
|
321
|
+
// identity: verifiedIdentity,
|
|
322
|
+
updated: {
|
|
323
|
+
timestamp: assistant.meta.startTime.timestamp,
|
|
324
|
+
timestampUNIX: assistant.meta.startTime.timestampUNIX,
|
|
325
|
+
}
|
|
324
326
|
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
327
|
+
},
|
|
328
|
+
metadata: Manager.Metadata().set({tag: 'user:oauth2'}),
|
|
329
|
+
}, { merge: true })
|
|
330
|
+
.then(r => r)
|
|
331
|
+
.catch(e => e)
|
|
330
332
|
|
|
331
333
|
assistant.log('storeResponse', user.auth.uid, storeResponse, {environment: 'production'});
|
|
332
334
|
|
|
@@ -351,23 +353,24 @@ Module.prototype.processState_deauthorize = function (newUrl, user) {
|
|
|
351
353
|
|
|
352
354
|
return new Promise(async function(resolve, reject) {
|
|
353
355
|
self.libraries.admin.firestore().doc(`users/${user.auth.uid}`)
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
356
|
+
.set({
|
|
357
|
+
oauth2: {
|
|
358
|
+
[payload.data.payload.provider]: {},
|
|
359
|
+
updated: {
|
|
360
|
+
timestamp: assistant.meta.startTime.timestamp,
|
|
361
|
+
timestampUNIX: assistant.meta.startTime.timestampUNIX,
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
metadata: Manager.Metadata().set({tag: 'user:oauth2'}),
|
|
365
|
+
}, { merge: true })
|
|
366
|
+
.then(function(data) {
|
|
367
|
+
return resolve({
|
|
368
|
+
data: {success: true},
|
|
369
|
+
});
|
|
370
|
+
})
|
|
371
|
+
.catch(function(e) {
|
|
372
|
+
return reject(e);
|
|
373
|
+
})
|
|
371
374
|
});
|
|
372
375
|
};
|
|
373
376
|
|
|
@@ -392,22 +395,23 @@ Module.prototype.processState_status = function (newUrl, user) {
|
|
|
392
395
|
}
|
|
393
396
|
|
|
394
397
|
Manager.libraries.admin.firestore().doc(`users/${user.auth.uid}`)
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
398
|
+
.set({
|
|
399
|
+
oauth2: {
|
|
400
|
+
[payload.data.payload.provider]: {},
|
|
401
|
+
updated: {
|
|
402
|
+
timestamp: assistant.meta.startTime.timestamp,
|
|
403
|
+
timestampUNIX: assistant.meta.startTime.timestampUNIX,
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
metadata: Manager.Metadata().set({tag: 'user:oauth2'}),
|
|
407
|
+
}, { merge: true })
|
|
408
|
+
.then(async () => {
|
|
409
|
+
assistant.log(`Removed disconnected token for user: ${user.auth.uid}`)
|
|
410
|
+
})
|
|
411
|
+
.catch((e) => e)
|
|
412
|
+
.finally(() => {
|
|
413
|
+
return resolve();
|
|
414
|
+
})
|
|
411
415
|
});
|
|
412
416
|
}
|
|
413
417
|
|
|
@@ -33,6 +33,7 @@ Module.prototype.main = function () {
|
|
|
33
33
|
self.libraries.admin.firestore().doc(`users/${user.auth.uid}`)
|
|
34
34
|
.set({
|
|
35
35
|
api: newKeys,
|
|
36
|
+
metadata: Manager.Metadata().set({tag: 'user:regenerate-api-keys'}),
|
|
36
37
|
}, {merge: true})
|
|
37
38
|
.then(r => {
|
|
38
39
|
return resolve({data: newKeys});
|
|
@@ -72,14 +72,13 @@ Module.prototype.signOutOfSession = function (uid, session) {
|
|
|
72
72
|
.set('signout')
|
|
73
73
|
.catch(e => self.assistant.error(`Failed to signout of session ${key}`, e))
|
|
74
74
|
|
|
75
|
-
//
|
|
75
|
+
// Delay so the client has time to react to the command
|
|
76
|
+
await powertools.wait(5000);
|
|
76
77
|
|
|
77
78
|
// Delete session
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
.catch(e => self.assistant.error(`Failed to delete session ${key}`, e))
|
|
82
|
-
}, 30000);
|
|
79
|
+
self.libraries.admin.database().ref(`${session}/${key}`)
|
|
80
|
+
.remove()
|
|
81
|
+
.catch(e => self.assistant.error(`Failed to delete session ${key}`, e))
|
|
83
82
|
|
|
84
83
|
count++;
|
|
85
84
|
}
|
|
@@ -52,64 +52,75 @@ Module.prototype.main = function () {
|
|
|
52
52
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
+
|
|
56
|
+
|
|
55
57
|
Module.prototype.signUp = function (payload) {
|
|
56
58
|
const self = this;
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// updatedReferral: true,
|
|
61
|
-
};
|
|
62
|
-
let error;
|
|
63
|
-
payload = payload || {};
|
|
59
|
+
const Manager = self.Manager;
|
|
60
|
+
const Api = self.Api;
|
|
61
|
+
const assistant = self.assistant;
|
|
64
62
|
|
|
65
63
|
return new Promise(async function(resolve, reject) {
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
const result = {
|
|
65
|
+
signedUp: false,
|
|
66
|
+
referrerUid: undefined,
|
|
67
|
+
// updatedReferral: true,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
payload = payload || {};
|
|
68
71
|
|
|
72
|
+
// Check if the user has a UID and email
|
|
69
73
|
if (!_.get(payload, 'auth.uid', null) || !_.get(payload, 'auth.email', null)) {
|
|
70
74
|
return reject(new Error('Cannot create user without UID and email.'))
|
|
71
75
|
}
|
|
72
76
|
|
|
77
|
+
// Update the user who referred this user
|
|
73
78
|
await self.updateReferral({
|
|
74
79
|
affiliateCode: _.get(payload, 'affiliate.referrer', null),
|
|
75
80
|
uid: payload.auth.uid,
|
|
76
81
|
})
|
|
77
|
-
.then(r => {
|
|
82
|
+
.then((r) => {
|
|
78
83
|
payload.affiliate.referrer = r.referrerUid;
|
|
79
84
|
result.referrerUid = payload.affiliate.referrer;
|
|
80
85
|
})
|
|
81
|
-
.catch(
|
|
86
|
+
.catch((e) => {
|
|
82
87
|
payload.affiliate.referrer = undefined;
|
|
83
88
|
console.error('Failed to update affiliate code', e)
|
|
84
89
|
})
|
|
85
90
|
|
|
86
|
-
// payload.affiliate.referrer = undefined;
|
|
87
|
-
|
|
88
|
-
await self.libraries.admin.firestore().doc(`users/${payload.auth.uid}`)
|
|
89
|
-
.get()
|
|
90
|
-
.then(async function (doc) {
|
|
91
|
-
existingUser = doc.data() || {};
|
|
92
|
-
})
|
|
93
|
-
.catch(function (e) {
|
|
94
|
-
error = e;
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
if (error) {
|
|
98
|
-
return reject(error);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const user = self.Manager.User(payload);
|
|
102
|
-
|
|
103
91
|
// Merge the payload and the default user object
|
|
104
|
-
|
|
105
|
-
|
|
92
|
+
const user = {
|
|
93
|
+
activity: {
|
|
94
|
+
geolocation: {
|
|
95
|
+
// Main geolocation
|
|
96
|
+
ip: assistant.request.ip,
|
|
97
|
+
continent: assistant.request.continent,
|
|
98
|
+
country: assistant.request.country,
|
|
99
|
+
city: assistant.request.city,
|
|
100
|
+
latitude: assistant.request.latitude,
|
|
101
|
+
longitude: assistant.request.longitude,
|
|
102
|
+
|
|
103
|
+
// Get User Agent data
|
|
104
|
+
userAgent: assistant.request.userAgent,
|
|
105
|
+
language: assistant.request.language,
|
|
106
|
+
platform: assistant.request.platform,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
affiliate: {
|
|
110
|
+
referrer: payload.affiliate.referrer,
|
|
111
|
+
},
|
|
112
|
+
metadata: Manager.Metadata().set({tag: 'user:sign-up'}),
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Set the user
|
|
106
116
|
self.libraries.admin.firestore().doc(`users/${payload.auth.uid}`)
|
|
107
|
-
.set(
|
|
108
|
-
.then(
|
|
117
|
+
.set(user, { merge: true })
|
|
118
|
+
.then((data) => {
|
|
109
119
|
result.signedUp = true;
|
|
120
|
+
|
|
110
121
|
return resolve(result);
|
|
111
122
|
})
|
|
112
|
-
.catch(
|
|
123
|
+
.catch((e) => {
|
|
113
124
|
return reject(e);
|
|
114
125
|
})
|
|
115
126
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const _ = require('lodash');
|
|
3
3
|
const jetpack = require('fs-jetpack');
|
|
4
|
+
const powertools = require('node-powertools');
|
|
4
5
|
|
|
5
6
|
function Module() {
|
|
6
7
|
|
|
@@ -27,6 +28,7 @@ Module.prototype.init = function (Manager, data) {
|
|
|
27
28
|
const resolved = self.resolveCommand(self.assistant.request.data.command);
|
|
28
29
|
self.assistant.request.data.command = resolved.command;
|
|
29
30
|
self.assistant.request.data.payload = self.assistant.request.data.payload || {};
|
|
31
|
+
self.assistant.request.data.options = self.assistant.request.data.options || {};
|
|
30
32
|
|
|
31
33
|
if (Manager.options.log) {
|
|
32
34
|
self.assistant.log(`Executing (log): ${resolved.command}`, self.assistant.request, JSON.stringify(self.assistant.request), {environment: 'production'})
|
|
@@ -48,15 +50,31 @@ Module.prototype.main = function() {
|
|
|
48
50
|
self.payload.data = assistant.request.data;
|
|
49
51
|
self.payload.user = await assistant.authenticate();
|
|
50
52
|
|
|
53
|
+
// Quit if OPTIONS request
|
|
51
54
|
if (self.assistant.request.method === 'OPTIONS') {
|
|
52
55
|
return resolve();
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
// Resolve command
|
|
55
59
|
const resolved = self.resolveCommand(self.payload.data.command);
|
|
56
60
|
|
|
57
61
|
self.assistant.log(`Executing: ${resolved.command}`, self.payload, JSON.stringify(self.payload), {environment: 'production'})
|
|
58
62
|
self.assistant.log(`Resolved URL: ${Manager.project.functionsUrl}?command=${encodeURIComponent(resolved.command)}&payload=${encodeURIComponent(JSON.stringify(self.assistant.request.data.payload))}`, {environment: 'development'})
|
|
59
63
|
|
|
64
|
+
// Set up options
|
|
65
|
+
self.payload.data.options = self.payload.data.options || {};
|
|
66
|
+
self.payload.data.options.delay = self.payload.data.options.delay || 0;
|
|
67
|
+
|
|
68
|
+
// Delay
|
|
69
|
+
if (self.payload.data.options.delay > 0) {
|
|
70
|
+
let delay = Math.floor(self.payload.data.options.delay / 1000);
|
|
71
|
+
|
|
72
|
+
await powertools.poll(() => {
|
|
73
|
+
self.assistant.log(`Delaying for ${delay--} seconds...`, {environment: 'production'});
|
|
74
|
+
}, {interval: 1000, timeout: self.payload.data.options.delay})
|
|
75
|
+
.catch(e => e);
|
|
76
|
+
}
|
|
77
|
+
|
|
60
78
|
if (!resolved.exists) {
|
|
61
79
|
self.payload.response.status = 400;
|
|
62
80
|
self.payload.response.error = new Error(`${self.payload.data.command} is not a valid command`);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { get } = require('lodash');
|
|
2
|
+
|
|
1
3
|
function Module() {
|
|
2
4
|
const self = this;
|
|
3
5
|
}
|
|
@@ -19,13 +21,33 @@ Module.prototype.main = function () {
|
|
|
19
21
|
const user = self.user;
|
|
20
22
|
|
|
21
23
|
return new Promise(async function(resolve, reject) {
|
|
24
|
+
// Check if exists already
|
|
25
|
+
// It could exist already if user signed up with email and then signed in with Google
|
|
26
|
+
const existingUser = await libraries.admin.firestore().doc(`users/${user.uid}`)
|
|
27
|
+
.get()
|
|
28
|
+
.then((doc) => doc.data() || {})
|
|
29
|
+
.catch(e => e)
|
|
30
|
+
|
|
31
|
+
// If user already exists, skip auth-on-create handler
|
|
32
|
+
if (
|
|
33
|
+
existingUser instanceof Error
|
|
34
|
+
|| get(existingUser, 'auth.uid', null)
|
|
35
|
+
|| get(existingUser, 'auth.email', null)
|
|
36
|
+
) {
|
|
37
|
+
assistant.log(`auth-on-create: Skipping handler because user already exists ${user.uid}:`, existingUser, {environment: 'production'});
|
|
38
|
+
|
|
39
|
+
return resolve(self);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Build user object
|
|
22
43
|
const newUser = self.Manager.User({
|
|
23
44
|
auth: {
|
|
24
45
|
uid: user.uid,
|
|
25
46
|
email: user.email,
|
|
26
47
|
}
|
|
27
|
-
});
|
|
48
|
+
}).properties;
|
|
28
49
|
|
|
50
|
+
// Set up analytics
|
|
29
51
|
const analytics = self.Manager.Analytics({
|
|
30
52
|
assistant: assistant,
|
|
31
53
|
uuid: user.uid,
|
|
@@ -42,14 +64,17 @@ Module.prototype.main = function () {
|
|
|
42
64
|
return true
|
|
43
65
|
}
|
|
44
66
|
}).length < 1) {
|
|
45
|
-
return;
|
|
67
|
+
return resolve(self);
|
|
46
68
|
}
|
|
47
69
|
|
|
70
|
+
// Add metadata
|
|
71
|
+
newUser.metadata = self.Manager.Metadata().set({tag: 'auth:on-create'});
|
|
72
|
+
|
|
48
73
|
// Add user record
|
|
49
|
-
await libraries.admin.firestore().doc(`users/${newUser.
|
|
50
|
-
.set(newUser
|
|
51
|
-
.catch(e => {
|
|
52
|
-
assistant.error(e, {environment: 'production'});
|
|
74
|
+
await libraries.admin.firestore().doc(`users/${newUser.auth.uid}`)
|
|
75
|
+
.set(newUser, {merge: true})
|
|
76
|
+
.catch((e) => {
|
|
77
|
+
assistant.error(`auth-on-create: Failed save user record`, e, {environment: 'production'});
|
|
53
78
|
})
|
|
54
79
|
|
|
55
80
|
// Update user count
|
|
@@ -57,11 +82,12 @@ Module.prototype.main = function () {
|
|
|
57
82
|
.update({
|
|
58
83
|
'users.total': libraries.admin.firestore.FieldValue.increment(1),
|
|
59
84
|
})
|
|
60
|
-
.catch(e => {
|
|
61
|
-
assistant.error(e, {environment: 'production'});
|
|
85
|
+
.catch((e) => {
|
|
86
|
+
assistant.error(`auth-on-create: Failed to increment user`, e, {environment: 'production'});
|
|
62
87
|
})
|
|
63
88
|
|
|
64
|
-
assistant.log(
|
|
89
|
+
assistant.log(`auth-on-create: User created ${user.uid}:`, newUser, user, {environment: 'production'});
|
|
90
|
+
|
|
65
91
|
return resolve(self);
|
|
66
92
|
});
|
|
67
93
|
};
|
|
@@ -19,6 +19,7 @@ Module.prototype.main = function () {
|
|
|
19
19
|
const user = self.user;
|
|
20
20
|
|
|
21
21
|
return new Promise(async function(resolve, reject) {
|
|
22
|
+
// Set up analytics
|
|
22
23
|
const analytics = self.Manager.Analytics({
|
|
23
24
|
assistant: assistant,
|
|
24
25
|
uuid: user.uid,
|
|
@@ -29,11 +30,11 @@ Module.prototype.main = function () {
|
|
|
29
30
|
// label: 'regular',
|
|
30
31
|
});
|
|
31
32
|
|
|
32
|
-
//
|
|
33
|
+
// Delete user record
|
|
33
34
|
await libraries.admin.firestore().doc(`users/${user.uid}`)
|
|
34
35
|
.delete()
|
|
35
|
-
.catch(e => {
|
|
36
|
-
assistant.error(e, {environment: 'production'});
|
|
36
|
+
.catch((e) => {
|
|
37
|
+
assistant.error(`auth-on-delete: Delete user failed`, e, {environment: 'production'});
|
|
37
38
|
})
|
|
38
39
|
|
|
39
40
|
// Update user count
|
|
@@ -41,11 +42,11 @@ Module.prototype.main = function () {
|
|
|
41
42
|
.update({
|
|
42
43
|
'users.total': libraries.admin.firestore.FieldValue.increment(-1),
|
|
43
44
|
})
|
|
44
|
-
.catch(e => {
|
|
45
|
-
assistant.error(e, {environment: 'production'});
|
|
45
|
+
.catch((e) => {
|
|
46
|
+
assistant.error(`auth-on-delete: Failed to decrement user`, e, {environment: 'production'});
|
|
46
47
|
})
|
|
47
48
|
|
|
48
|
-
assistant.log(
|
|
49
|
+
assistant.log(`auth-on-delete: User deleted ${user.uid}:`, user, {environment: 'production'});
|
|
49
50
|
|
|
50
51
|
return resolve(self);
|
|
51
52
|
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const moment = require('moment');
|
|
2
|
+
const uuidv4 = require('uuid').v4;
|
|
3
|
+
|
|
4
|
+
function Metadata(Manager, document) {
|
|
5
|
+
const self = this;
|
|
6
|
+
|
|
7
|
+
self.Manager = Manager;
|
|
8
|
+
|
|
9
|
+
self.document = document || {};
|
|
10
|
+
|
|
11
|
+
return self;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Metadata.prototype.set = function (metadata) {
|
|
15
|
+
const self = this;
|
|
16
|
+
|
|
17
|
+
const now = moment();
|
|
18
|
+
|
|
19
|
+
self.document = self.document || {};
|
|
20
|
+
self.document.metadata = self.document.metadata || {};
|
|
21
|
+
|
|
22
|
+
self.document.metadata.updated = self.document.metadata.updated || {};
|
|
23
|
+
self.document.metadata.updated.timestamp = now.toISOString();
|
|
24
|
+
self.document.metadata.updated.timestampUNIX = now.unix();
|
|
25
|
+
self.document.metadata.tag = metadata.tag || uuidv4();
|
|
26
|
+
|
|
27
|
+
self.Manager.assistant.log(`Metadata: #${self.document.metadata.tag}`);
|
|
28
|
+
|
|
29
|
+
return self.document.metadata;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
module.exports = Metadata;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
const moment = require('moment');
|
|
2
2
|
const { get } = require('lodash');
|
|
3
3
|
|
|
4
|
-
function SubscriptionResolver(profile, resource) {
|
|
4
|
+
function SubscriptionResolver(Manager, profile, resource) {
|
|
5
5
|
const self = this;
|
|
6
6
|
|
|
7
|
+
self.Manager = Manager;
|
|
7
8
|
self.profile = profile;
|
|
8
9
|
self.resource = resource;
|
|
10
|
+
|
|
11
|
+
return self;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
SubscriptionResolver.prototype.resolve = function (options) {
|
|
@@ -5,9 +5,11 @@ const powertools = require('node-powertools');
|
|
|
5
5
|
const UIDGenerator = require('uid-generator');
|
|
6
6
|
const uidgen = new UIDGenerator(256);
|
|
7
7
|
|
|
8
|
-
function User(settings, options) {
|
|
8
|
+
function User(Manager, settings, options) {
|
|
9
9
|
const self = this;
|
|
10
10
|
|
|
11
|
+
self.Manager = Manager;
|
|
12
|
+
|
|
11
13
|
settings = settings || {};
|
|
12
14
|
options = options || {};
|
|
13
15
|
|
|
@@ -81,6 +83,17 @@ function User(settings, options) {
|
|
|
81
83
|
timestamp: _.get(settings, 'activity.created.timestamp', useDefaults ? now : null),
|
|
82
84
|
timestampUNIX: _.get(settings, 'activity.created.timestampUNIX', useDefaults ? nowUNIX : null),
|
|
83
85
|
},
|
|
86
|
+
geolocation: {
|
|
87
|
+
ip: _.get(settings, 'activity.geolocation.ip', useDefaults ? 'unknown' : null),
|
|
88
|
+
continent: _.get(settings, 'activity.geolocation.continent', useDefaults ? 'unknown' : null),
|
|
89
|
+
country: _.get(settings, 'activity.geolocation.country', useDefaults ? 'unknown' : null),
|
|
90
|
+
city: _.get(settings, 'activity.geolocation.city', useDefaults ? 'unknown' : null),
|
|
91
|
+
latitude: _.get(settings, 'activity.geolocation.latitude', useDefaults ? 'unknown' : null),
|
|
92
|
+
longitude: _.get(settings, 'activity.geolocation.longitude', useDefaults ? 'unknown' : null),
|
|
93
|
+
userAgent: _.get(settings, 'activity.geolocation.userAgent', useDefaults ? 'unknown' : null),
|
|
94
|
+
language: _.get(settings, 'activity.geolocation.language', useDefaults ? 'unknown' : null),
|
|
95
|
+
platform: _.get(settings, 'activity.geolocation.platform', useDefaults ? 'unknown' : null),
|
|
96
|
+
},
|
|
84
97
|
},
|
|
85
98
|
api: {
|
|
86
99
|
clientId: _.get(settings, 'api.clientId', useDefaults ? `${uuid4()}` : null),
|
package/src/manager/index.js
CHANGED
|
@@ -554,7 +554,7 @@ Manager.prototype.Assistant = function(ref, options) {
|
|
|
554
554
|
Manager.prototype.User = function () {
|
|
555
555
|
const self = this;
|
|
556
556
|
self.libraries.User = self.libraries.User || require('./helpers/user.js');
|
|
557
|
-
return new self.libraries.User(...arguments);
|
|
557
|
+
return new self.libraries.User(self, ...arguments);
|
|
558
558
|
};
|
|
559
559
|
|
|
560
560
|
Manager.prototype.Analytics = function () {
|
|
@@ -578,7 +578,13 @@ Manager.prototype.Roles = function () {
|
|
|
578
578
|
Manager.prototype.SubscriptionResolver = function () {
|
|
579
579
|
const self = this;
|
|
580
580
|
self.libraries.SubscriptionResolver = self.libraries.SubscriptionResolver || require('./helpers/subscription-resolver.js');
|
|
581
|
-
return new self.libraries.SubscriptionResolver(...arguments);
|
|
581
|
+
return new self.libraries.SubscriptionResolver(self, ...arguments);
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
Manager.prototype.Metadata = function () {
|
|
585
|
+
const self = this;
|
|
586
|
+
self.libraries.Metadata = self.libraries.Metadata || require('./helpers/metadata.js');
|
|
587
|
+
return new self.libraries.Metadata(self, ...arguments);
|
|
582
588
|
};
|
|
583
589
|
|
|
584
590
|
// For importing API libraries
|