forked from parse-community/parse-server
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGlobalConfigRouter.js
100 lines (94 loc) · 3.7 KB
/
GlobalConfigRouter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// global_config.js
import Parse from 'parse/node';
import PromiseRouter from '../PromiseRouter';
import * as middleware from '../middlewares';
import * as triggers from '../triggers';
const getConfigFromParams = params => {
const config = new Parse.Config();
for (const attr in params) {
config.attributes[attr] = Parse._decode(undefined, params[attr]);
}
return config;
};
export class GlobalConfigRouter extends PromiseRouter {
getGlobalConfig(req) {
return req.config.database
.find('_GlobalConfig', { objectId: '1' }, { limit: 1 })
.then(results => {
if (results.length != 1) {
// If there is no config in the database - return empty config.
return { response: { params: {} } };
}
const globalConfig = results[0];
if (!req.auth.isMaster && globalConfig.masterKeyOnly !== undefined) {
for (const param in globalConfig.params) {
if (globalConfig.masterKeyOnly[param]) {
delete globalConfig.params[param];
delete globalConfig.masterKeyOnly[param];
}
}
}
return {
response: {
params: globalConfig.params,
masterKeyOnly: globalConfig.masterKeyOnly,
},
};
});
}
async updateGlobalConfig(req) {
if (req.auth.isReadOnly) {
throw new Parse.Error(
Parse.Error.OPERATION_FORBIDDEN,
"read-only masterKey isn't allowed to update the config."
);
}
const params = req.body.params || {};
const masterKeyOnly = req.body?.masterKeyOnly || {};
// Transform in dot notation to make sure it works
const update = Object.keys(params).reduce((acc, key) => {
acc[`params.${key}`] = params[key];
acc[`masterKeyOnly.${key}`] = masterKeyOnly[key] || false;
return acc;
}, {});
const className = triggers.getClassName(Parse.Config);
const hasBeforeSaveHook = triggers.triggerExists(className, triggers.Types.beforeSave, req.config.applicationId);
const hasAfterSaveHook = triggers.triggerExists(className, triggers.Types.afterSave, req.config.applicationId);
let originalConfigObject;
let updatedConfigObject;
const configObject = new Parse.Config();
configObject.attributes = params;
const results = await req.config.database.find('_GlobalConfig', { objectId: '1' }, { limit: 1 });
const isNew = results.length !== 1;
if (!isNew && (hasBeforeSaveHook || hasAfterSaveHook)) {
originalConfigObject = getConfigFromParams(results[0].params);
}
try {
await triggers.maybeRunGlobalConfigTrigger(triggers.Types.beforeSave, req.auth, configObject, originalConfigObject, req.config, req.context);
if (isNew) {
await req.config.database.update('_GlobalConfig', { objectId: '1' }, update, { upsert: true }, true)
updatedConfigObject = configObject;
} else {
const result = await req.config.database.update('_GlobalConfig', { objectId: '1' }, update, {}, true);
updatedConfigObject = getConfigFromParams(result.params);
}
await triggers.maybeRunGlobalConfigTrigger(triggers.Types.afterSave, req.auth, updatedConfigObject, originalConfigObject, req.config, req.context);
return { response: { result: true } }
} catch (err) {
const error = triggers.resolveError(err, {
code: Parse.Error.SCRIPT_FAILED,
message: 'Script failed. Unknown error.',
});
throw error;
}
}
mountRoutes() {
this.route('GET', '/config', req => {
return this.getGlobalConfig(req);
});
this.route('PUT', '/config', middleware.promiseEnforceMasterKeyAccess, req => {
return this.updateGlobalConfig(req);
});
}
}
export default GlobalConfigRouter;