parse_rust_server/routes/features.rs
1//! `GET /serverInfo`. Master-key gated.
2//!
3//! Upstream: `src/Routers/FeaturesRouter.js`. The `features` object is a static capability
4//! advertisement with three values read from config. Parse Dashboard reads it, so the key set
5//! and nesting are wire contract, not documentation.
6
7use serde_json::{json, Value as Json};
8
9use crate::config::{ServerConfig, REPORTED_PARSE_SERVER_VERSION};
10
11/// The response body. The master-key gate is applied by the dispatcher, not here.
12///
13/// The key set and nesting are transcribed from `FeaturesRouter` and are wire contract. The
14/// values are **not** transcribed: upstream hardcodes almost all of them to `true` because
15/// upstream implements them, and repeating that here would advertise hooks, a global config,
16/// cloud jobs, a log API and push, none of which have routes. Parse Dashboard renders its UI from
17/// this object, so a copied `true` becomes a control that 404s when a user clicks it. See
18/// `FeatureSupport` for the reasoning; each flag flips as its subsystem lands.
19pub fn server_info_body(config: &ServerConfig) -> Json {
20 let f = &config.features;
21 let features = json!({
22 "globalConfig": {
23 "create": f.global_config, "read": f.global_config,
24 "update": f.global_config, "delete": f.global_config,
25 },
26 "hooks": {
27 "create": f.hooks, "read": f.hooks, "update": f.hooks, "delete": f.hooks,
28 },
29 "cloudCode": { "jobs": f.cloud_code_jobs },
30 "logs": {
31 "level": f.logs, "size": f.logs, "order": f.logs, "until": f.logs, "from": f.logs,
32 },
33 "push": {
34 "immediatePush": config.has_push_support,
35 "scheduledPush": config.has_push_scheduled_support,
36 "storedPushData": config.has_push_support,
37 "pushAudiences": f.push_audiences,
38 "localization": f.push_audiences,
39 },
40 "schemas": {
41 "addField": f.schemas,
42 "removeField": f.schemas,
43 "addClass": f.schemas,
44 "removeClass": f.schemas,
45 "clearAllDataFromClass": f.schemas,
46 // Upstream ships this as `false` even with the schema API fully present, so it stays
47 // false here for both reasons and never follows `f.schemas`.
48 "exportClass": false,
49 "editClassLevelPermissions": f.schemas,
50 "editPointerPermissions": f.schemas,
51 },
52 "settings": { "securityCheck": config.security_check_enabled },
53 });
54
55 json!({
56 "features": features,
57 "parseServerVersion": REPORTED_PARSE_SERVER_VERSION,
58 })
59}