backend-manager 2.4.5 → 2.4.8
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 +203 -0
- package/src/manager/functions/core/actions/api/admin/create-post.js +1 -1
- package/src/manager/functions/core/actions/api/admin/firestore-read.js +0 -3
- package/src/manager/functions/core/actions/api/test/webhook.js +4 -0
- package/src/manager/functions/core/actions/api/user/oauth2/discord.js +27 -7
- package/src/manager/functions/core/actions/api/user/oauth2/google.js +7 -3
- package/src/manager/functions/core/actions/api/user/oauth2.js +18 -7
- package/src/manager/functions/core/actions/api.js +54 -48
- package/src/manager/functions/core/cron/backup.js +43 -0
- package/src/manager/index-bu.js +235 -0
- package/src/manager/index.js +65 -41
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.8",
|
|
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": "^0.0.
|
|
34
|
+
"backend-assistant": "^0.0.72",
|
|
35
35
|
"busboy": "^1.6.0",
|
|
36
36
|
"chalk": "^4.1.2",
|
|
37
37
|
"cors": "^2.8.5",
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const moment = require('moment');
|
|
2
|
+
const powertools = require('node-powertools');
|
|
3
|
+
const {Storage} = require('@google-cloud/storage');
|
|
4
|
+
const storage = new Storage();
|
|
5
|
+
|
|
6
|
+
function Module() {
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
Module.prototype.main = function () {
|
|
11
|
+
const self = this;
|
|
12
|
+
const Manager = self.Manager;
|
|
13
|
+
const Api = self.Api;
|
|
14
|
+
const assistant = self.assistant;
|
|
15
|
+
const payload = self.payload;
|
|
16
|
+
|
|
17
|
+
return new Promise(async function(resolve, reject) {
|
|
18
|
+
|
|
19
|
+
payload.data.payload.deletionRegex = payload.data.payload.deletionRegex ? powertools.regexify(payload.data.payload.deletionRegex) : payload.data.payload.deletionRegex;
|
|
20
|
+
|
|
21
|
+
if (!payload.user.roles.admin) {
|
|
22
|
+
return reject(assistant.errorManager(`Admin required.`, {code: 401, sentry: false, send: false, log: false}).error)
|
|
23
|
+
} else {
|
|
24
|
+
const client = new self.libraries.admin.firestore.v1.FirestoreAdminClient({});
|
|
25
|
+
const projectId = self.Manager.project.projectId;
|
|
26
|
+
const resourceZone = self.Manager.project.resourceZone;
|
|
27
|
+
const databaseName = client.databasePath(projectId, '(default)');
|
|
28
|
+
const bucketName = `bm-backup-firestore-${projectId}`;
|
|
29
|
+
const bucketAddress = `gs://${bucketName}`;
|
|
30
|
+
|
|
31
|
+
await self.createBucket(bucketName, resourceZone);
|
|
32
|
+
await self.deleteOldFiles(bucketName, resourceZone);
|
|
33
|
+
|
|
34
|
+
client.exportDocuments({
|
|
35
|
+
name: databaseName,
|
|
36
|
+
outputUriPrefix: bucketAddress,
|
|
37
|
+
// Leave collectionIds empty to export all collections
|
|
38
|
+
// or set to a list of collection IDs to export,
|
|
39
|
+
collectionIds: []
|
|
40
|
+
})
|
|
41
|
+
.then(responses => {
|
|
42
|
+
const response = responses[0];
|
|
43
|
+
// assistant.log('Saved backup successfully', response['name'], {environment: 'development'})
|
|
44
|
+
assistant.log('Saved backup successfully:', response.metadata.outputUriPrefix, {environment: 'development'})
|
|
45
|
+
return resolve(response['name']);
|
|
46
|
+
})
|
|
47
|
+
.catch(e => {
|
|
48
|
+
return reject(assistant.errorManager(e, {code: 500, sentry: false, send: false, log: true}).error)
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
Module.prototype.createBucket = function (bucketName, resourceZone) {
|
|
58
|
+
const self = this;
|
|
59
|
+
const Manager = self.Manager;
|
|
60
|
+
const Api = self.Api;
|
|
61
|
+
const assistant = self.assistant;
|
|
62
|
+
const payload = self.payload;
|
|
63
|
+
|
|
64
|
+
return new Promise(function(resolve, reject) {
|
|
65
|
+
storage.bucket(bucketName).getMetadata()
|
|
66
|
+
.then(async (meta) => {
|
|
67
|
+
assistant.log(`${bucketName} metadata`, meta[0], {environment: 'development'})
|
|
68
|
+
return resolve();
|
|
69
|
+
})
|
|
70
|
+
.catch(async (e) => {
|
|
71
|
+
const storageCreation = await storage.createBucket(bucketName, {
|
|
72
|
+
// location: 'ASIA',
|
|
73
|
+
location: resourceZone,
|
|
74
|
+
storageClass: 'COLDLINE',
|
|
75
|
+
})
|
|
76
|
+
.then(r => r)
|
|
77
|
+
.catch(e => e)
|
|
78
|
+
|
|
79
|
+
assistant.log('storageCreation', storageCreation, {environment: 'development'})
|
|
80
|
+
|
|
81
|
+
return resolve();
|
|
82
|
+
})
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// https://github.com/zsolt-dev/auto-delete-gcp-storage-backups/blob/master/index.js
|
|
87
|
+
Module.prototype.deleteOldFiles = function (bucketName, resourceZone) {
|
|
88
|
+
const self = this;
|
|
89
|
+
const Manager = self.Manager;
|
|
90
|
+
const Api = self.Api;
|
|
91
|
+
const assistant = self.assistant;
|
|
92
|
+
const payload = self.payload;
|
|
93
|
+
|
|
94
|
+
return new Promise(async function(resolve, reject) {
|
|
95
|
+
const now = moment();
|
|
96
|
+
const deletionRegex = payload.data.payload.deletionRegex;
|
|
97
|
+
|
|
98
|
+
// Helpers
|
|
99
|
+
const getFileObjectWithMetaData = async (bucketName, fileName) => {
|
|
100
|
+
const [metaData] = await storage.bucket(bucketName).file(fileName).getMetadata();
|
|
101
|
+
return ({ fileName, created: metaData.timeCreated });
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const deleteFileFromBucket = async (bucketName, fileName) => {
|
|
105
|
+
assistant.log(`Deleting item: ${fileName}...`, );
|
|
106
|
+
return await storage.bucket(bucketName).file(fileName).delete();
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Main
|
|
110
|
+
// get the file names as an array
|
|
111
|
+
let [allFiles] = await storage.bucket(bucketName).getFiles();
|
|
112
|
+
let deletePromises = [];
|
|
113
|
+
allFiles = allFiles.map(file => file.name);
|
|
114
|
+
// console.log(`all files: ${allFiles.join(', ')}`);
|
|
115
|
+
|
|
116
|
+
// transform to array of objects with creation timestamp { fileName: xyz, created: }
|
|
117
|
+
allFiles = allFiles.map(fileName => getFileObjectWithMetaData(bucketName, fileName));
|
|
118
|
+
allFiles = await Promise.all(allFiles);
|
|
119
|
+
|
|
120
|
+
allFiles.forEach((backup, i) => {
|
|
121
|
+
const date = moment(backup.created);
|
|
122
|
+
const day = date.date();
|
|
123
|
+
const month = date.month();
|
|
124
|
+
const age = now.diff(date, 'days', false);
|
|
125
|
+
|
|
126
|
+
assistant.log(`Sorting item ${i}: date=${date.format('MMM Do, YYYY')}, day=${day}, month=${month}, age=${age}`, );
|
|
127
|
+
|
|
128
|
+
if (age >= 31) {
|
|
129
|
+
if (day === 1) { return }
|
|
130
|
+
deletePromises.push(deleteFileFromBucket(bucketName, backup.fileName))
|
|
131
|
+
} else if ((deletionRegex && backup.fileName.match(deletionRegex))) {
|
|
132
|
+
deletePromises.push(deleteFileFromBucket(bucketName, backup.fileName))
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
await Promise.all(deletePromises);
|
|
137
|
+
|
|
138
|
+
return resolve();
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
Module.prototype._deleteOldFiles = function (bucketName, resourceZone) {
|
|
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
|
+
// Helpers
|
|
151
|
+
const getFileObjectWithMetaData = async (bucketName, fileName) => {
|
|
152
|
+
const [metaData] = await storage.bucket(bucketName).file(fileName).getMetadata();
|
|
153
|
+
return ({ fileName, created: metaData.timeCreated });
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const deleteFileFromBucket = async (bucketName, fileName) => {
|
|
157
|
+
return await storage.bucket(bucketName).file(fileName).delete();
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Main
|
|
161
|
+
// get the file names as an array
|
|
162
|
+
let [allFiles] = await storage.bucket(bucketName).getFiles();
|
|
163
|
+
allFiles = allFiles.map(file => file.name);
|
|
164
|
+
console.log(`all files: ${allFiles.join(', ')}`);
|
|
165
|
+
|
|
166
|
+
// transform to array of objects with creation timestamp { fileName: xyz, created: }
|
|
167
|
+
allFiles = allFiles.map(fileName => getFileObjectWithMetaData(bucketName, fileName));
|
|
168
|
+
allFiles = await Promise.all(allFiles);
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
const filesToKeep = new Set(); // using set insted of array since set does not allow duplicates
|
|
172
|
+
|
|
173
|
+
// recent backups
|
|
174
|
+
allFiles.forEach(backup => {
|
|
175
|
+
const createdDate = new Date(backup.created);
|
|
176
|
+
createdDate.setHours( createdDate.getHours() + numHoursToKeepRecentBackups );
|
|
177
|
+
if(createdDate > new Date()) filesToKeep.add(backup.fileName);
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// daily backups
|
|
181
|
+
for(var i = 0; i < numDaysToKeepOneDailyBackup; i++) {
|
|
182
|
+
// get day
|
|
183
|
+
const now = new Date();
|
|
184
|
+
now.setDate( now.getDate() - i );
|
|
185
|
+
dateString = now.toISOString().substring(0, 10);
|
|
186
|
+
// keep only one from that day
|
|
187
|
+
const backupsFromThatDay = allFiles.filter(backup => backup.created.startsWith(dateString));
|
|
188
|
+
if(backupsFromThatDay && backupsFromThatDay.length > 0) filesToKeep.add(backupsFromThatDay[0].fileName);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// filesToKeep.forEach(item => console.log(item));
|
|
192
|
+
|
|
193
|
+
const filesToDelete = allFiles.filter(backup => !filesToKeep.has(backup.fileName));
|
|
194
|
+
console.log(`Deleting ${filesToDelete.length} files: ${filesToDelete.map(backup => backup.fileName).join(', ')}`);
|
|
195
|
+
|
|
196
|
+
const deletePromises = filesToDelete.map(backup => deleteFileFromBucket(bucketName, backup.fileName));
|
|
197
|
+
await Promise.all(deletePromises);
|
|
198
|
+
|
|
199
|
+
return resolve();
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
module.exports = Module;
|
|
@@ -15,7 +15,7 @@ Module.prototype.main = function () {
|
|
|
15
15
|
const payload = self.payload;
|
|
16
16
|
|
|
17
17
|
return new Promise(async function(resolve, reject) {
|
|
18
|
-
if (!payload.user.roles.admin
|
|
18
|
+
if (!payload.user.roles.admin && !payload.user.roles.blogger) {
|
|
19
19
|
return reject(assistant.errorManager(`Admin required.`, {code: 401, sentry: false, send: false, log: false}).error)
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -13,13 +13,10 @@ Module.prototype.main = function () {
|
|
|
13
13
|
|
|
14
14
|
if (payload.user.roles.admin) {
|
|
15
15
|
|
|
16
|
-
// console.log('---payload.data.payload', payload.data.payload);
|
|
17
|
-
|
|
18
16
|
payload.data.payload.path = `${payload.data.payload.path || ''}`;
|
|
19
17
|
payload.data.payload.document = payload.data.payload.document || {};
|
|
20
18
|
payload.data.payload.options = payload.data.payload.options || { merge: true };
|
|
21
19
|
|
|
22
|
-
|
|
23
20
|
if (!payload.data.payload.path) {
|
|
24
21
|
return reject(assistant.errorManager(`<path> parameter required`, {code: 400, sentry: false, send: false, log: false}).error)
|
|
25
22
|
} else {
|
|
@@ -8,9 +8,13 @@ Module.prototype.main = function () {
|
|
|
8
8
|
const Api = self.Api;
|
|
9
9
|
const assistant = self.assistant;
|
|
10
10
|
const payload = self.payload;
|
|
11
|
+
const powertools = Manager.require('node-powertools');
|
|
11
12
|
|
|
12
13
|
return new Promise(async function(resolve, reject) {
|
|
13
14
|
|
|
15
|
+
if (payload.data.payload.delay > 0) {
|
|
16
|
+
await powertools.wait(payload.data.payload.delay)
|
|
17
|
+
}
|
|
14
18
|
|
|
15
19
|
if (payload.data.payload.status >= 200 && payload.data.payload.status <= 299) {
|
|
16
20
|
return resolve({data: payload.data.payload.response, status: payload.data.payload.status});
|
|
@@ -17,8 +17,10 @@ function OAuth2() {
|
|
|
17
17
|
|
|
18
18
|
OAuth2.prototype.buildUrl = function (state, url) {
|
|
19
19
|
const self = this;
|
|
20
|
+
const Manager = self.Manager;
|
|
21
|
+
const assistant = self.assistant;
|
|
20
22
|
|
|
21
|
-
return new Promise(function(resolve, reject) {
|
|
23
|
+
return new Promise(async function(resolve, reject) {
|
|
22
24
|
if (state === 'authorize') {
|
|
23
25
|
// do something with url
|
|
24
26
|
return resolve()
|
|
@@ -31,19 +33,36 @@ OAuth2.prototype.buildUrl = function (state, url) {
|
|
|
31
33
|
OAuth2.prototype.verifyIdentity = function (tokenizeResult) {
|
|
32
34
|
const self = this;
|
|
33
35
|
const Manager = self.Manager;
|
|
36
|
+
const assistant = self.assistant;
|
|
37
|
+
|
|
38
|
+
return new Promise(async function(resolve, reject) {
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
const identityResponse = await fetch('https://discord.com/api/users/@me', {
|
|
41
|
+
timeout: 60000,
|
|
42
|
+
response: 'json',
|
|
43
|
+
tries: 1,
|
|
44
|
+
log: true,
|
|
45
|
+
cacheBreaker: false,
|
|
46
|
+
headers: {
|
|
47
|
+
authorization: `${tokenizeResult.token_type} ${tokenizeResult.access_token}`,
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
.then(json => json)
|
|
51
|
+
.catch(e => e)
|
|
37
52
|
|
|
38
|
-
|
|
53
|
+
assistant.log('identityResponse', identityResponse, {environment: 'development'});
|
|
54
|
+
|
|
55
|
+
if (identityResponse instanceof Error) {
|
|
56
|
+
return reject(identityResponse);
|
|
57
|
+
}
|
|
39
58
|
|
|
40
59
|
// Check if exists
|
|
41
60
|
Manager.libraries.admin.firestore().collection(`users`)
|
|
42
|
-
.where(`oauth2.${self.provider}.identity.
|
|
61
|
+
.where(`oauth2.${self.provider}.identity.id`, '==', identityResponse.id)
|
|
43
62
|
.get()
|
|
44
63
|
.then(async (snap) => {
|
|
45
64
|
if (snap.size === 0) {
|
|
46
|
-
return resolve(
|
|
65
|
+
return resolve(identityResponse);
|
|
47
66
|
} else {
|
|
48
67
|
return reject(new Error(`This ${self.name} account is already connected to a ${Manager.config.brand.name} account`));
|
|
49
68
|
}
|
|
@@ -58,8 +77,9 @@ OAuth2.prototype.verifyIdentity = function (tokenizeResult) {
|
|
|
58
77
|
// OAuth2.prototype.verifyConnection = function (newUrl, token) {
|
|
59
78
|
// const self = this;
|
|
60
79
|
// const Manager = self.Manager;
|
|
80
|
+
// const assistant = self.assistant;
|
|
61
81
|
//
|
|
62
|
-
// return new Promise(function(resolve, reject) {
|
|
82
|
+
// return new Promise(async function(resolve, reject) {
|
|
63
83
|
//
|
|
64
84
|
// fetch(newUrl, {
|
|
65
85
|
// method: 'post',
|
|
@@ -16,8 +16,10 @@ function OAuth2() {
|
|
|
16
16
|
|
|
17
17
|
OAuth2.prototype.buildUrl = function (state, url) {
|
|
18
18
|
const self = this;
|
|
19
|
+
const Manager = self.Manager;
|
|
20
|
+
const assistant = self.assistant;
|
|
19
21
|
|
|
20
|
-
return new Promise(function(resolve, reject) {
|
|
22
|
+
return new Promise(async function(resolve, reject) {
|
|
21
23
|
if (state === 'authorize') {
|
|
22
24
|
// do something with url
|
|
23
25
|
return resolve()
|
|
@@ -30,8 +32,9 @@ OAuth2.prototype.buildUrl = function (state, url) {
|
|
|
30
32
|
OAuth2.prototype.verifyIdentity = function (tokenizeResult) {
|
|
31
33
|
const self = this;
|
|
32
34
|
const Manager = self.Manager;
|
|
35
|
+
const assistant = self.assistant;
|
|
33
36
|
|
|
34
|
-
return new Promise(function(resolve, reject) {
|
|
37
|
+
return new Promise(async function(resolve, reject) {
|
|
35
38
|
const decoded = decode(tokenizeResult.id_token);
|
|
36
39
|
|
|
37
40
|
// console.log('---decoded', decoded);
|
|
@@ -57,8 +60,9 @@ OAuth2.prototype.verifyIdentity = function (tokenizeResult) {
|
|
|
57
60
|
// OAuth2.prototype.verifyConnection = function (newUrl, token) {
|
|
58
61
|
// const self = this;
|
|
59
62
|
// const Manager = self.Manager;
|
|
63
|
+
// const assistant = self.assistant;
|
|
60
64
|
//
|
|
61
|
-
// return new Promise(function(resolve, reject) {
|
|
65
|
+
// return new Promise(async function(resolve, reject) {
|
|
62
66
|
//
|
|
63
67
|
// fetch(newUrl, {
|
|
64
68
|
// method: 'post',
|
|
@@ -39,9 +39,13 @@ Module.prototype.main = function () {
|
|
|
39
39
|
: payload.data.payload.redirect
|
|
40
40
|
|
|
41
41
|
payload.data.payload.referrer = typeof payload.data.payload.referrer === 'undefined'
|
|
42
|
-
? (assistant.meta.environment === 'development' ? `http://localhost:4000/
|
|
42
|
+
? (assistant.meta.environment === 'development' ? `http://localhost:4000/authentication/account` : `${Manager.config.brand.url}/authentication/account`)
|
|
43
43
|
: payload.data.payload.referrer
|
|
44
44
|
|
|
45
|
+
payload.data.payload.serverUrl = typeof payload.data.payload.serverUrl === 'undefined'
|
|
46
|
+
? (assistant.meta.environment === 'development' ? `${Manager.project.functionsUrl}/bm_api` : `${Manager.project.functionsUrl}/bm_api`)
|
|
47
|
+
: payload.data.payload.serverUrl
|
|
48
|
+
|
|
45
49
|
payload.data.payload.provider = payload.data.payload.provider || '';
|
|
46
50
|
payload.data.payload.state = payload.data.payload.state || 'authorize'; // authorize, tokenize, deauthorize, refresh, get
|
|
47
51
|
payload.data.payload.redirect_uri = payload.data.payload.redirect_uri
|
|
@@ -59,17 +63,22 @@ Module.prototype.main = function () {
|
|
|
59
63
|
code: 'success',
|
|
60
64
|
provider: payload.data.payload.provider,
|
|
61
65
|
authenticationToken: payload.data.authenticationToken,
|
|
62
|
-
serverUrl:
|
|
66
|
+
serverUrl: payload.data.payload.serverUrl,
|
|
63
67
|
referrer: payload.data.payload.referrer,
|
|
64
68
|
redirectUrl: payload.data.payload.redirect_uri,
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
assistant.log('OAuth2 payload', payload.data.payload);
|
|
68
72
|
|
|
73
|
+
if (!payload.data.payload.provider) {
|
|
74
|
+
return reject(new Error(`The provider parameter is required.`));
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
try {
|
|
70
78
|
self.oauth2 = new (require(`./oauth2/${payload.data.payload.provider}.js`))();
|
|
71
79
|
self.oauth2.parent = self;
|
|
72
80
|
self.oauth2.Manager = self.Manager;
|
|
81
|
+
self.oauth2.assistant = self.assistant;
|
|
73
82
|
|
|
74
83
|
newUrl = self.oauth2.urls[payload.data.payload.state]
|
|
75
84
|
|
|
@@ -159,6 +168,8 @@ Module.prototype.processState_tokenize = function (newUrl) {
|
|
|
159
168
|
return new Promise(async function(resolve, reject) {
|
|
160
169
|
const finalUrl = newUrl.toString();
|
|
161
170
|
|
|
171
|
+
assistant.log('Running processState_tokenize()', {environment: 'development'});
|
|
172
|
+
|
|
162
173
|
const body = {
|
|
163
174
|
client_id: _.get(Manager.config, `oauth2.${payload.data.payload.provider}.client_id`),
|
|
164
175
|
client_secret: _.get(Manager.config, `oauth2.${payload.data.payload.provider}.client_secret`),
|
|
@@ -168,13 +179,13 @@ Module.prototype.processState_tokenize = function (newUrl) {
|
|
|
168
179
|
// scope: '',
|
|
169
180
|
};
|
|
170
181
|
|
|
171
|
-
|
|
182
|
+
assistant.log('body', body, {environment: 'development'});
|
|
172
183
|
|
|
173
184
|
const tokenizeResponse = await fetch(finalUrl, {
|
|
174
185
|
method: 'POST',
|
|
175
186
|
timeout: 60000,
|
|
176
187
|
response: 'json',
|
|
177
|
-
tries:
|
|
188
|
+
tries: 1,
|
|
178
189
|
log: true,
|
|
179
190
|
body: new URLSearchParams(body),
|
|
180
191
|
cacheBreaker: false,
|
|
@@ -185,7 +196,7 @@ Module.prototype.processState_tokenize = function (newUrl) {
|
|
|
185
196
|
.then(json => json)
|
|
186
197
|
.catch(e => e)
|
|
187
198
|
|
|
188
|
-
|
|
199
|
+
assistant.log('tokenizeResponse', tokenizeResponse, {environment: 'development'});
|
|
189
200
|
|
|
190
201
|
if (tokenizeResponse instanceof Error) {
|
|
191
202
|
return reject(tokenizeResponse);
|
|
@@ -196,7 +207,7 @@ Module.prototype.processState_tokenize = function (newUrl) {
|
|
|
196
207
|
.then(identity => identity)
|
|
197
208
|
.catch(e => e);
|
|
198
209
|
|
|
199
|
-
|
|
210
|
+
assistant.log('verifiedIdentity', verifiedIdentity, {environment: 'development'});
|
|
200
211
|
|
|
201
212
|
if (verifiedIdentity instanceof Error) {
|
|
202
213
|
return reject(verifiedIdentity);
|
|
@@ -222,7 +233,7 @@ Module.prototype.processState_tokenize = function (newUrl) {
|
|
|
222
233
|
.then(r => r)
|
|
223
234
|
.catch(e => e)
|
|
224
235
|
|
|
225
|
-
|
|
236
|
+
assistant.log('storeResponse', storeResponse, {environment: 'development'});
|
|
226
237
|
|
|
227
238
|
if (storeResponse instanceof Error) {
|
|
228
239
|
return reject(storeResponse);
|
|
@@ -39,64 +39,70 @@ Module.prototype.main = function() {
|
|
|
39
39
|
const req = self.req;
|
|
40
40
|
const res = self.res;
|
|
41
41
|
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
return new Promise(async function(resolve, reject) {
|
|
43
|
+
return libraries.cors(req, res, async () => {
|
|
44
|
+
self.payload.data = assistant.request.data;
|
|
45
|
+
self.payload.user = await assistant.authenticate();
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
const resolved = self.resolveCommand(self.payload.data.command);
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
self.assistant.log(`Executing: ${resolved.command}`, self.payload, JSON.stringify(self.payload), {environment: 'production'})
|
|
50
|
+
self.assistant.log(`Resolved URL: ${Manager.project.functionsUrl}?command=${encodeURIComponent(resolved.command)}&payload=${encodeURIComponent(JSON.stringify(self.assistant.request.data.payload))}`, {environment: 'development'})
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
self.payload.response.status = 400;
|
|
53
|
-
self.payload.response.error = new Error(`${self.payload.data.command} is not a valid command`);
|
|
54
|
-
} else {
|
|
55
|
-
await self.import(resolved.command)
|
|
56
|
-
.then(async lib => {
|
|
57
|
-
try {
|
|
58
|
-
// Call main function
|
|
59
|
-
await lib.main()
|
|
60
|
-
.then(result => {
|
|
61
|
-
result = result || {};
|
|
62
|
-
// console.log('---result', result);
|
|
63
|
-
// console.log('---self.payload.response.data', self.payload.response.data);
|
|
64
|
-
self.payload.response.status = result.status || self.payload.response.status || 200;
|
|
65
|
-
self.payload.response.data = result.data || self.payload.response.data || {};
|
|
66
|
-
self.payload.response.redirect = result.redirect || self.payload.response.redirect || null;
|
|
67
|
-
})
|
|
68
|
-
.catch(e => {
|
|
69
|
-
self.payload.response.status = e.code || 500;
|
|
70
|
-
self.payload.response.error = e || new Error('Unknown error occured');
|
|
71
|
-
})
|
|
72
|
-
} catch (e) {
|
|
73
|
-
self.payload.response.status = 500;
|
|
74
|
-
self.payload.response.error = e || new Error('Unknown error occured');
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
.catch(e => {
|
|
52
|
+
if (!resolved.exists) {
|
|
78
53
|
self.payload.response.status = 400;
|
|
79
|
-
self.payload.response.error = new Error(
|
|
80
|
-
}
|
|
81
|
-
|
|
54
|
+
self.payload.response.error = new Error(`${self.payload.data.command} is not a valid command`);
|
|
55
|
+
} else {
|
|
56
|
+
await self.import(resolved.command)
|
|
57
|
+
.then(async lib => {
|
|
58
|
+
try {
|
|
59
|
+
// Call main function
|
|
60
|
+
await lib.main()
|
|
61
|
+
.then(result => {
|
|
62
|
+
result = result || {};
|
|
63
|
+
// console.log('---result', result);
|
|
64
|
+
// console.log('---self.payload.response.data', self.payload.response.data);
|
|
65
|
+
self.payload.response.status = result.status || self.payload.response.status || 200;
|
|
66
|
+
self.payload.response.data = result.data || self.payload.response.data || {};
|
|
67
|
+
self.payload.response.redirect = result.redirect || self.payload.response.redirect || null;
|
|
68
|
+
})
|
|
69
|
+
.catch(e => {
|
|
70
|
+
// console.log('---e', e);
|
|
71
|
+
self.payload.response.status = e.code || 500;
|
|
72
|
+
self.payload.response.error = e || new Error('Unknown error occured');
|
|
73
|
+
})
|
|
74
|
+
} catch (e) {
|
|
75
|
+
self.payload.response.status = 500;
|
|
76
|
+
self.payload.response.error = e || new Error('Unknown error occured');
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
.catch(e => {
|
|
80
|
+
self.payload.response.status = 400;
|
|
81
|
+
self.payload.response.error = new Error(`Failed to import: ${e}`);
|
|
82
|
+
})
|
|
83
|
+
}
|
|
82
84
|
|
|
83
|
-
|
|
85
|
+
self.payload.response.status = _fixStatus(self.payload.response.status);
|
|
84
86
|
|
|
85
|
-
|
|
87
|
+
res.status(self.payload.response.status)
|
|
86
88
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
if (self.payload.response.status >= 200 && self.payload.response.status < 300) {
|
|
90
|
+
self.assistant.log(`Finished ${resolved.command} (status=${self.payload.response.status})`, self.payload, JSON.stringify(self.payload), {environment: 'production'})
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
if (self.payload.response.redirect) {
|
|
93
|
+
res.redirect(self.payload.response.redirect);
|
|
94
|
+
return resolve();
|
|
95
|
+
} else {
|
|
96
|
+
res.json(self.payload.response.data);
|
|
97
|
+
return resolve();
|
|
98
|
+
}
|
|
92
99
|
} else {
|
|
93
|
-
|
|
100
|
+
console.error(`Error executing ${resolved.command} @ ${resolved.path} (status=${self.payload.response.status}):`, self.payload.response.error)
|
|
101
|
+
// return res.send(self.payload.response.error.message);
|
|
102
|
+
res.send(`${self.payload.response.error}`)
|
|
103
|
+
return reject(self.payload.response.error);
|
|
94
104
|
}
|
|
95
|
-
}
|
|
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}`);
|
|
99
|
-
}
|
|
105
|
+
});
|
|
100
106
|
});
|
|
101
107
|
}
|
|
102
108
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const fetch = require('wonderful-fetch');
|
|
2
|
+
|
|
3
|
+
function Module() {
|
|
4
|
+
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
Module.prototype.init = function (Manager, data) {
|
|
8
|
+
const self = this;
|
|
9
|
+
self.Manager = Manager;
|
|
10
|
+
self.libraries = Manager.libraries;
|
|
11
|
+
self.assistant = Manager.Assistant()
|
|
12
|
+
|
|
13
|
+
self.context = data.context;
|
|
14
|
+
return self;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Module.prototype.main = function() {
|
|
18
|
+
const self = this;
|
|
19
|
+
const Manager = self.Manager;
|
|
20
|
+
const libraries = self.libraries;
|
|
21
|
+
const assistant = self.assistant;
|
|
22
|
+
const context = self.context;
|
|
23
|
+
|
|
24
|
+
return new Promise(async function(resolve, reject) {
|
|
25
|
+
fetch(`${Manager.project.functionsUrl}/bm_api`, {
|
|
26
|
+
method: 'post',
|
|
27
|
+
body: {
|
|
28
|
+
backendManagerKey: Manager.config.backend_manager.key,
|
|
29
|
+
command: 'admin:backup',
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
.then(response => {
|
|
33
|
+
assistant.log(`Successfully executed backup: ${response}`, {environment: 'production'})
|
|
34
|
+
return resolve(response);
|
|
35
|
+
})
|
|
36
|
+
.catch(e => {
|
|
37
|
+
assistant.errorManager(`Error executing backup: ${e}`, {sentry: true, send: false, log: true})
|
|
38
|
+
return reject();
|
|
39
|
+
})
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = Module;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
if (options.setupFunctions) {
|
|
2
|
+
// exporter.bm_api =
|
|
3
|
+
// self.libraries.functions
|
|
4
|
+
// .runWith({memory: '256MB', timeoutSeconds: 60})
|
|
5
|
+
// .https.onRequest(async (req, res) => {
|
|
6
|
+
// const Module = (new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, });
|
|
7
|
+
//
|
|
8
|
+
// return self._preProcess(Module)
|
|
9
|
+
// .then(r => Module.main())
|
|
10
|
+
// .catch(e => {
|
|
11
|
+
// self.assistant.error(e, {environment: 'production'});
|
|
12
|
+
// return res.status(500).send(e.message);
|
|
13
|
+
// });
|
|
14
|
+
// });
|
|
15
|
+
exporter.bm_api =
|
|
16
|
+
self.libraries.functions
|
|
17
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
18
|
+
.https.onRequest(async (req, res) => {
|
|
19
|
+
return self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, }))
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (options.setupFunctionsLegacy) {
|
|
23
|
+
exporter.bm_signUpHandler =
|
|
24
|
+
self.libraries.functions
|
|
25
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
26
|
+
.https.onRequest(async (req, res) => {
|
|
27
|
+
const Module = require(`${core}/actions/sign-up-handler.js`);
|
|
28
|
+
Module.init(self, { req: req, res: res, });
|
|
29
|
+
|
|
30
|
+
return self._preProcess(Module)
|
|
31
|
+
.then(r => Module.main())
|
|
32
|
+
.catch(e => {
|
|
33
|
+
self.assistant.error(e, {environment: 'production'});
|
|
34
|
+
return res.status(500).send(e.message);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Admin
|
|
39
|
+
exporter.bm_createPost =
|
|
40
|
+
self.libraries.functions
|
|
41
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
42
|
+
.https.onRequest(async (req, res) => {
|
|
43
|
+
const Module = require(`${core}/admin/create-post.js`);
|
|
44
|
+
Module.init(self, { req: req, res: res, });
|
|
45
|
+
|
|
46
|
+
return self._preProcess(Module)
|
|
47
|
+
.then(r => Module.main())
|
|
48
|
+
.catch(e => {
|
|
49
|
+
self.assistant.error(e, {environment: 'production'});
|
|
50
|
+
return res.status(500).send(e.message);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
exporter.bm_firestoreWrite =
|
|
55
|
+
self.libraries.functions
|
|
56
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
57
|
+
.https.onRequest(async (req, res) => {
|
|
58
|
+
const Module = require(`${core}/admin/firestore-write.js`);
|
|
59
|
+
Module.init(self, { req: req, res: res, });
|
|
60
|
+
|
|
61
|
+
return self._preProcess(Module)
|
|
62
|
+
.then(r => Module.main())
|
|
63
|
+
.catch(e => {
|
|
64
|
+
self.assistant.error(e, {environment: 'production'});
|
|
65
|
+
return res.status(500).send(e.message);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
exporter.bm_getStats =
|
|
70
|
+
self.libraries.functions
|
|
71
|
+
.runWith({memory: '256MB', timeoutSeconds: 420})
|
|
72
|
+
.https.onRequest(async (req, res) => {
|
|
73
|
+
const Module = require(`${core}/admin/get-stats.js`);
|
|
74
|
+
Module.init(self, { req: req, res: res, });
|
|
75
|
+
|
|
76
|
+
return self._preProcess(Module)
|
|
77
|
+
.then(r => Module.main())
|
|
78
|
+
.catch(e => {
|
|
79
|
+
self.assistant.error(e, {environment: 'production'});
|
|
80
|
+
return res.status(500).send(e.message);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
exporter.bm_sendNotification =
|
|
85
|
+
self.libraries.functions
|
|
86
|
+
.runWith({memory: '1GB', timeoutSeconds: 420})
|
|
87
|
+
.https.onRequest(async (req, res) => {
|
|
88
|
+
const Module = require(`${core}/admin/send-notification.js`);
|
|
89
|
+
Module.init(self, { req: req, res: res, });
|
|
90
|
+
|
|
91
|
+
return self._preProcess(Module)
|
|
92
|
+
.then(r => Module.main())
|
|
93
|
+
.catch(e => {
|
|
94
|
+
self.assistant.error(e, {environment: 'production'});
|
|
95
|
+
return res.status(500).send(e.message);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
exporter.bm_query =
|
|
100
|
+
self.libraries.functions
|
|
101
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
102
|
+
.https.onRequest(async (req, res) => {
|
|
103
|
+
const Module = require(`${core}/admin/query.js`);
|
|
104
|
+
Module.init(self, { req: req, res: res, });
|
|
105
|
+
|
|
106
|
+
return self._preProcess(Module)
|
|
107
|
+
.then(r => Module.main())
|
|
108
|
+
.catch(e => {
|
|
109
|
+
self.assistant.error(e, {environment: 'production'});
|
|
110
|
+
return res.status(500).send(e.message);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
exporter.bm_createPostHandler =
|
|
115
|
+
self.libraries.functions
|
|
116
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
117
|
+
.https.onRequest(async (req, res) => {
|
|
118
|
+
const Module = require(`${core}/actions/create-post-handler.js`);
|
|
119
|
+
Module.init(self, { req: req, res: res, });
|
|
120
|
+
|
|
121
|
+
return self._preProcess(Module)
|
|
122
|
+
.then(r => Module.main())
|
|
123
|
+
.catch(e => {
|
|
124
|
+
self.assistant.error(e, {environment: 'production'});
|
|
125
|
+
return res.status(500).send(e.message);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
exporter.bm_generateUuid =
|
|
130
|
+
self.libraries.functions
|
|
131
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
132
|
+
.https.onRequest(async (req, res) => {
|
|
133
|
+
const Module = require(`${core}/actions/generate-uuid.js`);
|
|
134
|
+
Module.init(self, { req: req, res: res, });
|
|
135
|
+
|
|
136
|
+
return self._preProcess(Module)
|
|
137
|
+
.then(r => Module.main())
|
|
138
|
+
.catch(e => {
|
|
139
|
+
self.assistant.error(e, {environment: 'production'});
|
|
140
|
+
return res.status(500).send(e.message);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Test
|
|
145
|
+
exporter.bm_test_authenticate =
|
|
146
|
+
self.libraries.functions
|
|
147
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
148
|
+
.https.onRequest(async (req, res) => {
|
|
149
|
+
const Module = require(`${test}/authenticate.js`);
|
|
150
|
+
Module.init(self, { req: req, res: res, });
|
|
151
|
+
|
|
152
|
+
return self._preProcess(Module)
|
|
153
|
+
.then(r => Module.main())
|
|
154
|
+
.catch(e => {
|
|
155
|
+
self.assistant.error(e, {environment: 'production'});
|
|
156
|
+
return res.status(500).send(e.message);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
exporter.bm_test_createTestAccounts =
|
|
161
|
+
self.libraries.functions
|
|
162
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
163
|
+
.https.onRequest(async (req, res) => {
|
|
164
|
+
const Module = require(`${test}/create-test-accounts.js`);
|
|
165
|
+
Module.init(self, { req: req, res: res, });
|
|
166
|
+
|
|
167
|
+
return self._preProcess(Module)
|
|
168
|
+
.then(r => Module.main())
|
|
169
|
+
.catch(e => {
|
|
170
|
+
self.assistant.error(e, {environment: 'production'});
|
|
171
|
+
return res.status(500).send(e.message);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
exporter.bm_test_webhook =
|
|
176
|
+
self.libraries.functions
|
|
177
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
178
|
+
.https.onRequest(async (req, res) => {
|
|
179
|
+
const Module = require(`${test}/webhook.js`);
|
|
180
|
+
Module.init(self, { req: req, res: res, });
|
|
181
|
+
|
|
182
|
+
return self._preProcess(Module)
|
|
183
|
+
.then(r => Module.main())
|
|
184
|
+
.catch(e => {
|
|
185
|
+
self.assistant.error(e, {environment: 'production'});
|
|
186
|
+
return res.status(500).send(e.message);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Events
|
|
192
|
+
exporter.bm_authOnCreate =
|
|
193
|
+
self.libraries.functions
|
|
194
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
195
|
+
.auth.user().onCreate(async (user) => {
|
|
196
|
+
const Module = require(`${core}/events/auth/on-create.js`);
|
|
197
|
+
Module.init(self, { user: user });
|
|
198
|
+
|
|
199
|
+
return self._preProcess(Module)
|
|
200
|
+
.then(r => Module.main())
|
|
201
|
+
.catch(e => {
|
|
202
|
+
self.assistant.error(e, {environment: 'production'});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
exporter.bm_authOnDelete =
|
|
207
|
+
self.libraries.functions
|
|
208
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
209
|
+
.auth.user().onDelete(async (user) => {
|
|
210
|
+
const Module = require(`${core}/events/auth/on-delete.js`);
|
|
211
|
+
Module.init(self, { user: user });
|
|
212
|
+
|
|
213
|
+
return self._preProcess(Module)
|
|
214
|
+
.then(r => Module.main())
|
|
215
|
+
.catch(e => {
|
|
216
|
+
self.assistant.error(e, {environment: 'production'});
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
exporter.bm_subOnWrite =
|
|
221
|
+
self.libraries.functions
|
|
222
|
+
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
223
|
+
.firestore
|
|
224
|
+
.document('notifications/subscriptions/all/{token}')
|
|
225
|
+
.onWrite(async (change, context) => {
|
|
226
|
+
const Module = require(`${core}/events/firestore/on-subscription.js`);
|
|
227
|
+
Module.init(self, { change: change, context: context, });
|
|
228
|
+
|
|
229
|
+
return self._preProcess(Module)
|
|
230
|
+
.then(r => Module.main())
|
|
231
|
+
.catch(e => {
|
|
232
|
+
self.assistant.error(e, {environment: 'production'});
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
package/src/manager/index.js
CHANGED
|
@@ -72,11 +72,13 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
72
72
|
// };
|
|
73
73
|
|
|
74
74
|
// Set properties
|
|
75
|
+
self.cwd = process.cwd();
|
|
76
|
+
|
|
75
77
|
self.options = options;
|
|
76
78
|
self.project = options.firebaseConfig || JSON.parse(process.env.FIREBASE_CONFIG || '{}');
|
|
77
79
|
self.project.resourceZone = options.resourceZone;
|
|
80
|
+
self.project.serviceAccountPath = path.resolve(self.cwd, options.serviceAccountPath)
|
|
78
81
|
|
|
79
|
-
self.cwd = process.cwd();
|
|
80
82
|
self.package = resolveProjectPackage();
|
|
81
83
|
self.config = merge(
|
|
82
84
|
require(path.resolve(self.cwd, 'backend-manager-config.json')),
|
|
@@ -86,13 +88,12 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
86
88
|
// Init assistant
|
|
87
89
|
self.assistant = self.Assistant().init(undefined, options.assistant);
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
// set more properties (need to wait for assistant to determine if DEV)
|
|
91
|
+
// Set more properties (need to wait for assistant to determine if DEV)
|
|
92
92
|
self.project.functionsUrl = self.assistant.meta.environment === 'development'
|
|
93
93
|
? `http://localhost:5001/${self.project.projectId}/${self.project.resourceZone}`
|
|
94
94
|
: `https://${self.project.resourceZone}-${self.project.projectId}.cloudfunctions.net`;
|
|
95
95
|
|
|
96
|
+
process.env.ENVIRONMENT = !process.env.ENVIRONMENT ? self.assistant.meta.environment : process.env.ENVIRONMENT;
|
|
96
97
|
|
|
97
98
|
// Use the working Firebase logger that they disabled for whatever reason
|
|
98
99
|
if (self.assistant.meta.environment !== 'development' && options.useFirebaseLogger) {
|
|
@@ -138,7 +139,7 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
138
139
|
} else {
|
|
139
140
|
self.libraries.initializedAdmin = self.libraries.admin.initializeApp({
|
|
140
141
|
credential: self.libraries.admin.credential.cert(
|
|
141
|
-
require(
|
|
142
|
+
require(self.project.serviceAccountPath)
|
|
142
143
|
),
|
|
143
144
|
databaseURL: self.project.databaseURL,
|
|
144
145
|
}, options.uniqueAppName);
|
|
@@ -154,15 +155,9 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
154
155
|
exporter.bm_api =
|
|
155
156
|
self.libraries.functions
|
|
156
157
|
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
157
|
-
.https
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return self._preProcess(Module)
|
|
161
|
-
.then(r => Module.main())
|
|
162
|
-
.catch(e => {
|
|
163
|
-
self.assistant.error(e, {environment: 'production'});
|
|
164
|
-
return res.status(500).send(e.message);
|
|
165
|
-
});
|
|
158
|
+
.https
|
|
159
|
+
.onRequest(async (req, res) => {
|
|
160
|
+
return self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, }))
|
|
166
161
|
});
|
|
167
162
|
|
|
168
163
|
if (options.setupFunctionsLegacy) {
|
|
@@ -338,45 +333,34 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
338
333
|
exporter.bm_authOnCreate =
|
|
339
334
|
self.libraries.functions
|
|
340
335
|
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
341
|
-
.auth.user()
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return self._preProcess(Module)
|
|
346
|
-
.then(r => Module.main())
|
|
347
|
-
.catch(e => {
|
|
348
|
-
self.assistant.error(e, {environment: 'production'});
|
|
349
|
-
});
|
|
336
|
+
.auth.user()
|
|
337
|
+
.onCreate(async (user) => {
|
|
338
|
+
return self._process((new (require(`${core}/events/auth/on-create.js`))()).init(self, { user: user, }))
|
|
350
339
|
});
|
|
351
340
|
|
|
352
341
|
exporter.bm_authOnDelete =
|
|
353
342
|
self.libraries.functions
|
|
354
343
|
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
355
|
-
.auth.user()
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return self._preProcess(Module)
|
|
360
|
-
.then(r => Module.main())
|
|
361
|
-
.catch(e => {
|
|
362
|
-
self.assistant.error(e, {environment: 'production'});
|
|
363
|
-
});
|
|
344
|
+
.auth.user()
|
|
345
|
+
.onDelete(async (user) => {
|
|
346
|
+
return self._process((new (require(`${core}/events/auth/on-delete.js`))()).init(self, { user: user, }))
|
|
364
347
|
});
|
|
365
348
|
|
|
366
349
|
exporter.bm_subOnWrite =
|
|
367
350
|
self.libraries.functions
|
|
368
351
|
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
369
|
-
.firestore
|
|
370
|
-
.document('notifications/subscriptions/all/{token}')
|
|
352
|
+
.firestore.document('notifications/subscriptions/all/{token}')
|
|
371
353
|
.onWrite(async (change, context) => {
|
|
372
|
-
|
|
373
|
-
|
|
354
|
+
return self._process((new (require(`${core}/events/firestore/on-subscription.js`))()).init(self, { change: change, context: context, }))
|
|
355
|
+
});
|
|
374
356
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
357
|
+
// Cron
|
|
358
|
+
exporter.bm_backup =
|
|
359
|
+
self.libraries.functions
|
|
360
|
+
.runWith({ memory: '256MB', timeoutSeconds: 60 })
|
|
361
|
+
.pubsub.schedule(get(self.config, 'backup.schedule', 'every 24 hours'))
|
|
362
|
+
.onRun(async (context) => {
|
|
363
|
+
return self._process((new (require(`${core}/cron/backup.js`))()).init(self, { context: context, }))
|
|
380
364
|
});
|
|
381
365
|
}
|
|
382
366
|
|
|
@@ -396,6 +380,46 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
396
380
|
};
|
|
397
381
|
|
|
398
382
|
// HELPERS
|
|
383
|
+
Manager.prototype._process = function (mod) {
|
|
384
|
+
const self = this;
|
|
385
|
+
const name = mod.assistant.meta.name;
|
|
386
|
+
const hook = self.handlers && self.handlers[name];
|
|
387
|
+
const req = mod.req;
|
|
388
|
+
const res = mod.res;
|
|
389
|
+
|
|
390
|
+
return new Promise(async function(resolve, reject) {
|
|
391
|
+
let error;
|
|
392
|
+
|
|
393
|
+
function _reject(e, log) {
|
|
394
|
+
if (log) {
|
|
395
|
+
// self.assistant.error(e, {environment: 'production'});
|
|
396
|
+
mod.assistant.errorManager(e, {code: 500, sentry: true, send: false, log: true});
|
|
397
|
+
}
|
|
398
|
+
// res.status(500).send(e.message);
|
|
399
|
+
return resolve()
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Run pre
|
|
403
|
+
if (hook) {
|
|
404
|
+
await hook(mod, 'pre').catch(e => {error = e});
|
|
405
|
+
}
|
|
406
|
+
if (error) { return _reject(error, true) }
|
|
407
|
+
|
|
408
|
+
// Run main
|
|
409
|
+
await mod.main().catch(e => {error = e});
|
|
410
|
+
if (error) { return _reject(error, false) }
|
|
411
|
+
|
|
412
|
+
// Run post
|
|
413
|
+
if (hook) {
|
|
414
|
+
await hook(mod, 'post').catch(e => {error = e});
|
|
415
|
+
}
|
|
416
|
+
if (error) { return _reject(error, true) }
|
|
417
|
+
|
|
418
|
+
// Fin
|
|
419
|
+
return resolve();
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
|
|
399
423
|
Manager.prototype._preProcess = function (mod) {
|
|
400
424
|
const self = this;
|
|
401
425
|
const name = mod.assistant.meta.name;
|