backend-manager 2.3.18 → 2.4.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Quick tools for developing Firebase functions",
|
|
5
5
|
"main": "src/manager/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://itwcreativeworks.com",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@firebase/rules-unit-testing": "^2.0.
|
|
30
|
+
"@firebase/rules-unit-testing": "^2.0.4",
|
|
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": "^0.0.
|
|
34
|
+
"backend-assistant": "^0.0.71",
|
|
35
35
|
"busboy": "^1.6.0",
|
|
36
36
|
"chalk": "^4.1.2",
|
|
37
37
|
"cors": "^2.8.5",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"hcaptcha": "^0.1.1",
|
|
43
43
|
"inquirer": "^8.2.4",
|
|
44
44
|
"json5": "^2.2.1",
|
|
45
|
+
"jwt-decode": "^3.1.2",
|
|
45
46
|
"lodash": "^4.17.21",
|
|
46
47
|
"lowdb": "^1.0.0",
|
|
47
48
|
"mailchimp-api-v3": "^1.15.0",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const decode = require('jwt-decode')
|
|
2
|
+
|
|
3
|
+
function OAuth2() {
|
|
4
|
+
const self = this;
|
|
5
|
+
self.service = 'google';
|
|
6
|
+
self.name = 'Google';
|
|
7
|
+
self.urls = {
|
|
8
|
+
authorize: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
9
|
+
tokenize: 'https://oauth2.googleapis.com/token',
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
OAuth2.prototype.buildUrl = function (state, url) {
|
|
14
|
+
const self = this;
|
|
15
|
+
|
|
16
|
+
return new Promise(function(resolve, reject) {
|
|
17
|
+
if (state === 'authorize') {
|
|
18
|
+
// do something with url
|
|
19
|
+
return resolve()
|
|
20
|
+
} else {
|
|
21
|
+
return resolve()
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
OAuth2.prototype.verifyIdentity = function (tokenizeResult) {
|
|
27
|
+
const self = this;
|
|
28
|
+
const Manager = self.Manager;
|
|
29
|
+
|
|
30
|
+
return new Promise(function(resolve, reject) {
|
|
31
|
+
const decoded = decode(tokenizeResult.id_token);
|
|
32
|
+
|
|
33
|
+
// console.log('---decoded', decoded);
|
|
34
|
+
|
|
35
|
+
// Check if exists
|
|
36
|
+
Manager.libraries.admin.firestore().collection(`users`)
|
|
37
|
+
.where(`oauth2.${self.service}.identity.email`, '==', decoded.email)
|
|
38
|
+
.get()
|
|
39
|
+
.then(async (snap) => {
|
|
40
|
+
if (snap.size === 0) {
|
|
41
|
+
return resolve(decoded);
|
|
42
|
+
} else {
|
|
43
|
+
return reject(new Error(`This ${self.name} account is already connected to a ${Manager.config.brand.name} account`));
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
.catch((e) => {
|
|
47
|
+
return reject(e);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
module.exports = OAuth2;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
2
|
+
const fetch = require('wonderful-fetch');
|
|
3
|
+
|
|
4
|
+
function Module() {
|
|
5
|
+
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
authorize: redirect or send back the URL for authorization, which will go to UJ page that sends the data back to bm_api
|
|
10
|
+
- if no client_id is provided, fetch from ITW/APP
|
|
11
|
+
tokenize: save the credentials in firestore and redirect or respond with URL to the desired end page
|
|
12
|
+
deauthorize: delete from firestore
|
|
13
|
+
refresh: call refresh on token
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
Module.prototype.main = function () {
|
|
17
|
+
const self = this;
|
|
18
|
+
const Manager = self.Manager;
|
|
19
|
+
const Api = self.Api;
|
|
20
|
+
const assistant = self.assistant;
|
|
21
|
+
const payload = self.payload;
|
|
22
|
+
|
|
23
|
+
return new Promise(async function(resolve, reject) {
|
|
24
|
+
self.Api.resolveUser({adminRequired: true})
|
|
25
|
+
.then(async (user) => {
|
|
26
|
+
|
|
27
|
+
self.ultimateJekyllOAuth2Url = assistant.meta.environment === 'development'
|
|
28
|
+
? `http://localhost:4000/oauth2`
|
|
29
|
+
: `${Manager.config.brand.url}/oauth2`
|
|
30
|
+
self.oauth2 = null;
|
|
31
|
+
self.omittedPayloadFields = ['redirect', 'referrer', 'service', 'state'];
|
|
32
|
+
|
|
33
|
+
// self.ultimateJekyllOAuth2Url = `${Manager.config.brand.url}/oauth2`;
|
|
34
|
+
|
|
35
|
+
// Options
|
|
36
|
+
// payload.data.payload.uid = payload.data.payload.uid;
|
|
37
|
+
payload.data.payload.redirect = typeof payload.data.payload.redirect === 'undefined'
|
|
38
|
+
? true
|
|
39
|
+
: payload.data.payload.redirect
|
|
40
|
+
|
|
41
|
+
payload.data.payload.referrer = typeof payload.data.payload.referrer === 'undefined'
|
|
42
|
+
? (assistant.meta.environment === 'development' ? `http://localhost:4000/oauth2` : `${Manager.config.brand.url}/oauth2`)
|
|
43
|
+
: payload.data.payload.referrer
|
|
44
|
+
|
|
45
|
+
payload.data.payload.service = payload.data.payload.service || '';
|
|
46
|
+
payload.data.payload.state = payload.data.payload.state || 'authorize'; // authorize, tokenize, deauthorize, refresh, get
|
|
47
|
+
|
|
48
|
+
// payload.data.payload.parameters = payload.data.payload.parameters || {}
|
|
49
|
+
|
|
50
|
+
// payload.data.payload.client_id = payload.data.payload.client_id;
|
|
51
|
+
// payload.data.payload.scope = payload.data.payload.scope;
|
|
52
|
+
// payload.data.payload.redirect_uri = payload.data.payload.redirect_uri;
|
|
53
|
+
|
|
54
|
+
let newUrl;
|
|
55
|
+
const state = {
|
|
56
|
+
code: 'success',
|
|
57
|
+
service: payload.data.payload.service,
|
|
58
|
+
authenticationToken: payload.data.authenticationToken,
|
|
59
|
+
serverUrl: `${Manager.project.functionsUrl}/bm_api`,
|
|
60
|
+
referrer: payload.data.payload.referrer,
|
|
61
|
+
redirectUrl: payload.data.payload.redirect_uri,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
assistant.log('OAuth2 payload', payload.data.payload);
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
self.oauth2 = new (require(`./oauth2/${payload.data.payload.service}.js`))();
|
|
68
|
+
self.oauth2.parent = self;
|
|
69
|
+
self.oauth2.Manager = self.Manager;
|
|
70
|
+
|
|
71
|
+
newUrl = self.oauth2.urls[payload.data.payload.state]
|
|
72
|
+
|
|
73
|
+
// Set parameters
|
|
74
|
+
if (newUrl) {
|
|
75
|
+
newUrl = new URL(newUrl)
|
|
76
|
+
|
|
77
|
+
if (payload.data.payload.state === 'authorize') {
|
|
78
|
+
newUrl.searchParams.set('state', JSON.stringify(state));
|
|
79
|
+
newUrl.searchParams.set('client_id', _.get(Manager.config, `oauth2.${payload.data.payload.service}.client_id`));
|
|
80
|
+
newUrl.searchParams.set('scope', payload.data.payload.scope);
|
|
81
|
+
newUrl.searchParams.set('redirect_uri', self.ultimateJekyllOAuth2Url);
|
|
82
|
+
|
|
83
|
+
newUrl.searchParams.set('access_type', typeof payload.data.payload.access_type === 'undefined' ? 'offline' : payload.data.payload.access_type)
|
|
84
|
+
newUrl.searchParams.set('include_granted_scopes', typeof payload.data.payload.include_granted_scopes === 'undefined' ? 'true' : payload.data.payload.include_granted_scopes)
|
|
85
|
+
newUrl.searchParams.set('response_type', typeof payload.data.payload.response_type === 'undefined' ? 'code' : payload.data.payload.response_type)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await self.oauth2.buildUrl(payload.data.payload.state, newUrl)
|
|
89
|
+
.then(url => {
|
|
90
|
+
if (url) {
|
|
91
|
+
newUrl = url;
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
.catch(e => { throw e; });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
} catch (e) {
|
|
98
|
+
return reject(e);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Process by state
|
|
102
|
+
if (payload.data.payload.state === 'authorize') {
|
|
103
|
+
self.processState_authorize(newUrl)
|
|
104
|
+
.then(r => {resolve(r)})
|
|
105
|
+
.catch(e => {reject(e)})
|
|
106
|
+
} else if (payload.data.payload.state === 'tokenize') {
|
|
107
|
+
self.processState_tokenize(newUrl)
|
|
108
|
+
.then(r => {resolve(r)})
|
|
109
|
+
.catch(e => {reject(e)})
|
|
110
|
+
} else if (payload.data.payload.state === 'deauthorize') {
|
|
111
|
+
self.processState_deauthorize(newUrl)
|
|
112
|
+
.then(r => {resolve(r)})
|
|
113
|
+
.catch(e => {reject(e)})
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
.catch(e => {
|
|
117
|
+
return reject(e);
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
Module.prototype.processState_authorize = function (newUrl) {
|
|
124
|
+
const self = this;
|
|
125
|
+
const Manager = self.Manager;
|
|
126
|
+
const Api = self.Api;
|
|
127
|
+
const assistant = self.assistant;
|
|
128
|
+
const payload = self.payload;
|
|
129
|
+
|
|
130
|
+
return new Promise(async function(resolve, reject) {
|
|
131
|
+
const finalUrl = newUrl.toString();
|
|
132
|
+
|
|
133
|
+
return resolve({
|
|
134
|
+
data: {
|
|
135
|
+
authorizationUrl: finalUrl,
|
|
136
|
+
},
|
|
137
|
+
redirect: payload.data.payload.redirect ? finalUrl : null
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
Module.prototype.processState_tokenize = function (newUrl) {
|
|
143
|
+
const self = this;
|
|
144
|
+
const Manager = self.Manager;
|
|
145
|
+
const Api = self.Api;
|
|
146
|
+
const assistant = self.assistant;
|
|
147
|
+
const payload = self.payload;
|
|
148
|
+
|
|
149
|
+
return new Promise(async function(resolve, reject) {
|
|
150
|
+
const finalUrl = newUrl.toString();
|
|
151
|
+
|
|
152
|
+
const body = {
|
|
153
|
+
client_id: _.get(Manager.config, `oauth2.${payload.data.payload.service}.client_id`),
|
|
154
|
+
client_secret: _.get(Manager.config, `oauth2.${payload.data.payload.service}.client_secret`),
|
|
155
|
+
grant_type: 'authorization_code',
|
|
156
|
+
redirect_uri: self.ultimateJekyllOAuth2Url,
|
|
157
|
+
code: payload.data.payload.code,
|
|
158
|
+
// scope: '',
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// console.log('----body', body);
|
|
162
|
+
|
|
163
|
+
const tokenizeResponse = await fetch(finalUrl, {
|
|
164
|
+
method: 'POST',
|
|
165
|
+
timeout: 60000,
|
|
166
|
+
response: 'json',
|
|
167
|
+
tries: 2,
|
|
168
|
+
log: true,
|
|
169
|
+
body: new URLSearchParams(body),
|
|
170
|
+
cacheBreaker: false,
|
|
171
|
+
headers: {
|
|
172
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
173
|
+
},
|
|
174
|
+
})
|
|
175
|
+
.then(json => json)
|
|
176
|
+
.catch(e => e)
|
|
177
|
+
|
|
178
|
+
// console.log('---tokenizeResponse', tokenizeResponse);
|
|
179
|
+
|
|
180
|
+
if (tokenizeResponse instanceof Error) {
|
|
181
|
+
return reject(tokenizeResponse);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Determine identity
|
|
185
|
+
const verifiedIdentity = await self.oauth2.verifyIdentity(tokenizeResponse)
|
|
186
|
+
.then(identity => identity)
|
|
187
|
+
.catch(e => e);
|
|
188
|
+
|
|
189
|
+
// console.log('---verifiedIdentity', verifiedIdentity);
|
|
190
|
+
|
|
191
|
+
if (verifiedIdentity instanceof Error) {
|
|
192
|
+
return reject(verifiedIdentity);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const storeResponse = await self.libraries.admin.firestore().doc(`users/${payload.user.auth.uid}`)
|
|
196
|
+
.set({
|
|
197
|
+
oauth2: {
|
|
198
|
+
[payload.data.payload.service]: {
|
|
199
|
+
code: _.omit(
|
|
200
|
+
_.merge({}, payload.data.payload),
|
|
201
|
+
self.omittedPayloadFields,
|
|
202
|
+
),
|
|
203
|
+
token: tokenizeResponse,
|
|
204
|
+
identity: verifiedIdentity,
|
|
205
|
+
updated: {
|
|
206
|
+
timestamp: assistant.meta.startTime.timestamp,
|
|
207
|
+
timestampUNIX: assistant.meta.startTime.timestampUNIX,
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}, { merge: true })
|
|
212
|
+
.then(r => r)
|
|
213
|
+
.catch(e => e)
|
|
214
|
+
|
|
215
|
+
// console.log('---storeResponse', storeResponse);
|
|
216
|
+
|
|
217
|
+
if (storeResponse instanceof Error) {
|
|
218
|
+
return reject(storeResponse);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return resolve({
|
|
222
|
+
data: {success: true}
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
Module.prototype.processState_deauthorize = function () {
|
|
229
|
+
const self = this;
|
|
230
|
+
const Manager = self.Manager;
|
|
231
|
+
const Api = self.Api;
|
|
232
|
+
const assistant = self.assistant;
|
|
233
|
+
const payload = self.payload;
|
|
234
|
+
|
|
235
|
+
return new Promise(async function(resolve, reject) {
|
|
236
|
+
self.libraries.admin.firestore().doc(`users/${payload.user.auth.uid}`)
|
|
237
|
+
.set({
|
|
238
|
+
oauth2: {
|
|
239
|
+
[payload.data.payload.service]: {},
|
|
240
|
+
updated: {
|
|
241
|
+
timestamp: assistant.meta.startTime.timestamp,
|
|
242
|
+
timestampUNIX: assistant.meta.startTime.timestampUNIX,
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}, { merge: true })
|
|
246
|
+
.then(function(data) {
|
|
247
|
+
return resolve({
|
|
248
|
+
data: {success: true},
|
|
249
|
+
});
|
|
250
|
+
})
|
|
251
|
+
.catch(function(e) {
|
|
252
|
+
return reject(e);
|
|
253
|
+
})
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
Module.prototype.processState_template = function (newUrl) {
|
|
261
|
+
const self = this;
|
|
262
|
+
const Manager = self.Manager;
|
|
263
|
+
const Api = self.Api;
|
|
264
|
+
const assistant = self.assistant;
|
|
265
|
+
const payload = self.payload;
|
|
266
|
+
|
|
267
|
+
return new Promise(async function(resolve, reject) {
|
|
268
|
+
const finalUrl = newUrl.toString();
|
|
269
|
+
|
|
270
|
+
return resolve({
|
|
271
|
+
data: {
|
|
272
|
+
authorizationUrl: finalUrl,
|
|
273
|
+
},
|
|
274
|
+
redirect: payload.data.payload.redirect ? finalUrl : null
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
module.exports = Module;
|
|
@@ -33,6 +33,7 @@ Module.prototype.init = function (Manager, data) {
|
|
|
33
33
|
|
|
34
34
|
Module.prototype.main = function() {
|
|
35
35
|
const self = this;
|
|
36
|
+
const Manager = self.Manager;
|
|
36
37
|
const libraries = self.libraries;
|
|
37
38
|
const assistant = self.assistant;
|
|
38
39
|
const req = self.req;
|
|
@@ -45,6 +46,7 @@ Module.prototype.main = function() {
|
|
|
45
46
|
const resolved = self.resolveCommand(self.payload.data.command);
|
|
46
47
|
|
|
47
48
|
self.assistant.log(`Executing: ${resolved.command}`, self.payload, JSON.stringify(self.payload), {environment: 'production'})
|
|
49
|
+
self.assistant.log(`Resolved URL: ${Manager.project.functionsUrl}?command=${encodeURIComponent(resolved.command)}&payload=${encodeURIComponent(JSON.stringify(self.assistant.request.data.payload))}`, {environment: 'development'})
|
|
48
50
|
|
|
49
51
|
if (!resolved.exists) {
|
|
50
52
|
self.payload.response.status = 400;
|
|
@@ -61,6 +63,7 @@ Module.prototype.main = function() {
|
|
|
61
63
|
// console.log('---self.payload.response.data', self.payload.response.data);
|
|
62
64
|
self.payload.response.status = result.status || self.payload.response.status || 200;
|
|
63
65
|
self.payload.response.data = result.data || self.payload.response.data || {};
|
|
66
|
+
self.payload.response.redirect = result.redirect || self.payload.response.redirect || null;
|
|
64
67
|
})
|
|
65
68
|
.catch(e => {
|
|
66
69
|
self.payload.response.status = e.code || 500;
|
|
@@ -77,13 +80,22 @@ Module.prototype.main = function() {
|
|
|
77
80
|
})
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
self.payload.response.status = _fixStatus(self.payload.response.status);
|
|
84
|
+
|
|
85
|
+
res.status(self.payload.response.status)
|
|
86
|
+
|
|
87
|
+
if (self.payload.response.status >= 200 && self.payload.response.status < 300) {
|
|
88
|
+
self.assistant.log(`Finished ${resolved.command} (status=${self.payload.response.status})`, self.payload, JSON.stringify(self.payload), {environment: 'production'})
|
|
89
|
+
|
|
90
|
+
if (self.payload.response.redirect) {
|
|
91
|
+
return res.redirect(self.payload.response.redirect);
|
|
92
|
+
} else {
|
|
93
|
+
return res.json(self.payload.response.data);
|
|
94
|
+
}
|
|
83
95
|
} else {
|
|
84
|
-
console.error(`Error executing ${resolved.command} @ ${resolved.path}
|
|
85
|
-
// return res.
|
|
86
|
-
return res.
|
|
96
|
+
console.error(`Error executing ${resolved.command} @ ${resolved.path} (status=${self.payload.response.status}):`, self.payload.response.error)
|
|
97
|
+
// return res.send(self.payload.response.error.message);
|
|
98
|
+
return res.send(`${self.payload.response.error}`);
|
|
87
99
|
}
|
|
88
100
|
});
|
|
89
101
|
}
|
|
@@ -252,4 +264,16 @@ Module.prototype.resolveUser = function (options) {
|
|
|
252
264
|
});
|
|
253
265
|
};
|
|
254
266
|
|
|
267
|
+
function _fixStatus(status) {
|
|
268
|
+
if (typeof status === 'number') {
|
|
269
|
+
return status;
|
|
270
|
+
} else {
|
|
271
|
+
if (status === 'ok') {
|
|
272
|
+
return 200
|
|
273
|
+
} else {
|
|
274
|
+
return 500
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
255
279
|
module.exports = Module;
|
package/src/manager/index.js
CHANGED
|
@@ -19,6 +19,8 @@ function Manager(exporter, options) {
|
|
|
19
19
|
storage: {},
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
// self.isDevelopment = false;
|
|
23
|
+
|
|
22
24
|
return self;
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -32,8 +34,11 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
32
34
|
// Set options defaults
|
|
33
35
|
options = options || {};
|
|
34
36
|
options.initialize = typeof options.initialize === 'undefined' ? true : options.initialize;
|
|
37
|
+
options.log = typeof options.log === 'undefined' ? false : options.log;
|
|
35
38
|
options.setupFunctions = typeof options.setupFunctions === 'undefined' ? true : options.setupFunctions;
|
|
39
|
+
options.setupFunctionsLegacy = typeof options.setupFunctionsLegacy === 'undefined' ? true : options.setupFunctionsLegacy;
|
|
36
40
|
options.initializeLocalStorage = typeof options.initializeLocalStorage === 'undefined' ? false : options.initializeLocalStorage;
|
|
41
|
+
options.resourceZone = typeof options.resourceZone === 'undefined' ? 'us-central1' : options.resourceZone;
|
|
37
42
|
options.sentry = typeof options.sentry === 'undefined' ? true : options.sentry;
|
|
38
43
|
options.reportErrorsInDev = typeof options.reportErrorsInDev === 'undefined' ? false : options.reportErrorsInDev;
|
|
39
44
|
options.firebaseConfig = options.firebaseConfig;
|
|
@@ -68,7 +73,9 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
68
73
|
|
|
69
74
|
// Set properties
|
|
70
75
|
self.options = options;
|
|
71
|
-
self.project = options.firebaseConfig || JSON.parse(process.env.FIREBASE_CONFIG);
|
|
76
|
+
self.project = options.firebaseConfig || JSON.parse(process.env.FIREBASE_CONFIG || '{}');
|
|
77
|
+
self.project.resourceZone = options.resourceZone;
|
|
78
|
+
|
|
72
79
|
self.cwd = process.cwd();
|
|
73
80
|
self.package = resolveProjectPackage();
|
|
74
81
|
self.config = merge(
|
|
@@ -76,15 +83,26 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
76
83
|
self.libraries.functions.config()
|
|
77
84
|
);
|
|
78
85
|
|
|
86
|
+
// Init assistant
|
|
79
87
|
self.assistant = self.Assistant().init(undefined, options.assistant);
|
|
80
88
|
|
|
81
89
|
process.env.ENVIRONMENT = !process.env.ENVIRONMENT ? self.assistant.meta.environment : process.env.ENVIRONMENT;
|
|
82
90
|
|
|
91
|
+
// set more properties (need to wait for assistant to determine if DEV)
|
|
92
|
+
self.project.functionsUrl = self.assistant.meta.environment === 'development'
|
|
93
|
+
? `http://localhost:5001/${self.project.projectId}/${self.project.resourceZone}`
|
|
94
|
+
: `https://${self.project.resourceZone}-${self.project.projectId}.cloudfunctions.net`;
|
|
95
|
+
|
|
96
|
+
|
|
83
97
|
// Use the working Firebase logger that they disabled for whatever reason
|
|
84
98
|
if (self.assistant.meta.environment !== 'development' && options.useFirebaseLogger) {
|
|
85
99
|
require('firebase-functions/lib/logger/compat');
|
|
86
100
|
}
|
|
87
101
|
|
|
102
|
+
if (options.log) {
|
|
103
|
+
self.assistant.log('process.env', process.env, {environment: 'production'})
|
|
104
|
+
}
|
|
105
|
+
|
|
88
106
|
// Setup sentry
|
|
89
107
|
if (self.options.sentry) {
|
|
90
108
|
const sentryRelease = `${get(self.config, 'app.id') || self.project.projectId}@${self.package.version}`;
|
|
@@ -112,14 +130,19 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
112
130
|
// Setup options features
|
|
113
131
|
if (self.options.initialize) {
|
|
114
132
|
// console.log('Initializing:', self.project);
|
|
133
|
+
// console.log('----process.env.GOOGLE_APPLICATION_CREDENTIALS', process.env.GOOGLE_APPLICATION_CREDENTIALS);
|
|
115
134
|
try {
|
|
116
|
-
// console.log('
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
// console.log('---process.env.GOOGLE_APPLICATION_CREDENTIALS', process.env.GOOGLE_APPLICATION_CREDENTIALS);
|
|
136
|
+
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
137
|
+
self.libraries.initializedAdmin = self.libraries.admin.initializeApp();
|
|
138
|
+
} else {
|
|
139
|
+
self.libraries.initializedAdmin = self.libraries.admin.initializeApp({
|
|
140
|
+
credential: self.libraries.admin.credential.cert(
|
|
141
|
+
require(path.resolve(self.cwd, options.serviceAccountPath))
|
|
142
|
+
),
|
|
143
|
+
databaseURL: self.project.databaseURL,
|
|
144
|
+
}, options.uniqueAppName);
|
|
145
|
+
}
|
|
123
146
|
} catch (e) {
|
|
124
147
|
console.error('Failed to call .initializeApp()', e);
|
|
125
148
|
}
|
|
@@ -142,127 +165,174 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
142
165
|
});
|
|
143
166
|
});
|
|
144
167
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
if (options.setupFunctionsLegacy) {
|
|
169
|
+
exporter.bm_signUpHandler =
|
|
170
|
+
self.libraries.functions
|
|
171
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
172
|
+
.https.onRequest(async (req, res) => {
|
|
173
|
+
const Module = require(`${core}/actions/sign-up-handler.js`);
|
|
174
|
+
Module.init(self, { req: req, res: res, });
|
|
151
175
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
176
|
+
return self._preProcess(Module)
|
|
177
|
+
.then(r => Module.main())
|
|
178
|
+
.catch(e => {
|
|
179
|
+
self.assistant.error(e, {environment: 'production'});
|
|
180
|
+
return res.status(500).send(e.message);
|
|
181
|
+
});
|
|
157
182
|
});
|
|
158
|
-
});
|
|
159
183
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
184
|
+
// Admin
|
|
185
|
+
exporter.bm_createPost =
|
|
186
|
+
self.libraries.functions
|
|
187
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
188
|
+
.https.onRequest(async (req, res) => {
|
|
189
|
+
const Module = require(`${core}/admin/create-post.js`);
|
|
190
|
+
Module.init(self, { req: req, res: res, });
|
|
167
191
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
192
|
+
return self._preProcess(Module)
|
|
193
|
+
.then(r => Module.main())
|
|
194
|
+
.catch(e => {
|
|
195
|
+
self.assistant.error(e, {environment: 'production'});
|
|
196
|
+
return res.status(500).send(e.message);
|
|
197
|
+
});
|
|
173
198
|
});
|
|
174
|
-
});
|
|
175
199
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
200
|
+
exporter.bm_firestoreWrite =
|
|
201
|
+
self.libraries.functions
|
|
202
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
203
|
+
.https.onRequest(async (req, res) => {
|
|
204
|
+
const Module = require(`${core}/admin/firestore-write.js`);
|
|
205
|
+
Module.init(self, { req: req, res: res, });
|
|
182
206
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
207
|
+
return self._preProcess(Module)
|
|
208
|
+
.then(r => Module.main())
|
|
209
|
+
.catch(e => {
|
|
210
|
+
self.assistant.error(e, {environment: 'production'});
|
|
211
|
+
return res.status(500).send(e.message);
|
|
212
|
+
});
|
|
188
213
|
});
|
|
189
|
-
});
|
|
190
214
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
215
|
+
exporter.bm_getStats =
|
|
216
|
+
self.libraries.functions
|
|
217
|
+
.runWith({memory: '256MB', timeoutSeconds: 420})
|
|
218
|
+
.https.onRequest(async (req, res) => {
|
|
219
|
+
const Module = require(`${core}/admin/get-stats.js`);
|
|
220
|
+
Module.init(self, { req: req, res: res, });
|
|
197
221
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
222
|
+
return self._preProcess(Module)
|
|
223
|
+
.then(r => Module.main())
|
|
224
|
+
.catch(e => {
|
|
225
|
+
self.assistant.error(e, {environment: 'production'});
|
|
226
|
+
return res.status(500).send(e.message);
|
|
227
|
+
});
|
|
203
228
|
});
|
|
204
|
-
});
|
|
205
229
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
230
|
+
exporter.bm_sendNotification =
|
|
231
|
+
self.libraries.functions
|
|
232
|
+
.runWith({memory: '1GB', timeoutSeconds: 420})
|
|
233
|
+
.https.onRequest(async (req, res) => {
|
|
234
|
+
const Module = require(`${core}/admin/send-notification.js`);
|
|
235
|
+
Module.init(self, { req: req, res: res, });
|
|
212
236
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
237
|
+
return self._preProcess(Module)
|
|
238
|
+
.then(r => Module.main())
|
|
239
|
+
.catch(e => {
|
|
240
|
+
self.assistant.error(e, {environment: 'production'});
|
|
241
|
+
return res.status(500).send(e.message);
|
|
242
|
+
});
|
|
218
243
|
});
|
|
219
|
-
});
|
|
220
244
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
245
|
+
exporter.bm_query =
|
|
246
|
+
self.libraries.functions
|
|
247
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
248
|
+
.https.onRequest(async (req, res) => {
|
|
249
|
+
const Module = require(`${core}/admin/query.js`);
|
|
250
|
+
Module.init(self, { req: req, res: res, });
|
|
227
251
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
252
|
+
return self._preProcess(Module)
|
|
253
|
+
.then(r => Module.main())
|
|
254
|
+
.catch(e => {
|
|
255
|
+
self.assistant.error(e, {environment: 'production'});
|
|
256
|
+
return res.status(500).send(e.message);
|
|
257
|
+
});
|
|
233
258
|
});
|
|
234
|
-
});
|
|
235
259
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
260
|
+
exporter.bm_createPostHandler =
|
|
261
|
+
self.libraries.functions
|
|
262
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
263
|
+
.https.onRequest(async (req, res) => {
|
|
264
|
+
const Module = require(`${core}/actions/create-post-handler.js`);
|
|
265
|
+
Module.init(self, { req: req, res: res, });
|
|
242
266
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
267
|
+
return self._preProcess(Module)
|
|
268
|
+
.then(r => Module.main())
|
|
269
|
+
.catch(e => {
|
|
270
|
+
self.assistant.error(e, {environment: 'production'});
|
|
271
|
+
return res.status(500).send(e.message);
|
|
272
|
+
});
|
|
248
273
|
});
|
|
249
|
-
});
|
|
250
274
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
275
|
+
exporter.bm_generateUuid =
|
|
276
|
+
self.libraries.functions
|
|
277
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
278
|
+
.https.onRequest(async (req, res) => {
|
|
279
|
+
const Module = require(`${core}/actions/generate-uuid.js`);
|
|
280
|
+
Module.init(self, { req: req, res: res, });
|
|
257
281
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
282
|
+
return self._preProcess(Module)
|
|
283
|
+
.then(r => Module.main())
|
|
284
|
+
.catch(e => {
|
|
285
|
+
self.assistant.error(e, {environment: 'production'});
|
|
286
|
+
return res.status(500).send(e.message);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Test
|
|
291
|
+
exporter.bm_test_authenticate =
|
|
292
|
+
self.libraries.functions
|
|
293
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
294
|
+
.https.onRequest(async (req, res) => {
|
|
295
|
+
const Module = require(`${test}/authenticate.js`);
|
|
296
|
+
Module.init(self, { req: req, res: res, });
|
|
297
|
+
|
|
298
|
+
return self._preProcess(Module)
|
|
299
|
+
.then(r => Module.main())
|
|
300
|
+
.catch(e => {
|
|
301
|
+
self.assistant.error(e, {environment: 'production'});
|
|
302
|
+
return res.status(500).send(e.message);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
exporter.bm_test_createTestAccounts =
|
|
307
|
+
self.libraries.functions
|
|
308
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
309
|
+
.https.onRequest(async (req, res) => {
|
|
310
|
+
const Module = require(`${test}/create-test-accounts.js`);
|
|
311
|
+
Module.init(self, { req: req, res: res, });
|
|
312
|
+
|
|
313
|
+
return self._preProcess(Module)
|
|
314
|
+
.then(r => Module.main())
|
|
315
|
+
.catch(e => {
|
|
316
|
+
self.assistant.error(e, {environment: 'production'});
|
|
317
|
+
return res.status(500).send(e.message);
|
|
318
|
+
});
|
|
263
319
|
});
|
|
264
|
-
});
|
|
265
320
|
|
|
321
|
+
exporter.bm_test_webhook =
|
|
322
|
+
self.libraries.functions
|
|
323
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
324
|
+
.https.onRequest(async (req, res) => {
|
|
325
|
+
const Module = require(`${test}/webhook.js`);
|
|
326
|
+
Module.init(self, { req: req, res: res, });
|
|
327
|
+
|
|
328
|
+
return self._preProcess(Module)
|
|
329
|
+
.then(r => Module.main())
|
|
330
|
+
.catch(e => {
|
|
331
|
+
self.assistant.error(e, {environment: 'production'});
|
|
332
|
+
return res.status(500).send(e.message);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
}
|
|
266
336
|
|
|
267
337
|
// Events
|
|
268
338
|
exporter.bm_authOnCreate =
|
|
@@ -308,53 +378,6 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
308
378
|
self.assistant.error(e, {environment: 'production'});
|
|
309
379
|
});
|
|
310
380
|
});
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
// Test
|
|
314
|
-
exporter.bm_test_authenticate =
|
|
315
|
-
self.libraries.functions
|
|
316
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
317
|
-
.https.onRequest(async (req, res) => {
|
|
318
|
-
const Module = require(`${test}/authenticate.js`);
|
|
319
|
-
Module.init(self, { req: req, res: res, });
|
|
320
|
-
|
|
321
|
-
return self._preProcess(Module)
|
|
322
|
-
.then(r => Module.main())
|
|
323
|
-
.catch(e => {
|
|
324
|
-
self.assistant.error(e, {environment: 'production'});
|
|
325
|
-
return res.status(500).send(e.message);
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
exporter.bm_test_createTestAccounts =
|
|
330
|
-
self.libraries.functions
|
|
331
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
332
|
-
.https.onRequest(async (req, res) => {
|
|
333
|
-
const Module = require(`${test}/create-test-accounts.js`);
|
|
334
|
-
Module.init(self, { req: req, res: res, });
|
|
335
|
-
|
|
336
|
-
return self._preProcess(Module)
|
|
337
|
-
.then(r => Module.main())
|
|
338
|
-
.catch(e => {
|
|
339
|
-
self.assistant.error(e, {environment: 'production'});
|
|
340
|
-
return res.status(500).send(e.message);
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
exporter.bm_test_webhook =
|
|
345
|
-
self.libraries.functions
|
|
346
|
-
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
347
|
-
.https.onRequest(async (req, res) => {
|
|
348
|
-
const Module = require(`${test}/webhook.js`);
|
|
349
|
-
Module.init(self, { req: req, res: res, });
|
|
350
|
-
|
|
351
|
-
return self._preProcess(Module)
|
|
352
|
-
.then(r => Module.main())
|
|
353
|
-
.catch(e => {
|
|
354
|
-
self.assistant.error(e, {environment: 'production'});
|
|
355
|
-
return res.status(500).send(e.message);
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
381
|
}
|
|
359
382
|
|
|
360
383
|
// Set dotenv
|