backend-manager 2.4.5 → 2.4.6
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 +59 -37
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.6",
|
|
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
|
@@ -93,7 +93,6 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
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
|
-
|
|
97
96
|
// Use the working Firebase logger that they disabled for whatever reason
|
|
98
97
|
if (self.assistant.meta.environment !== 'development' && options.useFirebaseLogger) {
|
|
99
98
|
require('firebase-functions/lib/logger/compat');
|
|
@@ -154,15 +153,9 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
154
153
|
exporter.bm_api =
|
|
155
154
|
self.libraries.functions
|
|
156
155
|
.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
|
-
});
|
|
156
|
+
.https
|
|
157
|
+
.onRequest(async (req, res) => {
|
|
158
|
+
return self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, }))
|
|
166
159
|
});
|
|
167
160
|
|
|
168
161
|
if (options.setupFunctionsLegacy) {
|
|
@@ -338,45 +331,34 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
338
331
|
exporter.bm_authOnCreate =
|
|
339
332
|
self.libraries.functions
|
|
340
333
|
.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
|
-
});
|
|
334
|
+
.auth.user()
|
|
335
|
+
.onCreate(async (user) => {
|
|
336
|
+
return self._process((new (require(`${core}/events/auth/on-create.js`))()).init(self, { user: user, }))
|
|
350
337
|
});
|
|
351
338
|
|
|
352
339
|
exporter.bm_authOnDelete =
|
|
353
340
|
self.libraries.functions
|
|
354
341
|
.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
|
-
});
|
|
342
|
+
.auth.user()
|
|
343
|
+
.onDelete(async (user) => {
|
|
344
|
+
return self._process((new (require(`${core}/events/auth/on-delete.js`))()).init(self, { user: user, }))
|
|
364
345
|
});
|
|
365
346
|
|
|
366
347
|
exporter.bm_subOnWrite =
|
|
367
348
|
self.libraries.functions
|
|
368
349
|
.runWith({memory: '256MB', timeoutSeconds: 60})
|
|
369
|
-
.firestore
|
|
370
|
-
.document('notifications/subscriptions/all/{token}')
|
|
350
|
+
.firestore.document('notifications/subscriptions/all/{token}')
|
|
371
351
|
.onWrite(async (change, context) => {
|
|
372
|
-
|
|
373
|
-
|
|
352
|
+
return self._process((new (require(`${core}/events/firestore/on-subscription.js`))()).init(self, { change: change, context: context, }))
|
|
353
|
+
});
|
|
374
354
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
355
|
+
// Cron
|
|
356
|
+
exporter.bm_backup =
|
|
357
|
+
self.libraries.functions
|
|
358
|
+
.runWith({ memory: '256MB', timeoutSeconds: 60 })
|
|
359
|
+
.pubsub.schedule(get(self.config, 'backup.schedule', 'every 24 hours'))
|
|
360
|
+
.onRun(async (context) => {
|
|
361
|
+
return self._process((new (require(`${core}/cron/backup.js`))()).init(self, { context: context, }))
|
|
380
362
|
});
|
|
381
363
|
}
|
|
382
364
|
|
|
@@ -396,6 +378,46 @@ Manager.prototype.init = function (exporter, options) {
|
|
|
396
378
|
};
|
|
397
379
|
|
|
398
380
|
// HELPERS
|
|
381
|
+
Manager.prototype._process = function (mod) {
|
|
382
|
+
const self = this;
|
|
383
|
+
const name = mod.assistant.meta.name;
|
|
384
|
+
const hook = self.handlers && self.handlers[name];
|
|
385
|
+
const req = mod.req;
|
|
386
|
+
const res = mod.res;
|
|
387
|
+
|
|
388
|
+
return new Promise(async function(resolve, reject) {
|
|
389
|
+
let error;
|
|
390
|
+
|
|
391
|
+
function _reject(e, log) {
|
|
392
|
+
if (log) {
|
|
393
|
+
// self.assistant.error(e, {environment: 'production'});
|
|
394
|
+
mod.assistant.errorManager(e, {code: 500, sentry: true, send: false, log: true});
|
|
395
|
+
}
|
|
396
|
+
// res.status(500).send(e.message);
|
|
397
|
+
return resolve()
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Run pre
|
|
401
|
+
if (hook) {
|
|
402
|
+
await hook(mod, 'pre').catch(e => {error = e});
|
|
403
|
+
}
|
|
404
|
+
if (error) { return _reject(error, true) }
|
|
405
|
+
|
|
406
|
+
// Run main
|
|
407
|
+
await mod.main().catch(e => {error = e});
|
|
408
|
+
if (error) { return _reject(error, false) }
|
|
409
|
+
|
|
410
|
+
// Run post
|
|
411
|
+
if (hook) {
|
|
412
|
+
await hook(mod, 'post').catch(e => {error = e});
|
|
413
|
+
}
|
|
414
|
+
if (error) { return _reject(error, true) }
|
|
415
|
+
|
|
416
|
+
// Fin
|
|
417
|
+
return resolve();
|
|
418
|
+
});
|
|
419
|
+
};
|
|
420
|
+
|
|
399
421
|
Manager.prototype._preProcess = function (mod) {
|
|
400
422
|
const self = this;
|
|
401
423
|
const name = mod.assistant.meta.name;
|