backend-manager 2.5.71 → 2.5.74

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-manager",
3
- "version": "2.5.71",
3
+ "version": "2.5.74",
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.3",
34
+ "backend-assistant": "^1.0.4",
35
35
  "busboy": "^1.6.0",
36
36
  "chalk": "^4.1.2",
37
37
  "cors": "^2.8.5",
@@ -62,4 +62,4 @@
62
62
  "wonderful-fetch": "^0.0.17",
63
63
  "yargs": "^17.7.1"
64
64
  }
65
- }
65
+ }
@@ -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
- .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,
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
- }, { merge: true })
243
- .then(r => r)
244
- .catch(e => e)
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
- .set({
317
- oauth2: {
318
- [payload.data.payload.provider]: {
319
- token: refreshResponse,
320
- // identity: verifiedIdentity,
321
- updated: {
322
- timestamp: assistant.meta.startTime.timestamp,
323
- timestampUNIX: assistant.meta.startTime.timestampUNIX,
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
- }, { merge: true })
328
- .then(r => r)
329
- .catch(e => e)
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
- .set({
355
- oauth2: {
356
- [payload.data.payload.provider]: {},
357
- updated: {
358
- timestamp: assistant.meta.startTime.timestamp,
359
- timestampUNIX: assistant.meta.startTime.timestampUNIX,
360
- }
361
- }
362
- }, { merge: true })
363
- .then(function(data) {
364
- return resolve({
365
- data: {success: true},
366
- });
367
- })
368
- .catch(function(e) {
369
- return reject(e);
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
- .set({
396
- oauth2: {
397
- [payload.data.payload.provider]: {},
398
- updated: {
399
- timestamp: assistant.meta.startTime.timestamp,
400
- timestampUNIX: assistant.meta.startTime.timestampUNIX,
401
- }
402
- }
403
- }, { merge: true })
404
- .then(async () => {
405
- assistant.log(`Removed disconnected token for user: ${user.auth.uid}`)
406
- })
407
- .catch((e) => e)
408
- .finally(() => {
409
- return resolve();
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
- // await powertools.wait(3000);
75
+ // Delay so the client has time to react to the command
76
+ await powertools.wait(5000);
76
77
 
77
78
  // Delete session
78
- setTimeout(function () {
79
- self.libraries.admin.database().ref(`${session}/${key}`)
80
- .remove()
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
  }
@@ -15,6 +15,21 @@ Module.prototype.main = function () {
15
15
  return new Promise(async function(resolve, reject) {
16
16
  self.Api.resolveUser({adminRequired: true})
17
17
  .then(async (user) => {
18
+ // Get auth user from firebase
19
+ const authUser = await self.libraries.admin.auth().getUser(user.auth.uid).catch(e => e);
20
+
21
+ if (authUser instanceof Error) {
22
+ return reject(assistant.errorManager(`Failed to get auth user: ${authUser}`, {code: 500, sentry: false, send: false, log: false}).error)
23
+ }
24
+
25
+ // Difference in hours
26
+ const diff = (Date.now() - new Date(authUser.metadata.creationTime)) / 36e5;
27
+
28
+ // If the user is not new, reject
29
+ if (diff > 0.5) {
30
+ return reject(assistant.errorManager(`User is not new.`, {code: 400, sentry: false, send: false, log: false}).error)
31
+ }
32
+
18
33
  await self.signUp({
19
34
  auth: {
20
35
  uid: _.get(user, 'auth.uid', null),
@@ -52,64 +67,75 @@ Module.prototype.main = function () {
52
67
 
53
68
  };
54
69
 
70
+
71
+
55
72
  Module.prototype.signUp = function (payload) {
56
73
  const self = this;
57
- const result = {
58
- signedUp: false,
59
- referrerUid: undefined,
60
- // updatedReferral: true,
61
- };
62
- let error;
63
- payload = payload || {};
74
+ const Manager = self.Manager;
75
+ const Api = self.Api;
76
+ const assistant = self.assistant;
64
77
 
65
78
  return new Promise(async function(resolve, reject) {
66
- let existingUser = {};
67
- let finalPayload = {};
79
+ const result = {
80
+ signedUp: false,
81
+ referrerUid: undefined,
82
+ // updatedReferral: true,
83
+ };
68
84
 
85
+ payload = payload || {};
86
+
87
+ // Check if the user has a UID and email
69
88
  if (!_.get(payload, 'auth.uid', null) || !_.get(payload, 'auth.email', null)) {
70
89
  return reject(new Error('Cannot create user without UID and email.'))
71
90
  }
72
91
 
92
+ // Update the user who referred this user
73
93
  await self.updateReferral({
74
94
  affiliateCode: _.get(payload, 'affiliate.referrer', null),
75
95
  uid: payload.auth.uid,
76
96
  })
77
- .then(r => {
97
+ .then((r) => {
78
98
  payload.affiliate.referrer = r.referrerUid;
79
99
  result.referrerUid = payload.affiliate.referrer;
80
100
  })
81
- .catch(function (e) {
101
+ .catch((e) => {
82
102
  payload.affiliate.referrer = undefined;
83
103
  console.error('Failed to update affiliate code', e)
84
104
  })
85
105
 
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
106
  // Merge the payload and the default user object
104
- finalPayload = _.merge({}, existingUser, user.properties)
105
-
107
+ const user = {
108
+ activity: {
109
+ geolocation: {
110
+ // Main geolocation
111
+ ip: assistant.request.ip,
112
+ continent: assistant.request.continent,
113
+ country: assistant.request.country,
114
+ city: assistant.request.city,
115
+ latitude: assistant.request.latitude,
116
+ longitude: assistant.request.longitude,
117
+
118
+ // Get User Agent data
119
+ userAgent: assistant.request.userAgent,
120
+ language: assistant.request.language,
121
+ platform: assistant.request.platform,
122
+ },
123
+ },
124
+ affiliate: {
125
+ referrer: payload.affiliate.referrer,
126
+ },
127
+ metadata: Manager.Metadata().set({tag: 'user:sign-up'}),
128
+ }
129
+
130
+ // Set the user
106
131
  self.libraries.admin.firestore().doc(`users/${payload.auth.uid}`)
107
- .set(finalPayload, { merge: true })
108
- .then(function(data) {
132
+ .set(user, { merge: true })
133
+ .then((data) => {
109
134
  result.signedUp = true;
135
+
110
136
  return resolve(result);
111
137
  })
112
- .catch(function(e) {
138
+ .catch((e) => {
113
139
  return reject(e);
114
140
  })
115
141
 
@@ -65,7 +65,8 @@ Module.prototype.main = function () {
65
65
  decision: decision,
66
66
  owner: {
67
67
  uid: get(user, 'auth.uid', null),
68
- }
68
+ },
69
+ metadata: Manager.Metadata().set({tag: 'user:submit-feedback'}),
69
70
  }, {merge: true})
70
71
  .then(r => {
71
72
  return resolve({
@@ -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.properties.auth.uid}`)
50
- .set(newUser.properties, {merge: true})
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('User created:', user, {environment: 'production'});
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
- // Add user record
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('User deleted:', user, {environment: 'production'});
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),
@@ -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