backend-manager 2.5.123 → 2.6.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # CHANGELOG
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
+
7
+ ## Changelog Categories
8
+
9
+ - `BREAKING` for breaking changes.
10
+ - `Added` for new features.
11
+ - `Changed` for changes in existing functionality.
12
+ - `Deprecated` for soon-to-be removed features.
13
+ - `Removed` for now removed features.
14
+ - `Fixed` for any bug fixes.
15
+ - `Security` in case of vulnerabilities.
16
+
17
+ ---
18
+
19
+ ## [2.6.0] - 2023-09-05
20
+ ### Added
21
+ - Identity Platform auth/before-create.js
22
+ - Identity Platform auth/before-signin.js
23
+ - Disable these by passing `options.setupFunctionsIdentity: false`
24
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-manager",
3
- "version": "2.5.123",
3
+ "version": "2.6.0",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -66,4 +66,4 @@
66
66
  "wonderful-log": "^1.0.5",
67
67
  "yargs": "^17.7.2"
68
68
  }
69
- }
69
+ }
@@ -54,7 +54,7 @@ Module.prototype.main = function () {
54
54
  })
55
55
  .catch(function (e) {
56
56
  return reject(assistant.errorManager(`Failed to get: ${e}`, {code: 500, sentry: false, send: false, log: false}).error)
57
- })
57
+ })
58
58
  });
59
59
 
60
60
  };
@@ -79,6 +79,7 @@ Module.prototype.updateStats = function (existingData) {
79
79
  const stats = self.libraries.admin.firestore().doc(`meta/stats`);
80
80
  const gatheringOnline = self.libraries.admin.database().ref(`gatherings/online`);
81
81
  const sessionsApp = self.libraries.admin.database().ref(`sessions/app`);
82
+ const sessionsOnline = self.libraries.admin.database().ref(`sessions/online`);
82
83
 
83
84
  let error = null;
84
85
  let update = {
@@ -121,32 +122,29 @@ Module.prototype.updateStats = function (existingData) {
121
122
  if (error) {
122
123
  return reject(error);
123
124
  }
124
-
125
+
126
+ const _countUsersOnline = async (app) => {
127
+ await app
128
+ .once('value')
129
+ .then((snap) => {
130
+ const data = snap.val() || {};
131
+ const keys = Object.keys(data);
132
+ const existing = _.get(update, 'users.online', 0)
133
+ _.set(update, 'users.online', existing + keys.length)
134
+ })
135
+ .catch(e => {
136
+ error = new Error(`Failed getting online users: ${e}`);
137
+ })
138
+ }
139
+
125
140
  // Count users online (in old gathering)
126
- await gatheringOnline
127
- .once('value')
128
- .then((snap) => {
129
- const data = snap.val() || {};
130
- const keys = Object.keys(data);
131
- const existing = _.get(update, 'users.online', 0)
132
- _.set(update, 'users.online', existing + keys.length)
133
- })
134
- .catch(e => {
135
- error = new Error(`Failed getting online users: ${e}`);
136
- })
141
+ await _countUsersOnline(gatheringOnline);
137
142
 
138
143
  // Count users online (in new session)
139
- await sessionsApp
140
- .once('value')
141
- .then((snap) => {
142
- const data = snap.val() || {};
143
- const keys = Object.keys(data);
144
- const existing = _.get(update, 'users.online', 0)
145
- _.set(update, 'users.online', existing + keys.length)
146
- })
147
- .catch(e => {
148
- error = new Error(`Failed getting online users: ${e}`);
149
- })
144
+ await _countUsersOnline(sessionsApp);
145
+
146
+ // Count users online (in new session)
147
+ await _countUsersOnline(sessionsOnine);
150
148
 
151
149
  if (error) {
152
150
  return reject(error);
@@ -111,6 +111,7 @@ Module.prototype.signUp = function (payload) {
111
111
  // Main geolocation
112
112
  ip: assistant.request.ip,
113
113
  continent: assistant.request.continent,
114
+ region: assistant.request.region,
114
115
  country: assistant.request.country,
115
116
  city: assistant.request.city,
116
117
  latitude: assistant.request.latitude,
@@ -120,6 +121,7 @@ Module.prototype.signUp = function (payload) {
120
121
  userAgent: assistant.request.userAgent,
121
122
  language: assistant.request.language,
122
123
  platform: assistant.request.platform,
124
+ mobile: assistant.request.mobile,
123
125
  },
124
126
  },
125
127
  affiliate: {
@@ -127,7 +129,7 @@ Module.prototype.signUp = function (payload) {
127
129
  },
128
130
  metadata: Manager.Metadata().set({tag: 'user:sign-up'}),
129
131
  }
130
-
132
+
131
133
  assistant.log(`signUp(): user`, user, {environment: 'production'})
132
134
 
133
135
  // Set the user
@@ -157,7 +159,7 @@ Module.prototype.updateReferral = function (payload) {
157
159
  payload = payload || {};
158
160
 
159
161
  assistant.log(`updateReferral(): payload`, payload, {environment: 'production'})
160
-
162
+
161
163
  self.libraries.admin.firestore().collection('users')
162
164
  .where('affiliate.code', '==', payload.affiliateCode)
163
165
  .get()
@@ -0,0 +1,114 @@
1
+ const { get, merge } = require('lodash');
2
+ const functions = require('firebase-functions');
3
+ const admin = require('firebase-admin');
4
+
5
+ function Module() {
6
+ const self = this;
7
+ }
8
+
9
+ Module.prototype.init = function (Manager, payload) {
10
+ const self = this;
11
+ self.Manager = Manager;
12
+ self.libraries = Manager.libraries;
13
+ self.assistant = Manager.Assistant();
14
+ self.user = payload.user;
15
+ self.context = payload.context;
16
+
17
+ return self;
18
+ };
19
+
20
+ Module.prototype.main = function () {
21
+ const self = this;
22
+ const libraries = self.libraries;
23
+ const assistant = self.assistant;
24
+ const user = self.user;
25
+ const context = self.context;
26
+
27
+ return new Promise(async function(resolve, reject) {
28
+ const functions = self.libraries.functions;
29
+ const admin = self.libraries.admin;
30
+
31
+ assistant.log(`Request: ${user.uid}`, user, context, { environment: 'production' });
32
+
33
+ const ipAddress = context.ipAddress;
34
+ const currentTime = Date.now();
35
+ const oneHour = 60 * 60 * 1000; // One hour in milliseconds
36
+
37
+ // Get current rate-limiting data
38
+ const rateLimitingData = await self.Manager.storage({ name: 'rate-limiting' }).get(`ipRateLimits.${ipAddress}`);
39
+ const count = get(rateLimitingData, 'count', 0);
40
+ const lastTime = get(rateLimitingData, 'lastTime', 0);
41
+
42
+ assistant.log(`Rate limiting for ${ipAddress}:`, rateLimitingData, { environment: 'production' });
43
+
44
+ if (currentTime - lastTime < oneHour && count >= 2) {
45
+ assistant.error(`Too many attemps to create an account for ${ipAddress}`, { environment: 'production' });
46
+
47
+ throw new functions.auth.HttpsError('resource-exhausted');
48
+ }
49
+
50
+ // Update rate-limiting data
51
+ await self.Manager.storage({ name: 'rate-limiting' }).set(`ipRateLimits.${ipAddress}`, { count: count + 1, lastTime: currentTime });
52
+
53
+ const existingAccount = await admin.firestore().doc(`users/${user.uid}`)
54
+ .get()
55
+ .then((doc) => doc.data())
56
+ .catch(e => e);
57
+
58
+ // If user already exists, skip auth-on-create handler
59
+ if (existingAccount instanceof Error) {
60
+ assistant.error(`Failed to get existing account ${user.uid}:`, existingAccount, { environment: 'production' });
61
+
62
+ throw new functions.auth.HttpsError('internal');
63
+ }
64
+
65
+ let account = {
66
+ activity: {
67
+ lastActivity: {
68
+ timestamp: new Date(currentTime).toISOString(),
69
+ timestampUNIX: Math.round(currentTime / 1000),
70
+ },
71
+ geolocation: {
72
+ ip: ipAddress,
73
+ language: context.locale,
74
+ userAgent: context.userAgent,
75
+ },
76
+ },
77
+ };
78
+
79
+ // If it exists, just add the activity data
80
+ if (!get(existingAccount, 'auth.uid', null) || !get(existingAccount, 'auth.email', null)) {
81
+ account = merge(
82
+ self.Manager.User({
83
+ auth: {
84
+ uid: user.uid,
85
+ email: user.email,
86
+ },
87
+ activity: {
88
+ created: {
89
+ timestamp: new Date(currentTime).toISOString(),
90
+ timestampUNIX: Math.round(currentTime / 1000),
91
+ },
92
+ },
93
+ }).properties,
94
+ account,
95
+ );
96
+ }
97
+
98
+ // Save IP to Firestore after successful IP check
99
+ const update = await admin.firestore().doc(`users/${user.uid}`)
100
+ .set(account, { merge: true });
101
+
102
+ if (update instanceof Error) {
103
+ assistant.error(`Failed to update user ${user.uid}:`, update, { environment: 'production' });
104
+
105
+ throw new functions.auth.HttpsError('internal');
106
+ }
107
+
108
+ assistant.log(`User created at users/${user.uid}`, account, { environment: 'production' });
109
+
110
+ return resolve(self);
111
+ });
112
+ };
113
+
114
+ module.exports = Module;
@@ -0,0 +1,59 @@
1
+ const { get } = require('lodash');
2
+
3
+ function Module() {
4
+ const self = this;
5
+ }
6
+
7
+ Module.prototype.init = function (Manager, payload) {
8
+ const self = this;
9
+ self.Manager = Manager;
10
+ self.libraries = Manager.libraries;
11
+ self.assistant = Manager.Assistant();
12
+ self.user = payload.user
13
+ self.context = payload.context
14
+
15
+ return self;
16
+ };
17
+
18
+ Module.prototype.main = function () {
19
+ const self = this;
20
+ const libraries = self.libraries;
21
+ const assistant = self.assistant;
22
+ const user = self.user;
23
+ const context = self.context;
24
+
25
+ return new Promise(async function(resolve, reject) {
26
+
27
+ assistant.log(`Request: ${user.uid}`, user, context, {environment: 'production'});
28
+
29
+ const now = new Date();
30
+
31
+ // Save IP to Firestore after successful IP check
32
+ const update = await admin.firestore().doc(`users/${user.uid}`)
33
+ .set({
34
+ activity: {
35
+ lastActivity: {
36
+ timestamp: now.toISOString(),
37
+ timestampUNIX: Math.round(now.getTime() / 1000),
38
+ },
39
+ geolocation: {
40
+ ip: context.ipAddress,
41
+ language: context.locale,
42
+ userAgent: context.userAgent,
43
+ },
44
+ },
45
+ }, { merge: true });
46
+
47
+ if (update instanceof Error) {
48
+ assistant.error(`Failed to update user ${user.uid}:`, update, { environment: 'production' });
49
+
50
+ throw new functions.auth.HttpsError('internal');
51
+ }
52
+
53
+ assistant.log(`Updated user activity`, {environment: 'production'});
54
+
55
+ return resolve(self);
56
+ });
57
+ };
58
+
59
+ module.exports = Module;
@@ -10,8 +10,9 @@ Module.prototype.init = function (Manager, payload) {
10
10
  self.libraries = Manager.libraries;
11
11
  self.assistant = Manager.Assistant();
12
12
  self.user = payload.user
13
+ self.context = payload.context
13
14
 
14
- return self;
15
+ return self;
15
16
  };
16
17
 
17
18
  Module.prototype.main = function () {
@@ -19,8 +20,11 @@ Module.prototype.main = function () {
19
20
  const libraries = self.libraries;
20
21
  const assistant = self.assistant;
21
22
  const user = self.user;
23
+ const context = self.context;
22
24
 
23
25
  return new Promise(async function(resolve, reject) {
26
+ assistant.log(`Request: ${user.uid}`, user, context, { environment: 'production' });
27
+
24
28
  // Check if exists already
25
29
  // It could exist already if user signed up with email and then signed in with Google
26
30
  const existingUser = await libraries.admin.firestore().doc(`users/${user.uid}`)
@@ -29,15 +33,18 @@ Module.prototype.main = function () {
29
33
  .catch(e => e)
30
34
 
31
35
  // If user already exists, skip auth-on-create handler
32
- if (
33
- existingUser instanceof Error
34
- || get(existingUser, 'auth.uid', null)
36
+ if (existingUser instanceof Error) {
37
+ assistant.error(`Failed to get existing user ${user.uid}:`, existingUser, { environment: 'production' });
38
+
39
+ return reject(existingUser);
40
+ } else if (
41
+ get(existingUser, 'auth.uid', null)
35
42
  || get(existingUser, 'auth.email', null)
36
43
  ) {
37
- assistant.log(`auth-on-create: Skipping handler because user already exists ${user.uid}:`, existingUser, {environment: 'production'});
44
+ assistant.log(`Skipping handler because user already exists ${user.uid}:`, existingUser, {environment: 'production'});
38
45
 
39
- return resolve(self);
40
- }
46
+ return resolve(self);
47
+ }
41
48
 
42
49
  // Build user object
43
50
  const newUser = self.Manager.User({
@@ -45,7 +52,7 @@ Module.prototype.main = function () {
45
52
  uid: user.uid,
46
53
  email: user.email,
47
54
  }
48
- }).properties;
55
+ }).properties;
49
56
 
50
57
  // Set up analytics
51
58
  const analytics = self.Manager.Analytics({
@@ -64,7 +71,7 @@ Module.prototype.main = function () {
64
71
  return true
65
72
  }
66
73
  }).length < 1) {
67
- return resolve(self);
74
+ return resolve(self);
68
75
  }
69
76
 
70
77
  // Add metadata
@@ -74,7 +81,7 @@ Module.prototype.main = function () {
74
81
  await libraries.admin.firestore().doc(`users/${newUser.auth.uid}`)
75
82
  .set(newUser, {merge: true})
76
83
  .catch((e) => {
77
- assistant.error(`auth-on-create: Failed save user record`, e, {environment: 'production'});
84
+ assistant.error(`Failed save user record`, e, {environment: 'production'});
78
85
  })
79
86
 
80
87
  // Update user count
@@ -83,12 +90,12 @@ Module.prototype.main = function () {
83
90
  'users.total': libraries.admin.firestore.FieldValue.increment(1),
84
91
  })
85
92
  .catch((e) => {
86
- assistant.error(`auth-on-create: Failed to increment user`, e, {environment: 'production'});
93
+ assistant.error(`Failed to increment user`, e, {environment: 'production'});
87
94
  })
88
95
 
89
- assistant.log(`auth-on-create: User created ${user.uid}:`, newUser, user, {environment: 'production'});
96
+ assistant.log(`User created ${user.uid}:`, newUser, user, context, {environment: 'production'});
90
97
 
91
- return resolve(self);
98
+ return resolve(self);
92
99
  });
93
100
  };
94
101
 
@@ -8,8 +8,9 @@ Module.prototype.init = function (Manager, payload) {
8
8
  self.libraries = Manager.libraries;
9
9
  self.assistant = Manager.Assistant();
10
10
  self.user = payload.user
11
+ self.context = payload.context
11
12
 
12
- return self;
13
+ return self;
13
14
  };
14
15
 
15
16
  Module.prototype.main = function () {
@@ -17,8 +18,11 @@ Module.prototype.main = function () {
17
18
  const libraries = self.libraries;
18
19
  const assistant = self.assistant;
19
20
  const user = self.user;
21
+ const context = self.context;
20
22
 
21
23
  return new Promise(async function(resolve, reject) {
24
+ assistant.log(`Request: ${user.uid}`, user, context, { environment: 'production' });
25
+
22
26
  // Set up analytics
23
27
  const analytics = self.Manager.Analytics({
24
28
  assistant: assistant,
@@ -34,7 +38,7 @@ Module.prototype.main = function () {
34
38
  await libraries.admin.firestore().doc(`users/${user.uid}`)
35
39
  .delete()
36
40
  .catch((e) => {
37
- assistant.error(`auth-on-delete: Delete user failed`, e, {environment: 'production'});
41
+ assistant.error(`Delete user failed`, e, {environment: 'production'});
38
42
  })
39
43
 
40
44
  // Update user count
@@ -43,11 +47,11 @@ Module.prototype.main = function () {
43
47
  'users.total': libraries.admin.firestore.FieldValue.increment(-1),
44
48
  })
45
49
  .catch((e) => {
46
- assistant.error(`auth-on-delete: Failed to decrement user`, e, {environment: 'production'});
50
+ assistant.error(`Failed to decrement user`, e, {environment: 'production'});
47
51
  })
48
52
 
49
- assistant.log(`auth-on-delete: User deleted ${user.uid}:`, user, {environment: 'production'});
50
-
53
+ assistant.log(`User deleted ${user.uid}:`, user, context, {environment: 'production'});
54
+
51
55
  return resolve(self);
52
56
  });
53
57
  };
@@ -13,35 +13,38 @@ function User(Manager, settings, options) {
13
13
  settings = settings || {};
14
14
  options = options || {};
15
15
 
16
+ options.defaults = typeof options.defaults === 'undefined' ? true : options.defaults;
17
+ options.prune = typeof options.prune === 'undefined' ? false : options.prune;
18
+
16
19
  const now = powertools.timestamp(new Date(), {output: 'string'});
17
20
  const nowUNIX = powertools.timestamp(now, {output: 'unix'});
18
21
  const oldDate = powertools.timestamp(new Date(0), {output: 'string'})
19
22
  const oldDateUNIX = powertools.timestamp(oldDate, {output: 'unix'});
20
23
 
21
- const useDefaults = typeof options.defaults === 'undefined' ? true : options.defaults;
24
+ const defaults = options.defaults;
22
25
 
23
26
  self.properties = {
24
27
  auth: {
25
28
  uid: _.get(settings, 'auth.uid', null),
26
29
  email: _.get(settings, 'auth.email', null),
27
- temporary: _.get(settings, 'auth.temporary', useDefaults ? false : null),
30
+ temporary: _.get(settings, 'auth.temporary', defaults ? false : null),
28
31
  },
29
32
  roles: {
30
- admin: _.get(settings, 'roles.admin', useDefaults ? false : null),
31
- betaTester: _.get(settings, 'roles.betaTester', useDefaults ? false : null),
32
- developer: _.get(settings, 'roles.developer', useDefaults ? false : null),
33
+ admin: _.get(settings, 'roles.admin', defaults ? false : null),
34
+ betaTester: _.get(settings, 'roles.betaTester', defaults ? false : null),
35
+ developer: _.get(settings, 'roles.developer', defaults ? false : null),
33
36
  },
34
37
  plan: {
35
- id: _.get(settings, 'plan.id', useDefaults ? 'basic' : null), // intro | basic | advanced | premium
38
+ id: _.get(settings, 'plan.id', defaults ? 'basic' : null), // intro | basic | advanced | premium
36
39
  expires: {
37
- timestamp: _.get(settings, 'plan.expires.timestamp', useDefaults ? oldDate : null),
38
- timestampUNIX: _.get(settings, 'plan.expires.timestampUNIX', useDefaults ? oldDateUNIX : null),
40
+ timestamp: _.get(settings, 'plan.expires.timestamp', defaults ? oldDate : null),
41
+ timestampUNIX: _.get(settings, 'plan.expires.timestampUNIX', defaults ? oldDateUNIX : null),
39
42
  },
40
43
  trial: {
41
- activated: _.get(settings, 'plan.trial.activated', useDefaults ? false : null),
44
+ activated: _.get(settings, 'plan.trial.activated', defaults ? false : null),
42
45
  expires: {
43
- timestamp: _.get(settings, 'plan.trial.expires.timestamp', useDefaults ? oldDate : null),
44
- timestampUNIX: _.get(settings, 'plan.trial.expires.timestampUNIX', useDefaults ? oldDateUNIX : null),
46
+ timestamp: _.get(settings, 'plan.trial.expires.timestamp', defaults ? oldDate : null),
47
+ timestampUNIX: _.get(settings, 'plan.trial.expires.timestampUNIX', defaults ? oldDateUNIX : null),
45
48
  },
46
49
  },
47
50
  limits: {
@@ -53,71 +56,71 @@ function User(Manager, settings, options) {
53
56
  resourceId: _.get(settings, 'plan.payment.resourceId', null), // x-xxxxxx
54
57
  frequency: _.get(settings, 'plan.payment.frequency', null), // monthly || annually
55
58
  startDate: {
56
- timestamp: _.get(settings, 'plan.payment.startDate.timestamp', useDefaults ? now : null), // x-xxxxxx
57
- timestampUNIX: _.get(settings, 'plan.payment.startDate.timestampUNIX', useDefaults ? nowUNIX : null), // x-xxxxxx
59
+ timestamp: _.get(settings, 'plan.payment.startDate.timestamp', defaults ? now : null), // x-xxxxxx
60
+ timestampUNIX: _.get(settings, 'plan.payment.startDate.timestampUNIX', defaults ? nowUNIX : null), // x-xxxxxx
58
61
  },
59
- active: _.get(settings, 'plan.payment.active', useDefaults ? false : null), // true | false
62
+ active: _.get(settings, 'plan.payment.active', defaults ? false : null), // true | false
60
63
  updatedBy: {
61
64
  event: {
62
65
  name: _.get(settings, 'plan.payment.updatedBy.event.name', null), // x-xxxxxx
63
66
  id: _.get(settings, 'plan.payment.updatedBy.event.id', null), // x-xxxxxx
64
67
  },
65
68
  date: {
66
- timestamp: _.get(settings, 'plan.payment.updatedBy.date.timestamp', useDefaults ? now : null), // x-xxxxxx
67
- timestampUNIX: _.get(settings, 'plan.payment.updatedBy.date.timestampUNIX', useDefaults ? nowUNIX : null), // x-xxxxxx
69
+ timestamp: _.get(settings, 'plan.payment.updatedBy.date.timestamp', defaults ? now : null), // x-xxxxxx
70
+ timestampUNIX: _.get(settings, 'plan.payment.updatedBy.date.timestampUNIX', defaults ? nowUNIX : null), // x-xxxxxx
68
71
  },
69
72
  },
70
73
  }
71
74
  },
72
75
  affiliate: {
73
- code: _.get(settings, 'affiliate.code', useDefaults ? shortid.generate() : null),
76
+ code: _.get(settings, 'affiliate.code', defaults ? shortid.generate() : null),
74
77
  referrals: [],
75
78
  referrer: _.get(settings, 'affiliate.referrer', null),
76
79
  },
77
80
  activity: {
78
81
  lastActivity: {
79
- timestamp: _.get(settings, 'activity.lastActivity.timestamp', useDefaults ? now : null),
80
- timestampUNIX: _.get(settings, 'activity.lastActivity.timestampUNIX', useDefaults ? nowUNIX : null),
82
+ timestamp: _.get(settings, 'activity.lastActivity.timestamp', defaults ? now : null),
83
+ timestampUNIX: _.get(settings, 'activity.lastActivity.timestampUNIX', defaults ? nowUNIX : null),
81
84
  },
82
85
  created: {
83
- timestamp: _.get(settings, 'activity.created.timestamp', useDefaults ? now : null),
84
- timestampUNIX: _.get(settings, 'activity.created.timestampUNIX', useDefaults ? nowUNIX : null),
86
+ timestamp: _.get(settings, 'activity.created.timestamp', defaults ? now : null),
87
+ timestampUNIX: _.get(settings, 'activity.created.timestampUNIX', defaults ? nowUNIX : null),
85
88
  },
86
89
  geolocation: {
87
- ip: _.get(settings, 'activity.geolocation.ip', useDefaults ? '' : null),
88
- continent: _.get(settings, 'activity.geolocation.continent', useDefaults ? '' : null),
89
- country: _.get(settings, 'activity.geolocation.country', useDefaults ? '' : null),
90
- city: _.get(settings, 'activity.geolocation.city', useDefaults ? '' : null),
91
- latitude: _.get(settings, 'activity.geolocation.latitude', useDefaults ? 0 : null),
92
- longitude: _.get(settings, 'activity.geolocation.longitude', useDefaults ? 0 : null),
93
- userAgent: _.get(settings, 'activity.geolocation.userAgent', useDefaults ? '' : null),
94
- language: _.get(settings, 'activity.geolocation.language', useDefaults ? '' : null),
95
- platform: _.get(settings, 'activity.geolocation.platform', useDefaults ? '' : null),
90
+ ip: _.get(settings, 'activity.geolocation.ip', defaults ? '' : null),
91
+ continent: _.get(settings, 'activity.geolocation.continent', defaults ? '' : null),
92
+ country: _.get(settings, 'activity.geolocation.country', defaults ? '' : null),
93
+ city: _.get(settings, 'activity.geolocation.city', defaults ? '' : null),
94
+ latitude: _.get(settings, 'activity.geolocation.latitude', defaults ? 0 : null),
95
+ longitude: _.get(settings, 'activity.geolocation.longitude', defaults ? 0 : null),
96
+ userAgent: _.get(settings, 'activity.geolocation.userAgent', defaults ? '' : null),
97
+ language: _.get(settings, 'activity.geolocation.language', defaults ? '' : null),
98
+ platform: _.get(settings, 'activity.geolocation.platform', defaults ? '' : null),
96
99
  },
97
100
  },
98
101
  api: {
99
- clientId: _.get(settings, 'api.clientId', useDefaults ? `${uuid4()}` : null),
100
- privateKey: _.get(settings, 'api.privateKey', useDefaults ? `${uidgen.generateSync()}` : null),
102
+ clientId: _.get(settings, 'api.clientId', defaults ? `${uuid4()}` : null),
103
+ privateKey: _.get(settings, 'api.privateKey', defaults ? `${uidgen.generateSync()}` : null),
101
104
  },
102
105
  personal: {
103
106
  birthday: {
104
- timestamp: _.get(settings, 'personal.birthday.timestamp', useDefaults ? oldDate : null),
105
- timestampUNIX: _.get(settings, 'personal.birthday.timestampUNIX', useDefaults ? oldDateUNIX : null),
107
+ timestamp: _.get(settings, 'personal.birthday.timestamp', defaults ? oldDate : null),
108
+ timestampUNIX: _.get(settings, 'personal.birthday.timestampUNIX', defaults ? oldDateUNIX : null),
106
109
  },
107
- gender: _.get(settings, 'personal.gender', useDefaults ? '' : null),
110
+ gender: _.get(settings, 'personal.gender', defaults ? '' : null),
108
111
  location: {
109
- city: _.get(settings, 'personal.location.city', useDefaults ? '' : null),
110
- country: _.get(settings, 'personal.location.country', useDefaults ? '' : null),
112
+ city: _.get(settings, 'personal.location.city', defaults ? '' : null),
113
+ country: _.get(settings, 'personal.location.country', defaults ? '' : null),
111
114
  },
112
115
  name: {
113
- first: _.get(settings, 'personal.name.first', useDefaults ? '' : null),
114
- last: _.get(settings, 'personal.name.last', useDefaults ? '' : null),
116
+ first: _.get(settings, 'personal.name.first', defaults ? '' : null),
117
+ last: _.get(settings, 'personal.name.last', defaults ? '' : null),
115
118
  },
116
119
  telephone: {
117
- countryCode: _.get(settings, 'personal.telephone.countryCode', useDefaults ? 0 : null),
118
- national: _.get(settings, 'personal.telephone.national', useDefaults ? 0 : null),
119
- },
120
- },
120
+ countryCode: _.get(settings, 'personal.telephone.countryCode', defaults ? 0 : null),
121
+ national: _.get(settings, 'personal.telephone.national', defaults ? 0 : null),
122
+ },
123
+ },
121
124
  }
122
125
 
123
126
  if (options.prune) {
@@ -38,6 +38,7 @@ Manager.prototype.init = function (exporter, options) {
38
38
  options.log = typeof options.log === 'undefined' ? false : options.log;
39
39
  options.setupFunctions = typeof options.setupFunctions === 'undefined' ? true : options.setupFunctions;
40
40
  options.setupFunctionsLegacy = typeof options.setupFunctionsLegacy === 'undefined' ? true : options.setupFunctionsLegacy;
41
+ options.setupFunctionsIdentity = typeof options.setupFunctionsIdentity === 'undefined' ? true : options.setupFunctionsIdentity;
41
42
  options.initializeLocalStorage = typeof options.initializeLocalStorage === 'undefined' ? false : options.initializeLocalStorage;
42
43
  options.resourceZone = typeof options.resourceZone === 'undefined' ? 'us-central1' : options.resourceZone;
43
44
  options.sentry = typeof options.sentry === 'undefined' ? true : options.sentry;
@@ -371,20 +372,38 @@ Manager.prototype.init = function (exporter, options) {
371
372
  }
372
373
 
373
374
  // Events
375
+ if (options.setupFunctionsIdentity) {
376
+ exporter.bm_authBeforeCreate =
377
+ self.libraries.functions
378
+ .runWith({memory: '256MB', timeoutSeconds: 60})
379
+ .auth.user()
380
+ .beforeCreate(async (user, context) => {
381
+ return self._process((new (require(`${core}/events/auth/before-create.js`))()).init(self, { user: user, context: context}))
382
+ });
383
+
384
+ exporter.bm_authBeforeSignIn =
385
+ self.libraries.functions
386
+ .runWith({memory: '256MB', timeoutSeconds: 60})
387
+ .auth.user()
388
+ .beforeSignIn(async (user, context) => {
389
+ return self._process((new (require(`${core}/events/auth/before-signin.js`))()).init(self, { user: user, context: context}))
390
+ });
391
+ }
392
+
374
393
  exporter.bm_authOnCreate =
375
394
  self.libraries.functions
376
395
  .runWith({memory: '256MB', timeoutSeconds: 60})
377
396
  .auth.user()
378
- .onCreate(async (user) => {
379
- return self._process((new (require(`${core}/events/auth/on-create.js`))()).init(self, { user: user, }))
397
+ .onCreate(async (user, context) => {
398
+ return self._process((new (require(`${core}/events/auth/on-create.js`))()).init(self, { user: user, context: context}))
380
399
  });
381
400
 
382
401
  exporter.bm_authOnDelete =
383
402
  self.libraries.functions
384
403
  .runWith({memory: '256MB', timeoutSeconds: 60})
385
404
  .auth.user()
386
- .onDelete(async (user) => {
387
- return self._process((new (require(`${core}/events/auth/on-delete.js`))()).init(self, { user: user, }))
405
+ .onDelete(async (user, context) => {
406
+ return self._process((new (require(`${core}/events/auth/on-delete.js`))()).init(self, { user: user, context: context}))
388
407
  });
389
408
 
390
409
  exporter.bm_subOnWrite =