backend-manager 3.2.169 → 3.2.171
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/LICENSE +1 -1
- package/README.md +1 -1
- package/dist/cli/cli.js +1534 -0
- package/dist/manager/functions/core/actions/api/admin/backup.js +338 -0
- package/dist/manager/functions/core/actions/api/admin/create-post.js +388 -0
- package/dist/manager/functions/core/actions/api/admin/cron.js +37 -0
- package/dist/manager/functions/core/actions/api/admin/database-read.js +35 -0
- package/dist/manager/functions/core/actions/api/admin/database-write.js +39 -0
- package/dist/manager/functions/core/actions/api/admin/edit-post.js +158 -0
- package/dist/manager/functions/core/actions/api/admin/firestore-query.js +165 -0
- package/dist/manager/functions/core/actions/api/admin/firestore-read.js +38 -0
- package/dist/manager/functions/core/actions/api/admin/firestore-write.js +54 -0
- package/dist/manager/functions/core/actions/api/admin/get-stats.js +269 -0
- package/dist/manager/functions/core/actions/api/admin/payment-processor.js +57 -0
- package/dist/manager/functions/core/actions/api/admin/run-hook.js +95 -0
- package/dist/manager/functions/core/actions/api/admin/send-notification.js +197 -0
- package/dist/manager/functions/core/actions/api/admin/sync-users.js +125 -0
- package/dist/manager/functions/core/actions/api/admin/templates/post.html +16 -0
- package/dist/manager/functions/core/actions/api/firebase/get-providers.js +102 -0
- package/dist/manager/functions/core/actions/api/general/emails/general:download-app-link.js +21 -0
- package/dist/manager/functions/core/actions/api/general/fetch-post.js +99 -0
- package/dist/manager/functions/core/actions/api/general/generate-uuid.js +41 -0
- package/dist/manager/functions/core/actions/api/general/send-email.js +112 -0
- package/dist/manager/functions/core/actions/api/handler/create-post.js +146 -0
- package/dist/manager/functions/core/actions/api/special/setup-electron-manager-client.js +103 -0
- package/dist/manager/functions/core/actions/api/template.js +33 -0
- package/dist/manager/functions/core/actions/api/test/authenticate.js +22 -0
- package/dist/manager/functions/core/actions/api/test/create-test-accounts.js +27 -0
- package/dist/manager/functions/core/actions/api/test/lab.js +55 -0
- package/dist/manager/functions/core/actions/api/test/redirect.js +26 -0
- package/dist/manager/functions/core/actions/api/test/webhook.js +30 -0
- package/dist/manager/functions/core/actions/api/user/create-custom-token.js +32 -0
- package/dist/manager/functions/core/actions/api/user/delete.js +68 -0
- package/dist/manager/functions/core/actions/api/user/get-active-sessions.js +45 -0
- package/dist/manager/functions/core/actions/api/user/get-subscription-info.js +49 -0
- package/dist/manager/functions/core/actions/api/user/oauth2/discord.js +114 -0
- package/dist/manager/functions/core/actions/api/user/oauth2/google.js +99 -0
- package/dist/manager/functions/core/actions/api/user/oauth2.js +476 -0
- package/dist/manager/functions/core/actions/api/user/regenerate-api-keys.js +54 -0
- package/dist/manager/functions/core/actions/api/user/resolve.js +32 -0
- package/dist/manager/functions/core/actions/api/user/sign-out-all-sessions.js +118 -0
- package/dist/manager/functions/core/actions/api/user/sign-up copy.js +544 -0
- package/dist/manager/functions/core/actions/api/user/sign-up.js +99 -0
- package/dist/manager/functions/core/actions/api/user/submit-feedback.js +96 -0
- package/dist/manager/functions/core/actions/api/user/validate-settings.js +86 -0
- package/dist/manager/functions/core/actions/api.js +354 -0
- package/dist/manager/functions/core/actions/create-post-handler.js +184 -0
- package/dist/manager/functions/core/actions/generate-uuid.js +62 -0
- package/dist/manager/functions/core/actions/sign-up-handler.js +205 -0
- package/dist/manager/functions/core/admin/create-post.js +206 -0
- package/dist/manager/functions/core/admin/firestore-write.js +72 -0
- package/dist/manager/functions/core/admin/get-stats.js +218 -0
- package/dist/manager/functions/core/admin/query.js +198 -0
- package/dist/manager/functions/core/admin/send-notification.js +206 -0
- package/dist/manager/functions/core/cron/daily/ghostii-auto-publisher.js +377 -0
- package/dist/manager/functions/core/cron/daily/reset-usage.js +197 -0
- package/dist/manager/functions/core/cron/daily.js +114 -0
- package/dist/manager/functions/core/events/auth/before-create.js +124 -0
- package/dist/manager/functions/core/events/auth/before-signin.js +62 -0
- package/dist/manager/functions/core/events/auth/on-create copy.js +121 -0
- package/dist/manager/functions/core/events/auth/on-create.js +564 -0
- package/dist/manager/functions/core/events/auth/on-delete.js +72 -0
- package/dist/manager/functions/core/events/firestore/on-subscription.js +107 -0
- package/dist/manager/functions/test/authenticate.js +38 -0
- package/dist/manager/functions/test/create-test-accounts.js +144 -0
- package/dist/manager/functions/test/webhook.js +37 -0
- package/dist/manager/functions/wrappers/mailchimp/addToList.js +25 -0
- package/dist/manager/helpers/analytics copy.js +217 -0
- package/dist/manager/helpers/analytics.js +467 -0
- package/dist/manager/helpers/api-manager.js +324 -0
- package/dist/manager/helpers/assistant.js +1043 -0
- package/dist/manager/helpers/metadata.js +32 -0
- package/dist/manager/helpers/middleware.js +154 -0
- package/dist/manager/helpers/roles.js +69 -0
- package/dist/manager/helpers/settings.js +158 -0
- package/dist/manager/helpers/subscription-resolver-new.js +828 -0
- package/dist/manager/helpers/subscription-resolver.js +842 -0
- package/dist/manager/helpers/usage.js +381 -0
- package/dist/manager/helpers/user.js +198 -0
- package/dist/manager/helpers/utilities.js +292 -0
- package/dist/manager/index.js +1076 -0
- package/dist/manager/libraries/openai.js +460 -0
- package/dist/manager/routes/restart/index.js +52 -0
- package/dist/manager/routes/test/index.js +43 -0
- package/dist/manager/schemas/restart.js +13 -0
- package/dist/manager/schemas/test.js +13 -0
- package/dist/require.js +3 -0
- package/package.json +19 -9
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const powertools = require('node-powertools');
|
|
3
|
+
|
|
4
|
+
function Module() {
|
|
5
|
+
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
Module.prototype.main = function () {
|
|
9
|
+
const self = this;
|
|
10
|
+
const Manager = self.Manager;
|
|
11
|
+
const Api = self.Api;
|
|
12
|
+
const assistant = self.assistant;
|
|
13
|
+
const payload = self.payload;
|
|
14
|
+
|
|
15
|
+
return new Promise(async function(resolve, reject) {
|
|
16
|
+
// Perform checks
|
|
17
|
+
if (!payload.user.roles.admin) {
|
|
18
|
+
return reject(assistant.errorify(`Admin required.`, {code: 401}));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Run queries
|
|
22
|
+
self.docs = [];
|
|
23
|
+
assistant.log('Queries', payload.data.payload.queries);
|
|
24
|
+
let queries = powertools.arrayify(payload.data.payload.queries || []);
|
|
25
|
+
|
|
26
|
+
let promises = [];
|
|
27
|
+
for (var i = 0; i < queries.length; i++) {
|
|
28
|
+
queries[i]
|
|
29
|
+
promises.push(self.runQuery(queries[i]))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Get the results
|
|
33
|
+
await Promise.all(promises)
|
|
34
|
+
.then((r) => {
|
|
35
|
+
return resolve({data: self.docs});
|
|
36
|
+
})
|
|
37
|
+
.catch((e) => {
|
|
38
|
+
return reject(assistant.errorify(e, {code: 500}));
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
Module.prototype.runQuery = function (query) {
|
|
46
|
+
const self = this;
|
|
47
|
+
const Manager = self.Manager;
|
|
48
|
+
const assistant = self.assistant;
|
|
49
|
+
|
|
50
|
+
query = query || {};
|
|
51
|
+
query.where = powertools.arrayify(query.where || []);
|
|
52
|
+
query.filter = powertools.arrayify(query.filter || []);
|
|
53
|
+
query.orderBy = powertools.arrayify(query.orderBy || []);
|
|
54
|
+
|
|
55
|
+
// self.assistant.log('Query', query);
|
|
56
|
+
|
|
57
|
+
return new Promise(function(resolve, reject) {
|
|
58
|
+
let collection;
|
|
59
|
+
|
|
60
|
+
if (!query.collection) {
|
|
61
|
+
return resolve([]);
|
|
62
|
+
// return reject(new Error('No collection specified.'));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
collection = self.libraries.admin.firestore().collection(query.collection);
|
|
66
|
+
|
|
67
|
+
for (var i = 0; i < query.where.length; i++) {
|
|
68
|
+
let cur = query.where[i];
|
|
69
|
+
collection = collection.where(cur.field, cur.operator, cur.value);
|
|
70
|
+
}
|
|
71
|
+
for (var i = 0; i < query.orderBy.length; i++) {
|
|
72
|
+
let cur = query.orderBy[i];
|
|
73
|
+
collection = collection.orderBy(cur.field, cur.order)
|
|
74
|
+
}
|
|
75
|
+
if (query.limit) {
|
|
76
|
+
collection = collection.limit(query.limit)
|
|
77
|
+
}
|
|
78
|
+
if (query.startAt) {
|
|
79
|
+
collection = collection.startAt(query.startAt)
|
|
80
|
+
}
|
|
81
|
+
if (query.startAfter) {
|
|
82
|
+
collection = collection.startAfter(query.startAfter)
|
|
83
|
+
}
|
|
84
|
+
if (query.endAt) {
|
|
85
|
+
collection = collection.endAt(query.endAt)
|
|
86
|
+
}
|
|
87
|
+
if (query.endBefore) {
|
|
88
|
+
collection = collection.endBefore(query.endBefore)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
collection
|
|
92
|
+
.get()
|
|
93
|
+
.then(function (querySnapshot) {
|
|
94
|
+
querySnapshot.forEach(function (doc) {
|
|
95
|
+
|
|
96
|
+
let exists = self.docs.find(item => {
|
|
97
|
+
return item.path === doc.ref.path
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
if (!exists && checkFilter(doc.data(), query.filter)) {
|
|
101
|
+
self.docs.push({
|
|
102
|
+
path: doc.ref.path,
|
|
103
|
+
data: doc.data(),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (query.filterIndex) {
|
|
110
|
+
let iS = query.filterIndex[0];
|
|
111
|
+
let iF = query.filterIndex[1];
|
|
112
|
+
iF = iF > self.docs.length ? self.docs.length - 1 : iF;
|
|
113
|
+
self.docs = self.docs.slice(iS, iF);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return resolve(self.docs);
|
|
117
|
+
})
|
|
118
|
+
.catch(function (error) {
|
|
119
|
+
self.assistant.error(error)
|
|
120
|
+
return reject(error);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
function checkFilter(data, filter) {
|
|
128
|
+
|
|
129
|
+
// Loop through all filters
|
|
130
|
+
for (var i = 0, l = filter.length; i < l; i++) {
|
|
131
|
+
// Set up field and checks
|
|
132
|
+
let field = `${filter[i].field}`.split(' || ');
|
|
133
|
+
field = powertools.arrayify(field);
|
|
134
|
+
let matches = filter[i].matches || '';
|
|
135
|
+
let regex = powertools.regexify(matches);
|
|
136
|
+
|
|
137
|
+
// Pass/fail
|
|
138
|
+
let innerPassed = false;
|
|
139
|
+
|
|
140
|
+
// Loop through each filter's fields
|
|
141
|
+
for (var i2 = 0, l2 = field.length; i2 < l2; i2++) {
|
|
142
|
+
let fieldInner = field[i2];
|
|
143
|
+
let value = _.get(data, fieldInner, undefined);
|
|
144
|
+
|
|
145
|
+
if (typeof value === 'undefined') {
|
|
146
|
+
innerPassed = false;
|
|
147
|
+
continue;
|
|
148
|
+
} else if (typeof value === 'string') {
|
|
149
|
+
if (value.match(regex)) {
|
|
150
|
+
innerPassed = true;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// If there was not a successful innerPassed then break (innerPassed works on OR logic)
|
|
157
|
+
if (!innerPassed) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = Module;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
function Module() {
|
|
2
|
+
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
Module.prototype.main = function () {
|
|
6
|
+
const self = this;
|
|
7
|
+
const Manager = self.Manager;
|
|
8
|
+
const Api = self.Api;
|
|
9
|
+
const assistant = self.assistant;
|
|
10
|
+
const payload = self.payload;
|
|
11
|
+
|
|
12
|
+
return new Promise(async function(resolve, reject) {
|
|
13
|
+
// Set defaults
|
|
14
|
+
payload.data.payload.path = `${payload.data.payload.path || ''}`;
|
|
15
|
+
payload.data.payload.options = payload.data.payload.options || {};
|
|
16
|
+
|
|
17
|
+
// Perform checks
|
|
18
|
+
if (!payload.user.roles.admin) {
|
|
19
|
+
return reject(assistant.errorify(`Admin required.`, {code: 401}));
|
|
20
|
+
} else if (!payload.data.payload.path) {
|
|
21
|
+
return reject(assistant.errorify(`<path> parameter required`, {code: 400}));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Read from Firestore
|
|
25
|
+
await self.libraries.admin.firestore().doc(payload.data.payload.path)
|
|
26
|
+
.get()
|
|
27
|
+
.then(doc => {
|
|
28
|
+
return resolve({data: doc.data()});
|
|
29
|
+
})
|
|
30
|
+
.catch(e => {
|
|
31
|
+
return reject(assistant.errorify(e, {code: 500}));
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
module.exports = Module;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
function Module() {
|
|
2
|
+
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
Module.prototype.main = function () {
|
|
6
|
+
const self = this;
|
|
7
|
+
const Manager = self.Manager;
|
|
8
|
+
const Api = self.Api;
|
|
9
|
+
const assistant = self.assistant;
|
|
10
|
+
const payload = self.payload;
|
|
11
|
+
|
|
12
|
+
return new Promise(async function(resolve, reject) {
|
|
13
|
+
// Set defaults
|
|
14
|
+
payload.data.payload.path = `${payload.data.payload.path || ''}`;
|
|
15
|
+
payload.data.payload.document = payload.data.payload.document || {};
|
|
16
|
+
payload.data.payload.options = payload.data.payload.options || {};
|
|
17
|
+
payload.data.payload.options.merge = typeof payload.data.payload.options.merge === 'undefined' ? true : payload.data.payload.options.merge;
|
|
18
|
+
payload.data.payload.options.metadataTag = typeof payload.data.payload.options.metadataTag === 'undefined' ? 'admin:firestore-write' : payload.data.payload.options.metadataTag;
|
|
19
|
+
|
|
20
|
+
// Perform checks
|
|
21
|
+
if (!payload.user.roles.admin) {
|
|
22
|
+
return reject(assistant.errorify(`Admin required.`, {code: 401}));
|
|
23
|
+
} else if (!payload.data.payload.path) {
|
|
24
|
+
return reject(assistant.errorify(`Path parameter required.`, {code: 400}));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Fix path
|
|
28
|
+
if (payload.data.payload.path.match(/\{pushId\}/)) {
|
|
29
|
+
payload.data.payload.path = payload.data.payload.path.replace(/\{pushId\}/ig, require('pushid')());
|
|
30
|
+
} else if (payload.data.payload.path.match(/\{nanoId\}/)) {
|
|
31
|
+
payload.data.payload.path = payload.data.payload.path.replace(/\{nanoId\}/ig, Manager.Utilities().randomId());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Set metadata
|
|
35
|
+
payload.data.payload.document.metadata = Manager.Metadata().set({tag: payload.data.payload.options.metadataTag})
|
|
36
|
+
|
|
37
|
+
// Delete metadataTag
|
|
38
|
+
delete payload.data.payload.options.metadataTag;
|
|
39
|
+
|
|
40
|
+
// Write to Firestore
|
|
41
|
+
await self.libraries.admin.firestore().doc(payload.data.payload.path)
|
|
42
|
+
.set(payload.data.payload.document, payload.data.payload.options)
|
|
43
|
+
.then(r => {
|
|
44
|
+
return resolve({data: {path: payload.data.payload.path}});
|
|
45
|
+
})
|
|
46
|
+
.catch(e => {
|
|
47
|
+
return reject(assistant.errorify(e, {code: 500}));
|
|
48
|
+
})
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
module.exports = Module;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
let _;
|
|
2
|
+
|
|
3
|
+
function Module() {
|
|
4
|
+
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
Module.prototype.main = function () {
|
|
8
|
+
const self = this;
|
|
9
|
+
const Manager = self.Manager;
|
|
10
|
+
const Api = self.Api;
|
|
11
|
+
const assistant = self.assistant;
|
|
12
|
+
const payload = self.payload;
|
|
13
|
+
|
|
14
|
+
return new Promise(async function(resolve, reject) {
|
|
15
|
+
// Load libraries
|
|
16
|
+
_ = Manager.require('lodash')
|
|
17
|
+
|
|
18
|
+
// Perform checks
|
|
19
|
+
if (!payload.user.roles.admin) {
|
|
20
|
+
return reject(assistant.errorify(`Admin required.`, {code: 401}));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Get stats
|
|
24
|
+
const stats = self.libraries.admin.firestore().doc(`meta/stats`)
|
|
25
|
+
await stats
|
|
26
|
+
.get()
|
|
27
|
+
.then(async (doc) => {
|
|
28
|
+
let data = doc.data() || {};
|
|
29
|
+
|
|
30
|
+
// Only update if requested
|
|
31
|
+
if (payload.data.payload.update) {
|
|
32
|
+
await self.updateStats(data)
|
|
33
|
+
.catch(e => data = e)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (data instanceof Error) {
|
|
37
|
+
return reject(assistant.errorify(data, {code: 500}));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Retrieve the stats again after updating
|
|
41
|
+
await stats
|
|
42
|
+
.get()
|
|
43
|
+
.then(doc => {
|
|
44
|
+
data = doc.data() || {};
|
|
45
|
+
})
|
|
46
|
+
.catch(e => data = e)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if (data instanceof Error) {
|
|
50
|
+
return reject(assistant.errorify(data, {code: 500}));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return resolve({data: data})
|
|
54
|
+
})
|
|
55
|
+
.catch(function (e) {
|
|
56
|
+
return reject(assistant.errorify(`Failed to get: ${e}`, {code: 500}));
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
Module.prototype.fixStats = function (data) {
|
|
63
|
+
const self = this;
|
|
64
|
+
|
|
65
|
+
return new Promise(async function(resolve, reject) {
|
|
66
|
+
const stats = self.libraries.admin.firestore().doc(`meta/stats`);
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
return resolve();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// TODO: ADD https://firebase.google.com/docs/firestore/query-data/aggregation-queries#pricing
|
|
75
|
+
Module.prototype.updateStats = function (existingData) {
|
|
76
|
+
const self = this;
|
|
77
|
+
|
|
78
|
+
return new Promise(async function(resolve, reject) {
|
|
79
|
+
const stats = self.libraries.admin.firestore().doc(`meta/stats`);
|
|
80
|
+
const gatheringOnline = self.libraries.admin.database().ref(`gatherings/online`);
|
|
81
|
+
const sessionsApp = self.libraries.admin.database().ref(`sessions/app`);
|
|
82
|
+
const sessionsOnline = self.libraries.admin.database().ref(`sessions/online`);
|
|
83
|
+
|
|
84
|
+
let error = null;
|
|
85
|
+
let update = {
|
|
86
|
+
app: _.get(self.Manager.config, 'app.id', null),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Fix broken stats
|
|
90
|
+
if (!_.get(existingData, 'users.total', null)) {
|
|
91
|
+
await self.getAllUsers()
|
|
92
|
+
.then(r => {
|
|
93
|
+
_.set(update, 'users.total', r.length)
|
|
94
|
+
})
|
|
95
|
+
.catch(e => {
|
|
96
|
+
error = new Error(`Failed fixing stats: ${e}`);
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (error) {
|
|
101
|
+
return reject(error);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Fetch new notification stats
|
|
105
|
+
await self.getAllNotifications()
|
|
106
|
+
.then(r => {
|
|
107
|
+
_.set(update, 'notifications.total', r)
|
|
108
|
+
})
|
|
109
|
+
.catch(e => {
|
|
110
|
+
error = new Error(`Failed getting notifications: ${e}`);
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Fetch new subscription stats
|
|
114
|
+
await self.getAllSubscriptions()
|
|
115
|
+
.then(r => {
|
|
116
|
+
_.set(update, 'subscriptions', r)
|
|
117
|
+
})
|
|
118
|
+
.catch(e => {
|
|
119
|
+
error = new Error(`Failed getting subscriptions: ${e}`);
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
if (error) {
|
|
123
|
+
return reject(error);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const _countUsersOnline = async (app) => {
|
|
127
|
+
await app
|
|
128
|
+
.once('value')
|
|
129
|
+
.then((snap) => {
|
|
130
|
+
const data = snap.val() || {};
|
|
131
|
+
const keys = Object.keys(data);
|
|
132
|
+
const existing = _.get(update, 'users.online', 0)
|
|
133
|
+
_.set(update, 'users.online', existing + keys.length)
|
|
134
|
+
})
|
|
135
|
+
.catch(e => {
|
|
136
|
+
error = new Error(`Failed getting online users: ${e}`);
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Count users online (in old gathering)
|
|
141
|
+
await _countUsersOnline(gatheringOnline);
|
|
142
|
+
|
|
143
|
+
// Count users online (in new session)
|
|
144
|
+
await _countUsersOnline(sessionsApp);
|
|
145
|
+
|
|
146
|
+
// Count users online (in new session)
|
|
147
|
+
await _countUsersOnline(sessionsOnline);
|
|
148
|
+
|
|
149
|
+
if (error) {
|
|
150
|
+
return reject(error);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Set metadata
|
|
154
|
+
update.metadata = self.Manager.Metadata().set({tag: 'admin:get-stats'})
|
|
155
|
+
|
|
156
|
+
// Update stats
|
|
157
|
+
await stats
|
|
158
|
+
.set(update, { merge: true })
|
|
159
|
+
.catch(function (e) {
|
|
160
|
+
return reject(new Error(`Failed getting stats: ${e}`));
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
return resolve();
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
Module.prototype.getAllUsers = function () {
|
|
168
|
+
const self = this;
|
|
169
|
+
return new Promise(async function(resolve, reject) {
|
|
170
|
+
self.users = [];
|
|
171
|
+
await getUsersBatch(self)
|
|
172
|
+
.catch(e => {
|
|
173
|
+
return reject(e);
|
|
174
|
+
})
|
|
175
|
+
return resolve(self.users);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
Module.prototype.getAllNotifications = function () {
|
|
180
|
+
const self = this;
|
|
181
|
+
return new Promise(async function(resolve, reject) {
|
|
182
|
+
await self.libraries.admin.firestore().collection('notifications/subscriptions/all')
|
|
183
|
+
.get()
|
|
184
|
+
.then(function(querySnapshot) {
|
|
185
|
+
return resolve(querySnapshot.size)
|
|
186
|
+
})
|
|
187
|
+
.catch(function(e) {
|
|
188
|
+
return reject(e)
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
Module.prototype.getAllSubscriptions = function () {
|
|
194
|
+
const self = this;
|
|
195
|
+
return new Promise(async function(resolve, reject) {
|
|
196
|
+
await self.libraries.admin.firestore().collection('users')
|
|
197
|
+
.where('plan.expires.timestampUNIX', '>=', new Date().getTime() / 1000)
|
|
198
|
+
.get()
|
|
199
|
+
.then(function(snapshot) {
|
|
200
|
+
const stats = {
|
|
201
|
+
totals: {
|
|
202
|
+
total: 0,
|
|
203
|
+
exempt: 0,
|
|
204
|
+
},
|
|
205
|
+
plans: {}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
snapshot
|
|
209
|
+
.forEach((doc, i) => {
|
|
210
|
+
const data = doc.data();
|
|
211
|
+
const planId = _.get(data, 'plan.id', 'basic');
|
|
212
|
+
const frequency = _.get(data, 'plan.payment.frequency', 'unknown');
|
|
213
|
+
const isAdmin = _.get(data, 'roles.admin', false);
|
|
214
|
+
const isVip = _.get(data, 'roles.vip', false);
|
|
215
|
+
|
|
216
|
+
if (!stats.plans[planId]) {
|
|
217
|
+
stats.plans[planId] = {
|
|
218
|
+
total: 0,
|
|
219
|
+
monthly: 0,
|
|
220
|
+
annually: 0,
|
|
221
|
+
exempt: 0,
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (isAdmin || isVip) {
|
|
226
|
+
stats.totals.exempt++;
|
|
227
|
+
stats.plans[planId].exempt++;
|
|
228
|
+
return
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
stats.totals.total++;
|
|
232
|
+
stats.plans[planId].total++;
|
|
233
|
+
stats.plans[planId][frequency] = (stats.plans[planId][frequency] || 0) + 1
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
return resolve(stats);
|
|
237
|
+
})
|
|
238
|
+
.catch(function(e) {
|
|
239
|
+
return reject(e)
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function getUsersBatch(self, nextPageToken) {
|
|
246
|
+
return new Promise(async function(resolve, reject) {
|
|
247
|
+
self.libraries.admin.auth().listUsers(1000, nextPageToken)
|
|
248
|
+
.then(function(listUsersResult) {
|
|
249
|
+
self.users = self.users.concat(listUsersResult.users);
|
|
250
|
+
if (listUsersResult.pageToken) {
|
|
251
|
+
// List next batch of users.
|
|
252
|
+
getUsersBatch(self, listUsersResult.pageToken)
|
|
253
|
+
.then(() => {
|
|
254
|
+
return resolve(listUsersResult.users);
|
|
255
|
+
})
|
|
256
|
+
.catch((e) => {
|
|
257
|
+
return reject(e);
|
|
258
|
+
})
|
|
259
|
+
} else {
|
|
260
|
+
return resolve(listUsersResult.users);
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
.catch(function(e) {
|
|
264
|
+
return reject(e);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
module.exports = Module;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const jetpack = require('fs-jetpack');
|
|
3
|
+
|
|
4
|
+
function Module() {
|
|
5
|
+
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
Module.prototype.main = function () {
|
|
9
|
+
const self = this;
|
|
10
|
+
|
|
11
|
+
// Set shortcuts
|
|
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
|
+
// Check for admin
|
|
19
|
+
if (!payload.user.roles.admin) {
|
|
20
|
+
return reject(assistant.errorify(`Admin required.`, {code: 401}));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const productId = _.get(payload, 'data.payload.payload.details.productIdGlobal');
|
|
24
|
+
if (!productId) {
|
|
25
|
+
return reject(assistant.errorify(`No productId`, {code: 400}));
|
|
26
|
+
}
|
|
27
|
+
const processorPath = `${Manager.cwd}/payment-processors/${productId}.js`
|
|
28
|
+
let processor;
|
|
29
|
+
// console.log('---processorPath', processorPath);
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
if (!jetpack.exists(processorPath)) {
|
|
33
|
+
self.assistant.warn('Subprocessor does not exist:', processorPath)
|
|
34
|
+
|
|
35
|
+
return resolve({data: {}})
|
|
36
|
+
}
|
|
37
|
+
processor = new (require(processorPath));
|
|
38
|
+
processor.Manager = self.Manager;
|
|
39
|
+
} catch (e) {
|
|
40
|
+
self.assistant.error('Subprocessor failed to load:', processorPath, e)
|
|
41
|
+
|
|
42
|
+
return resolve({data: {}})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await processor.process(payload.data.payload)
|
|
46
|
+
.then(result => {
|
|
47
|
+
return resolve({data: result});
|
|
48
|
+
})
|
|
49
|
+
.catch(e => {
|
|
50
|
+
return reject(assistant.errorify(`Payment processor @ "${processorPath}" failed: ${e}`, {code: 400, sentry: true}));
|
|
51
|
+
})
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
module.exports = Module;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Load libraries
|
|
2
|
+
// const path = require('path');
|
|
3
|
+
|
|
4
|
+
function Module() {
|
|
5
|
+
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
Module.prototype.main = function () {
|
|
9
|
+
const self = this;
|
|
10
|
+
|
|
11
|
+
// Set shortcuts
|
|
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
|
+
// Perform checks
|
|
19
|
+
if (!payload.user.roles.admin && assistant.isProduction()) {
|
|
20
|
+
return reject(assistant.errorify(`Admin required.`, {code: 401}));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check for required options
|
|
24
|
+
if (!payload.data.payload.path) {
|
|
25
|
+
return reject(assistant.errorify(`Missing required parameter: path`, {code: 400}));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Load the hook
|
|
29
|
+
const hook = self.loadHook(payload);
|
|
30
|
+
|
|
31
|
+
// Run the hook
|
|
32
|
+
try {
|
|
33
|
+
// Set variables
|
|
34
|
+
hook.Manager = assistant.Manager;
|
|
35
|
+
hook.assistant = assistant;
|
|
36
|
+
hook.context = null;
|
|
37
|
+
hook.libraries = Manager.libraries;
|
|
38
|
+
|
|
39
|
+
// Get hook name
|
|
40
|
+
const hookName = payload.data.payload.path.split('/').pop();
|
|
41
|
+
|
|
42
|
+
// Set log prefix
|
|
43
|
+
assistant.setLogPrefix(`cron/daily/${hookName}()`);
|
|
44
|
+
|
|
45
|
+
// Run the hook
|
|
46
|
+
const result = await hook.main(assistant);
|
|
47
|
+
|
|
48
|
+
return resolve({data: result, status: 200});
|
|
49
|
+
} catch (e) {
|
|
50
|
+
return reject(assistant.errorify(e.message, {code: 500}));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
Module.prototype.loadHook = function () {
|
|
56
|
+
const self = this;
|
|
57
|
+
|
|
58
|
+
// Set shortcuts
|
|
59
|
+
const Manager = self.Manager;
|
|
60
|
+
const assistant = self.assistant;
|
|
61
|
+
const payload = self.payload;
|
|
62
|
+
|
|
63
|
+
// Set paths
|
|
64
|
+
const paths = [
|
|
65
|
+
`${Manager.rootDirectory}/functions/core/${payload.data.payload.path}`,
|
|
66
|
+
`${Manager.cwd}/${payload.data.payload.path}`,
|
|
67
|
+
`${Manager.cwd}/hooks/${payload.data.payload.path}`,
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
// Loop through paths and try to load the hook
|
|
71
|
+
for (let i = 0; i < paths.length; i++) {
|
|
72
|
+
const current = pathify(paths[i]);
|
|
73
|
+
|
|
74
|
+
// Log
|
|
75
|
+
assistant.log('Trying path:', current);
|
|
76
|
+
|
|
77
|
+
// Try to load the hook
|
|
78
|
+
try {
|
|
79
|
+
// If the hook is successfully loaded, break the loop
|
|
80
|
+
return (new (require(current))());
|
|
81
|
+
} catch (e) {
|
|
82
|
+
// if the hook fails to load, continue to the next path
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function pathify(path) {
|
|
88
|
+
const fixed = path
|
|
89
|
+
.replace('.js', '')
|
|
90
|
+
|
|
91
|
+
// Return
|
|
92
|
+
return `${fixed}.js`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = Module;
|