backend-manager 2.2.4 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backend-manager",
|
|
3
|
-
"version": "2.2
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "Quick tools for developing Firebase functions",
|
|
5
5
|
"main": "src/manager/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -27,17 +27,17 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://itwcreativeworks.com",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@firebase/rules-unit-testing": "^2.0.
|
|
30
|
+
"@firebase/rules-unit-testing": "^2.0.3",
|
|
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.66",
|
|
35
35
|
"busboy": "^1.6.0",
|
|
36
36
|
"chalk": "^4.1.2",
|
|
37
37
|
"cors": "^2.8.5",
|
|
38
38
|
"dotenv": "^16.0.1",
|
|
39
39
|
"firebase-admin": "^9.12.0",
|
|
40
|
-
"firebase-functions": "^3.
|
|
40
|
+
"firebase-functions": "^3.22.0",
|
|
41
41
|
"fs-jetpack": "^4.3.1",
|
|
42
42
|
"hcaptcha": "^0.1.1",
|
|
43
43
|
"inquirer": "^8.2.4",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"mocha": "^9.2.2",
|
|
49
49
|
"moment": "^2.29.3",
|
|
50
50
|
"node-fetch": "^2.6.7",
|
|
51
|
-
"node-powertools": "^0.0.
|
|
51
|
+
"node-powertools": "^0.0.14",
|
|
52
52
|
"npm-api": "^1.0.1",
|
|
53
|
-
"paypal-server-api": "^0.0.
|
|
53
|
+
"paypal-server-api": "^0.0.7",
|
|
54
54
|
"pushid": "^1.0.0",
|
|
55
55
|
"semver": "^7.3.7",
|
|
56
56
|
"shortid": "^2.2.16",
|
package/src/cli/cli.js
CHANGED
|
@@ -43,9 +43,9 @@ const fetch = require('node-fetch');
|
|
|
43
43
|
|
|
44
44
|
let bem_giRegex = 'Set in .setup()'
|
|
45
45
|
let bem_giRegexOuter = /# BEM>>>(.*\n?)# <<<BEM/sg;
|
|
46
|
-
let
|
|
47
|
-
let
|
|
48
|
-
let
|
|
46
|
+
let bem_allRulesRegex = /(\/\/\/---backend-manager---\/\/\/)(.*?)(\/\/\/---------end---------\/\/\/)/sgm;
|
|
47
|
+
let bem_allRulesDefaultRegex = /(\/\/\/---default-rules---\/\/\/)(.*?)(\/\/\/---------end---------\/\/\/)/sgm;
|
|
48
|
+
let bem_allRulesBackupRegex = /({{\s*?backend-manager\s*?}})/sgm;
|
|
49
49
|
let MOCHA_PKG_SCRIPT = 'mocha ../test/ --recursive --timeout=10000';
|
|
50
50
|
let NPM_CLEAN_SCRIPT = 'rm -fr node_modules && rm -fr package-lock.json && npm cache clean --force && npm install && npm rb';
|
|
51
51
|
let NOFIX_TEXT = chalk.red(`There is no automatic fix for this check.`);
|
|
@@ -139,7 +139,7 @@ Main.prototype.process = async function (args) {
|
|
|
139
139
|
|
|
140
140
|
if (self.options['rules:default'] || self.options['rules:getdefault']) {
|
|
141
141
|
self.getRulesFile();
|
|
142
|
-
console.log(self.default.firestoreRulesWhole.match(
|
|
142
|
+
console.log(self.default.firestoreRulesWhole.match(bem_allRulesDefaultRegex)[0].replace(' ///', '///'));
|
|
143
143
|
return;
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -205,9 +205,11 @@ module.exports = Main;
|
|
|
205
205
|
|
|
206
206
|
Main.prototype.getRulesFile = function () {
|
|
207
207
|
const self = this;
|
|
208
|
-
self.default.firestoreRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/firestore.rules`))).replace('=0.0.0-',
|
|
209
|
-
self.default.firestoreRulesCore = self.default.firestoreRulesWhole.match(
|
|
208
|
+
self.default.firestoreRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/firestore.rules`))).replace('=0.0.0-', `=${self.default.version}-`);
|
|
209
|
+
self.default.firestoreRulesCore = self.default.firestoreRulesWhole.match(bem_allRulesRegex)[0];
|
|
210
210
|
|
|
211
|
+
self.default.databaseRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/database.rules.json`))).replace('=0.0.0-', `=${self.default.version}-`);
|
|
212
|
+
self.default.databaseRulesCore = self.default.databaseRulesWhole.match(bem_allRulesRegex)[0];
|
|
211
213
|
};
|
|
212
214
|
|
|
213
215
|
Main.prototype.setup = async function () {
|
|
@@ -243,7 +245,7 @@ Main.prototype.setup = async function () {
|
|
|
243
245
|
|
|
244
246
|
self.getRulesFile();
|
|
245
247
|
|
|
246
|
-
self.default.
|
|
248
|
+
self.default.rulesVersionRegex = new RegExp(`///---version-${self.default.version}---///`)
|
|
247
249
|
// bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)).replace(/\./g, '\\.'), 'm' )
|
|
248
250
|
bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)), 'm' )
|
|
249
251
|
|
|
@@ -478,22 +480,26 @@ Main.prototype.setup = async function () {
|
|
|
478
480
|
|
|
479
481
|
// Update actual files
|
|
480
482
|
await self.test('update firestore rules file', function () {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
483
|
+
const exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.rules`);
|
|
484
|
+
const contents = jetpack.read(`${self.firebaseProjectPath}/firestore.rules`) || '';
|
|
485
|
+
const containsCore = contents.match(bem_allRulesRegex);
|
|
486
|
+
const matchesVersion = contents.match(self.default.rulesVersionRegex);
|
|
485
487
|
|
|
486
488
|
return (!!exists && !!containsCore && !!matchesVersion);
|
|
487
489
|
}, fix_firestoreRulesFile);
|
|
488
490
|
|
|
489
491
|
await self.test('update firestore indexes file', function () {
|
|
490
|
-
|
|
492
|
+
const exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.indexes.json`);
|
|
491
493
|
return (!!exists);
|
|
492
494
|
}, fix_firestoreIndexesFile);
|
|
493
495
|
|
|
494
496
|
await self.test('update realtime rules file', function () {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
+
const exists = jetpack.exists(`${self.firebaseProjectPath}/database.rules.json`);
|
|
498
|
+
const contents = jetpack.read(`${self.firebaseProjectPath}/database.rules.json`) || '';
|
|
499
|
+
const containsCore = contents.match(bem_allRulesRegex);
|
|
500
|
+
const matchesVersion = contents.match(self.default.rulesVersionRegex);
|
|
501
|
+
|
|
502
|
+
return (!!exists && !!containsCore && !!matchesVersion);
|
|
497
503
|
}, fix_realtimeRulesFile);
|
|
498
504
|
|
|
499
505
|
await self.test('update storage rules file', function () {
|
|
@@ -874,61 +880,94 @@ function fix_remoteconfigTemplate(self) {
|
|
|
874
880
|
|
|
875
881
|
function fix_firestoreRulesFile(self) {
|
|
876
882
|
return new Promise(function(resolve, reject) {
|
|
877
|
-
|
|
883
|
+
const name = 'firestore.rules'
|
|
884
|
+
let path = `${self.firebaseProjectPath}/${name}`;
|
|
878
885
|
let exists = jetpack.exists(path);
|
|
879
886
|
let contents = jetpack.read(path) || '';
|
|
880
887
|
|
|
881
888
|
if (!exists || !contents) {
|
|
882
|
-
log(chalk.yellow(`Writing new
|
|
889
|
+
log(chalk.yellow(`Writing new ${name} file...`));
|
|
883
890
|
jetpack.write(path, self.default.firestoreRulesWhole)
|
|
884
891
|
contents = jetpack.read(path) || '';
|
|
885
892
|
}
|
|
886
893
|
|
|
887
|
-
let hasTemplate = contents.match(
|
|
894
|
+
let hasTemplate = contents.match(bem_allRulesRegex) || contents.match(bem_allRulesBackupRegex);
|
|
888
895
|
|
|
889
896
|
if (!hasTemplate) {
|
|
890
|
-
log(chalk.red(`Could not find rules template. Please edit
|
|
897
|
+
log(chalk.red(`Could not find rules template. Please edit ${name} file and add`), chalk.red(`{{backend-manager}}`), chalk.red(`to it.`));
|
|
891
898
|
reject()
|
|
892
899
|
}
|
|
893
900
|
|
|
894
|
-
let matchesVersion = contents.match(self.default.
|
|
901
|
+
let matchesVersion = contents.match(self.default.rulesVersionRegex);
|
|
895
902
|
if (!matchesVersion) {
|
|
896
903
|
// console.log('replace wih', self.default.firestoreRulesCore);
|
|
897
|
-
contents = contents.replace(
|
|
898
|
-
contents = contents.replace(
|
|
904
|
+
contents = contents.replace(bem_allRulesBackupRegex, self.default.firestoreRulesCore)
|
|
905
|
+
contents = contents.replace(bem_allRulesRegex, self.default.firestoreRulesCore)
|
|
899
906
|
jetpack.write(path, contents)
|
|
900
|
-
log(chalk.yellow(`Writing core rules to
|
|
907
|
+
log(chalk.yellow(`Writing core rules to ${name} file...`));
|
|
901
908
|
}
|
|
902
909
|
resolve();
|
|
903
910
|
});
|
|
904
911
|
};
|
|
905
912
|
|
|
906
|
-
function
|
|
907
|
-
return new Promise(
|
|
908
|
-
const name = '
|
|
909
|
-
let
|
|
910
|
-
let exists = jetpack.exists(
|
|
913
|
+
function fix_realtimeRulesFile(self) {
|
|
914
|
+
return new Promise(function(resolve, reject) {
|
|
915
|
+
const name = 'database.rules.json'
|
|
916
|
+
let path = `${self.firebaseProjectPath}/${name}`;
|
|
917
|
+
let exists = jetpack.exists(path);
|
|
918
|
+
let contents = jetpack.read(path) || '';
|
|
911
919
|
|
|
912
|
-
if (!exists) {
|
|
920
|
+
if (!exists || !contents) {
|
|
913
921
|
log(chalk.yellow(`Writing new ${name} file...`));
|
|
914
|
-
|
|
922
|
+
jetpack.write(path, self.default.databaseRulesWhole)
|
|
923
|
+
contents = jetpack.read(path) || '';
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
let hasTemplate = contents.match(bem_allRulesRegex) || contents.match(bem_allRulesBackupRegex);
|
|
927
|
+
|
|
928
|
+
if (!hasTemplate) {
|
|
929
|
+
log(chalk.red(`Could not find rules template. Please edit ${name} file and add`), chalk.red(`{{backend-manager}}`), chalk.red(`to it.`));
|
|
930
|
+
reject()
|
|
915
931
|
}
|
|
916
932
|
|
|
933
|
+
let matchesVersion = contents.match(self.default.rulesVersionRegex);
|
|
934
|
+
if (!matchesVersion) {
|
|
935
|
+
// console.log('replace wih', self.default.databaseRulesCore);
|
|
936
|
+
contents = contents.replace(bem_allRulesBackupRegex, self.default.databaseRulesCore)
|
|
937
|
+
contents = contents.replace(bem_allRulesRegex, self.default.databaseRulesCore)
|
|
938
|
+
jetpack.write(path, contents)
|
|
939
|
+
log(chalk.yellow(`Writing core rules to ${name} file...`));
|
|
940
|
+
}
|
|
917
941
|
resolve();
|
|
918
942
|
});
|
|
919
943
|
};
|
|
920
944
|
|
|
921
|
-
function fix_realtimeRulesFile(self) {
|
|
922
|
-
|
|
923
|
-
|
|
945
|
+
// function fix_realtimeRulesFile(self) {
|
|
946
|
+
// return new Promise(function(resolve, reject) {
|
|
947
|
+
// const name = 'database.rules.json';
|
|
948
|
+
// let filePath = `${self.firebaseProjectPath}/${name}`;
|
|
949
|
+
// let exists = jetpack.exists(filePath);
|
|
950
|
+
// let contents = jetpack.read(filePath) || '';
|
|
951
|
+
//
|
|
952
|
+
// if (!exists) {
|
|
953
|
+
// log(chalk.yellow(`Writing new ${name} file...`));
|
|
954
|
+
// jetpack.write(filePath, jetpack.read(path.resolve(`${__dirname}/../../templates/${name}`)))
|
|
955
|
+
// contents = jetpack.read(filePath) || '';
|
|
956
|
+
// }
|
|
957
|
+
//
|
|
958
|
+
// resolve();
|
|
959
|
+
// });
|
|
960
|
+
// };
|
|
961
|
+
|
|
962
|
+
function fix_firestoreIndexesFile(self) {
|
|
963
|
+
return new Promise(async function(resolve, reject) {
|
|
964
|
+
const name = 'firestore.indexes.json';
|
|
924
965
|
let filePath = `${self.firebaseProjectPath}/${name}`;
|
|
925
966
|
let exists = jetpack.exists(filePath);
|
|
926
|
-
let contents = jetpack.read(filePath) || '';
|
|
927
967
|
|
|
928
968
|
if (!exists) {
|
|
929
969
|
log(chalk.yellow(`Writing new ${name} file...`));
|
|
930
|
-
|
|
931
|
-
contents = jetpack.read(filePath) || '';
|
|
970
|
+
await cmd_indexesGet(self, name, false);
|
|
932
971
|
}
|
|
933
972
|
|
|
934
973
|
resolve();
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
let _;
|
|
2
|
+
|
|
1
3
|
function Module() {
|
|
2
4
|
|
|
3
5
|
}
|
|
@@ -11,6 +13,8 @@ Module.prototype.main = function () {
|
|
|
11
13
|
|
|
12
14
|
return new Promise(async function(resolve, reject) {
|
|
13
15
|
|
|
16
|
+
_ = Manager.require('lodash')
|
|
17
|
+
|
|
14
18
|
if (!payload.user.roles.admin) {
|
|
15
19
|
return reject(assistant.errorManager(`Admin required.`, {code: 401, sentry: false, send: false, log: false}).error)
|
|
16
20
|
} else {
|
|
@@ -21,15 +25,11 @@ Module.prototype.main = function () {
|
|
|
21
25
|
let data = doc.data() || {};
|
|
22
26
|
let error = null;
|
|
23
27
|
|
|
24
|
-
await self.
|
|
28
|
+
await self.updateStats(data)
|
|
25
29
|
.catch(e => {
|
|
26
30
|
error = e;
|
|
27
31
|
})
|
|
28
32
|
|
|
29
|
-
await self.updateStats()
|
|
30
|
-
.catch(e => {
|
|
31
|
-
error = e;
|
|
32
|
-
})
|
|
33
33
|
|
|
34
34
|
if (error) {
|
|
35
35
|
return reject(assistant.errorManager(error, {code: 500, sentry: false, send: false, log: false}).error)
|
|
@@ -64,63 +64,64 @@ Module.prototype.fixStats = function (data) {
|
|
|
64
64
|
return new Promise(async function(resolve, reject) {
|
|
65
65
|
const stats = self.libraries.admin.firestore().doc(`meta/stats`);
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
return resolve();
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Module.prototype.updateStats = function (existingData) {
|
|
74
|
+
const self = this;
|
|
75
|
+
|
|
76
|
+
return new Promise(async function(resolve, reject) {
|
|
77
|
+
const stats = self.libraries.admin.firestore().doc(`meta/stats`);
|
|
78
|
+
const online = self.libraries.admin.database().ref(`gatherings/online`);
|
|
79
|
+
|
|
80
|
+
let error = null;
|
|
81
|
+
let update = {};
|
|
82
|
+
|
|
83
|
+
// Fix broken stats
|
|
84
|
+
if (!_.get(existingData, 'users.total', null)) {
|
|
71
85
|
await self.getAllUsers()
|
|
72
86
|
.then(r => {
|
|
73
|
-
|
|
87
|
+
_.set(update, 'users.total', r.length)
|
|
74
88
|
})
|
|
75
89
|
.catch(e => {
|
|
76
90
|
error = new Error(`Failed fixing stats: ${e}`);
|
|
77
|
-
self.assistant.error(error, {environment: 'production'});
|
|
78
|
-
})
|
|
79
|
-
await self.getAllSubscriptions()
|
|
80
|
-
.then(r => {
|
|
81
|
-
subscriptionsTotal = r
|
|
82
|
-
})
|
|
83
|
-
.catch(e => {
|
|
84
|
-
error = new Error(`Failed getting subscriptions: ${e}`);
|
|
85
|
-
self.assistant.error(error, {environment: 'production'});
|
|
86
91
|
})
|
|
92
|
+
}
|
|
87
93
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
await stats
|
|
92
|
-
.set({
|
|
93
|
-
users: {
|
|
94
|
-
total: usersTotal,
|
|
95
|
-
},
|
|
96
|
-
subscriptions: {
|
|
97
|
-
total: subscriptionsTotal,
|
|
98
|
-
},
|
|
99
|
-
}, { merge: true })
|
|
100
|
-
.catch(function (e) {
|
|
101
|
-
return reject(e);
|
|
102
|
-
})
|
|
94
|
+
if (error) {
|
|
95
|
+
return reject(error);
|
|
103
96
|
}
|
|
104
97
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
98
|
+
// Fetch new stats
|
|
99
|
+
await self.getAllNotifications()
|
|
100
|
+
.then(r => {
|
|
101
|
+
_.set(update, 'notifications.total', r)
|
|
102
|
+
})
|
|
103
|
+
.catch(e => {
|
|
104
|
+
error = new Error(`Failed getting notifications: ${e}`);
|
|
105
|
+
})
|
|
108
106
|
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
await self.getAllSubscriptions()
|
|
108
|
+
.then(r => {
|
|
109
|
+
_.set(update, 'subscriptions.total', r)
|
|
110
|
+
})
|
|
111
|
+
.catch(e => {
|
|
112
|
+
error = new Error(`Failed getting subscriptions: ${e}`);
|
|
113
|
+
})
|
|
111
114
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
let onlineCount = 0;
|
|
116
|
-
let error = null;
|
|
115
|
+
if (error) {
|
|
116
|
+
return reject(error);
|
|
117
|
+
}
|
|
117
118
|
|
|
118
119
|
await online
|
|
119
120
|
.once('value')
|
|
120
121
|
.then((snap) => {
|
|
121
122
|
let data = snap.val() || {};
|
|
122
123
|
let keys = Object.keys(data);
|
|
123
|
-
|
|
124
|
+
_.set(update, 'users.online', keys.length)
|
|
124
125
|
})
|
|
125
126
|
.catch(e => {
|
|
126
127
|
error = new Error(`Failed getting online users: ${e}`);
|
|
@@ -131,13 +132,9 @@ Module.prototype.updateStats = function () {
|
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
await stats
|
|
134
|
-
.set({
|
|
135
|
-
users: {
|
|
136
|
-
online: onlineCount
|
|
137
|
-
}
|
|
138
|
-
}, { merge: true })
|
|
135
|
+
.set(update, { merge: true })
|
|
139
136
|
.catch(function (e) {
|
|
140
|
-
return reject(`Failed getting stats: ${e}`);
|
|
137
|
+
return reject(new Error(`Failed getting stats: ${e}`));
|
|
141
138
|
})
|
|
142
139
|
|
|
143
140
|
return resolve();
|
|
@@ -156,7 +153,7 @@ Module.prototype.getAllUsers = function () {
|
|
|
156
153
|
});
|
|
157
154
|
}
|
|
158
155
|
|
|
159
|
-
Module.prototype.
|
|
156
|
+
Module.prototype.getAllNotifications = function () {
|
|
160
157
|
const self = this;
|
|
161
158
|
return new Promise(async function(resolve, reject) {
|
|
162
159
|
await self.libraries.admin.firestore().collection('notifications/subscriptions/all')
|
|
@@ -170,6 +167,33 @@ Module.prototype.getAllSubscriptions = function () {
|
|
|
170
167
|
});
|
|
171
168
|
}
|
|
172
169
|
|
|
170
|
+
Module.prototype.getAllSubscriptions = function () {
|
|
171
|
+
const self = this;
|
|
172
|
+
return new Promise(async function(resolve, reject) {
|
|
173
|
+
await self.libraries.admin.firestore().collection('users')
|
|
174
|
+
.where('plan.expires.timestampUNIX', '>=', new Date().getTime() / 1000)
|
|
175
|
+
.get()
|
|
176
|
+
.then(function(snapshot) {
|
|
177
|
+
let count = 0;
|
|
178
|
+
|
|
179
|
+
snapshot
|
|
180
|
+
.forEach((doc, i) => {
|
|
181
|
+
const data = doc.data();
|
|
182
|
+
const planId = _.get(data, 'plan.id', 'basic');
|
|
183
|
+
if (!['', 'basic', 'free'].includes(planId)) {
|
|
184
|
+
count++;
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return resolve(count);
|
|
189
|
+
})
|
|
190
|
+
.catch(function(e) {
|
|
191
|
+
return reject(e)
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
173
197
|
function getUsersBatch(self, nextPageToken) {
|
|
174
198
|
return new Promise(async function(resolve, reject) {
|
|
175
199
|
self.libraries.admin.auth().listUsers(1000, nextPageToken)
|
|
@@ -29,7 +29,7 @@ Module.prototype.main = function () {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const postUrl =
|
|
32
|
+
const postUrl = `${Manager.config.brand.url}/blog/${payload.data.payload.url}`;
|
|
33
33
|
|
|
34
34
|
if (payload.data.payload.invoiceEmail && payload.data.payload.invoicePrice) {
|
|
35
35
|
// Create invoice
|
|
@@ -1,31 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"rules": {
|
|
3
|
+
///---backend-manager---///
|
|
4
|
+
///---version=0.0.0---///
|
|
5
|
+
|
|
6
|
+
// Gathering rules
|
|
3
7
|
"gatherings": {
|
|
4
8
|
".read": false,
|
|
5
9
|
".write": false,
|
|
6
|
-
"
|
|
7
|
-
".read": "
|
|
10
|
+
"$room": {
|
|
11
|
+
".read": "
|
|
12
|
+
(auth.uid != null && query.equalTo == auth.uid)
|
|
13
|
+
",
|
|
8
14
|
".write": false,
|
|
9
15
|
".indexOn": ["uid"],
|
|
10
|
-
"$
|
|
16
|
+
"$id": {
|
|
11
17
|
".read": "
|
|
12
|
-
// Allowed if user is
|
|
18
|
+
// Allowed if user is authenticated AND is the owner of the doc
|
|
13
19
|
(auth != null && auth.uid == data.child('uid').val())
|
|
20
|
+
// Allowed if uid is equal to the doc id [LEGACY FOR SOMIIBO]
|
|
21
|
+
|| (auth != null && auth.uid == $id)
|
|
22
|
+
// Allowed if user is not authenticated AND is the doc has no owner
|
|
23
|
+
|| (auth == null && (data.child('uid').val() == ''))
|
|
14
24
|
",
|
|
15
25
|
".write": "
|
|
16
|
-
// Allowed if the user is
|
|
26
|
+
// Allowed if the user is authenticated AND is the owner of the existing doc
|
|
17
27
|
(auth != null && auth.uid == data.child('uid').val())
|
|
18
|
-
// Allowed if the user is
|
|
28
|
+
// Allowed if the user is authenticated AND is the owner of the new doc
|
|
19
29
|
|| (auth != null && auth.uid == newData.child('uid').val())
|
|
20
|
-
|
|
21
|
-
|| (
|
|
22
|
-
|
|
30
|
+
// Allowed if the user is authenticated AND is the owner of the existing doc
|
|
31
|
+
|| (auth != null && auth.uid == data.child('uid').val())
|
|
32
|
+
// Allowed if uid is equal to the doc id [LEGACY FOR SOMIIBO]
|
|
33
|
+
|| (auth != null && auth.uid == $id)
|
|
34
|
+
// Allowed if the existing doc has no owner
|
|
23
35
|
|| (data.child('uid').val() == '')
|
|
24
36
|
// Allowed if the new doc has no owner
|
|
25
37
|
|| (newData.child('uid').val() == '')
|
|
38
|
+
// Allowed if it's a delete
|
|
39
|
+
|| (!newData.exists())
|
|
26
40
|
",
|
|
27
41
|
}
|
|
28
42
|
}
|
|
29
|
-
}
|
|
43
|
+
},
|
|
44
|
+
///---------end---------///
|
|
30
45
|
}
|
|
31
46
|
}
|