diff --git a/assets/openapi.json b/assets/openapi.json
index 5d461364..6bf6f922 100644
--- a/assets/openapi.json
+++ b/assets/openapi.json
@@ -171,6 +171,301 @@
"token_type"
]
},
+ "StoredEmailResponse": {
+ "type": "object",
+ "properties": {
+ "Content-Type": {
+ "type": "string"
+ },
+ "From": {
+ "type": "string"
+ },
+ "Message-Id": {
+ "type": "string"
+ },
+ "Mime-Version": {
+ "type": "string"
+ },
+ "Subject": {
+ "type": "string"
+ },
+ "To": {
+ "type": "string"
+ },
+ "sender": {
+ "type": "string"
+ },
+ "recipients": {
+ "type": "string"
+ },
+ "from": {
+ "type": "string"
+ },
+ "subject": {
+ "type": "string"
+ },
+ "body-html": {
+ "type": "string"
+ },
+ "body-plain": {
+ "type": "string"
+ },
+ "attachments": {
+ "type": "array",
+ "items": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "content-type": {
+ "type": "string"
+ },
+ "size": {
+ "type": "integer"
+ },
+ "url": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "content-type",
+ "name",
+ "size",
+ "url"
+ ]
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 1
+ },
+ "content-id-map": {
+ "type": "object",
+ "properties": {},
+ "additionalProperties": true
+ },
+ "message-headers": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "string"
+ }
+ ],
+ "minItems": 2,
+ "maxItems": 2
+ }
+ },
+ "stripped-html": {
+ "type": "string"
+ },
+ "stripped-text": {
+ "type": "string"
+ },
+ "stripped-signature": {
+ "type": "string"
+ },
+ "Content-Transfer-Encoding": {
+ "type": "string"
+ },
+ "X-Mailgun-Tag": {
+ "type": "string"
+ },
+ "X-Mailgun-Template-Name": {
+ "type": "string"
+ },
+ "X-Mailgun-Template-Variables": {
+ "type": "string"
+ },
+ "X-Mailgun-Deliver-By": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "Content-Type",
+ "From",
+ "Message-Id",
+ "Mime-Version",
+ "Subject",
+ "To",
+ "body-html",
+ "body-plain",
+ "message-headers",
+ "recipients",
+ "sender",
+ "stripped-html",
+ "stripped-signature",
+ "stripped-text"
+ ]
+ },
+ "MessagesQueueStatusAPIResponse": {
+ "type": "object",
+ "properties": {
+ "regular": {
+ "type": "object",
+ "properties": {
+ "is_disabled": {
+ "type": "boolean"
+ },
+ "disabled": {
+ "type": "object",
+ "properties": {
+ "until": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "reason",
+ "until"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "disabled",
+ "is_disabled"
+ ]
+ },
+ "scheduled": {
+ "type": "object",
+ "properties": {
+ "is_disabled": {
+ "type": "boolean"
+ },
+ "disabled": {
+ "type": "object",
+ "properties": {
+ "until": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "reason",
+ "until"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "disabled",
+ "is_disabled"
+ ]
+ }
+ },
+ "required": [
+ "regular",
+ "scheduled"
+ ]
+ },
+ "SubaccountSendingLimitResponse": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "integer"
+ },
+ "current": {
+ "type": "integer"
+ },
+ "period": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "current",
+ "limit",
+ "period"
+ ]
+ },
+ "SubaccountSetSendingLimitResponse": {
+ "type": "object",
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "success"
+ ]
+ },
+ "SubaccountDestroyResponse": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "message"
+ ]
+ },
+ "ActivateDomainKeyResponse": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "authority": {
+ "type": "string"
+ },
+ "selector": {
+ "type": "string"
+ },
+ "active": {
+ "type": "boolean"
+ },
+ "status": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "active",
+ "authority",
+ "message",
+ "selector",
+ "status"
+ ]
+ },
+ "DeactivateDomainKeyResponse": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "authority": {
+ "type": "string"
+ },
+ "selector": {
+ "type": "string"
+ },
+ "active": {
+ "type": "boolean"
+ },
+ "status": {
+ "type": "integer"
+ }
+ },
+ "required": [
+ "active",
+ "authority",
+ "message",
+ "selector",
+ "status"
+ ]
+ },
"FieldErrorResponse": {
"type": "object",
"properties": {
@@ -1724,6 +2019,12 @@
"region": {
"type": "string"
},
+ "features": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"icon": {
"type": "string",
"nullable": true
@@ -1751,12 +2052,6 @@
"description": {
"type": "string"
},
- "features": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"verification_level": {
"type": "integer"
},
@@ -2115,6 +2410,15 @@
"InstanceDomainsResponse": {
"type": "object",
"properties": {
+ "admin": {
+ "type": "string"
+ },
+ "api": {
+ "type": "string"
+ },
+ "apiEndpoint": {
+ "type": "string"
+ },
"cdn": {
"type": "string"
},
@@ -2123,12 +2427,10 @@
},
"defaultApiVersion": {
"type": "string"
- },
- "apiEndpoint": {
- "type": "string"
}
},
"required": [
+ "api",
"apiEndpoint",
"cdn",
"defaultApiVersion",
@@ -2543,6 +2845,12 @@
"id": {
"type": "string"
},
+ "features": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"icon": {
"type": "string"
},
@@ -2602,12 +2910,6 @@
"description": {
"type": "string"
},
- "features": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"verification_level": {
"type": "integer"
},
@@ -2823,6 +3125,9 @@
"flags": {
"type": "integer"
},
+ "disabled": {
+ "type": "boolean"
+ },
"verified": {
"type": "boolean"
},
@@ -2890,9 +3195,6 @@
"premium_usage_flags": {
"type": "integer"
},
- "disabled": {
- "type": "boolean"
- },
"settings": {
"$ref": "#/components/schemas/UserSettingsSchema"
}
@@ -2950,6 +3252,9 @@
"flags": {
"type": "integer"
},
+ "disabled": {
+ "type": "boolean"
+ },
"verified": {
"type": "boolean"
},
@@ -3017,9 +3322,6 @@
"premium_usage_flags": {
"type": "integer"
},
- "disabled": {
- "type": "boolean"
- },
"settings": {
"$ref": "#/components/schemas/UserSettingsSchema"
}
@@ -3316,6 +3618,12 @@
"region": {
"type": "string"
},
+ "features": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"icon": {
"type": "string",
"nullable": true
@@ -3343,12 +3651,6 @@
"description": {
"type": "string"
},
- "features": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"verification_level": {
"type": "integer"
},
@@ -11842,7 +12144,7 @@
"length": {
"type": "integer"
},
- "__@unscopables@700": {
+ "__@unscopables@698": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
@@ -11971,17 +12273,17 @@
"remove": {
"type": "boolean"
},
- "__@iterator@698": {
+ "__@iterator@696": {
"type": "boolean"
},
- "__@unscopables@700": {
+ "__@unscopables@698": {
"type": "boolean"
}
}
}
},
"required": [
- "__@unscopables@700",
+ "__@unscopables@698",
"length"
]
},
@@ -15347,12 +15649,6 @@
},
"tags": [
"updates"
- ],
- "x-badges": [
- {
- "label": "Spacebar-only",
- "color": "red"
- }
]
}
},
diff --git a/assets/schemas.json b/assets/schemas.json
index e73e88c8..4d3646d6 100644
--- a/assets/schemas.json
+++ b/assets/schemas.json
@@ -152,6 +152,315 @@
],
"$schema": "http://json-schema.org/draft-07/schema#"
},
+ "StoredEmailResponse": {
+ "type": "object",
+ "properties": {
+ "Content-Type": {
+ "type": "string"
+ },
+ "From": {
+ "type": "string"
+ },
+ "Message-Id": {
+ "type": "string"
+ },
+ "Mime-Version": {
+ "type": "string"
+ },
+ "Subject": {
+ "type": "string"
+ },
+ "To": {
+ "type": "string"
+ },
+ "sender": {
+ "type": "string"
+ },
+ "recipients": {
+ "type": "string"
+ },
+ "from": {
+ "type": "string"
+ },
+ "subject": {
+ "type": "string"
+ },
+ "body-html": {
+ "type": "string"
+ },
+ "body-plain": {
+ "type": "string"
+ },
+ "attachments": {
+ "type": "array",
+ "items": [
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "content-type": {
+ "type": "string"
+ },
+ "size": {
+ "type": "integer"
+ },
+ "url": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "content-type",
+ "name",
+ "size",
+ "url"
+ ]
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 1
+ },
+ "content-id-map": {
+ "type": "object",
+ "properties": {},
+ "additionalProperties": true
+ },
+ "message-headers": {
+ "type": "array",
+ "items": {
+ "type": "array",
+ "items": [
+ {
+ "type": "string"
+ },
+ {
+ "type": "string"
+ }
+ ],
+ "minItems": 2,
+ "maxItems": 2
+ }
+ },
+ "stripped-html": {
+ "type": "string"
+ },
+ "stripped-text": {
+ "type": "string"
+ },
+ "stripped-signature": {
+ "type": "string"
+ },
+ "Content-Transfer-Encoding": {
+ "type": "string"
+ },
+ "X-Mailgun-Tag": {
+ "type": "string"
+ },
+ "X-Mailgun-Template-Name": {
+ "type": "string"
+ },
+ "X-Mailgun-Template-Variables": {
+ "type": "string"
+ },
+ "X-Mailgun-Deliver-By": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "Content-Type",
+ "From",
+ "Message-Id",
+ "Mime-Version",
+ "Subject",
+ "To",
+ "body-html",
+ "body-plain",
+ "message-headers",
+ "recipients",
+ "sender",
+ "stripped-html",
+ "stripped-signature",
+ "stripped-text"
+ ],
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
+ "MessagesQueueStatusAPIResponse": {
+ "type": "object",
+ "properties": {
+ "regular": {
+ "type": "object",
+ "properties": {
+ "is_disabled": {
+ "type": "boolean"
+ },
+ "disabled": {
+ "type": "object",
+ "properties": {
+ "until": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "reason",
+ "until"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "disabled",
+ "is_disabled"
+ ]
+ },
+ "scheduled": {
+ "type": "object",
+ "properties": {
+ "is_disabled": {
+ "type": "boolean"
+ },
+ "disabled": {
+ "type": "object",
+ "properties": {
+ "until": {
+ "type": "string"
+ },
+ "reason": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "reason",
+ "until"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "disabled",
+ "is_disabled"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "regular",
+ "scheduled"
+ ],
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
+ "SubaccountSendingLimitResponse": {
+ "type": "object",
+ "properties": {
+ "limit": {
+ "type": "integer"
+ },
+ "current": {
+ "type": "integer"
+ },
+ "period": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "current",
+ "limit",
+ "period"
+ ],
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
+ "SubaccountSetSendingLimitResponse": {
+ "type": "object",
+ "properties": {
+ "success": {
+ "type": "boolean"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "success"
+ ],
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
+ "SubaccountDestroyResponse": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "message"
+ ],
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
+ "ActivateDomainKeyResponse": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "authority": {
+ "type": "string"
+ },
+ "selector": {
+ "type": "string"
+ },
+ "active": {
+ "type": "boolean"
+ },
+ "status": {
+ "type": "integer"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "active",
+ "authority",
+ "message",
+ "selector",
+ "status"
+ ],
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
+ "DeactivateDomainKeyResponse": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
+ },
+ "authority": {
+ "type": "string"
+ },
+ "selector": {
+ "type": "string"
+ },
+ "active": {
+ "type": "boolean"
+ },
+ "status": {
+ "type": "integer"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "active",
+ "authority",
+ "message",
+ "selector",
+ "status"
+ ],
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
"FieldErrorResponse": {
"type": "object",
"properties": {
@@ -1784,6 +2093,12 @@
"region": {
"type": "string"
},
+ "features": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"icon": {
"type": [
"null",
@@ -1817,12 +2132,6 @@
"description": {
"type": "string"
},
- "features": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"verification_level": {
"type": "integer"
},
@@ -2205,6 +2514,15 @@
"InstanceDomainsResponse": {
"type": "object",
"properties": {
+ "admin": {
+ "type": "string"
+ },
+ "api": {
+ "type": "string"
+ },
+ "apiEndpoint": {
+ "type": "string"
+ },
"cdn": {
"type": "string"
},
@@ -2213,13 +2531,11 @@
},
"defaultApiVersion": {
"type": "string"
- },
- "apiEndpoint": {
- "type": "string"
}
},
"additionalProperties": false,
"required": [
+ "api",
"apiEndpoint",
"cdn",
"defaultApiVersion",
@@ -2668,6 +2984,12 @@
"id": {
"type": "string"
},
+ "features": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"icon": {
"type": "string"
},
@@ -2731,12 +3053,6 @@
"description": {
"type": "string"
},
- "features": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"verification_level": {
"type": "integer"
},
@@ -2960,6 +3276,9 @@
"flags": {
"type": "integer"
},
+ "disabled": {
+ "type": "boolean"
+ },
"verified": {
"type": "boolean"
},
@@ -3027,9 +3346,6 @@
"premium_usage_flags": {
"type": "integer"
},
- "disabled": {
- "type": "boolean"
- },
"settings": {
"$ref": "#/definitions/UserSettingsSchema"
}
@@ -3092,6 +3408,9 @@
"flags": {
"type": "integer"
},
+ "disabled": {
+ "type": "boolean"
+ },
"verified": {
"type": "boolean"
},
@@ -3159,9 +3478,6 @@
"premium_usage_flags": {
"type": "integer"
},
- "disabled": {
- "type": "boolean"
- },
"settings": {
"$ref": "#/definitions/UserSettingsSchema"
}
@@ -3488,6 +3804,12 @@
"region": {
"type": "string"
},
+ "features": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
"icon": {
"type": [
"null",
@@ -3521,12 +3843,6 @@
"description": {
"type": "string"
},
- "features": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
"verification_level": {
"type": "integer"
},
@@ -12580,7 +12896,7 @@
"length": {
"type": "integer"
},
- "__@unscopables@700": {
+ "__@unscopables@698": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
@@ -12709,17 +13025,17 @@
"remove": {
"type": "boolean"
},
- "__@iterator@698": {
+ "__@iterator@696": {
"type": "boolean"
},
- "__@unscopables@700": {
+ "__@unscopables@698": {
"type": "boolean"
}
}
}
},
"required": [
- "__@unscopables@700",
+ "__@unscopables@698",
"length"
]
},
diff --git a/src/util/util/Config.ts b/src/util/util/Config.ts
index 2fd9c0fb..a79c908d 100644
--- a/src/util/util/Config.ts
+++ b/src/util/util/Config.ts
@@ -54,7 +54,9 @@ export class Config {
config = OrmUtils.mergeDeep({}, { ...new ConfigValue() }, config);
- return this.set(config);
+ await this.set(config);
+ validateFinalConfig(config);
+ return config;
};
public static get() {
if (!config) {
@@ -169,3 +171,38 @@ const validateConfig = async () => {
return config;
};
+
+function validateFinalConfig(config: ConfigValue) {
+ let hasErrors = false;
+ function assertConfig(path: string, condition: (val: any) => boolean, recommendedValue: string) {
+ // _ to separate keys
+ const keys = path.split("_");
+ let obj: any = config;
+
+ for (const key of keys) {
+ if (obj == null || !(key in obj)) {
+ console.warn(`[Config] Missing config value for '${path}'. Recommended value: ${recommendedValue}`);
+ return;
+ }
+ obj = obj[key];
+ }
+
+ if (!condition(obj)) {
+ console.warn(`[Config] Invalid config value for '${path}': ${obj}. Recommended value: ${recommendedValue}`);
+ hasErrors = true;
+ }
+ }
+
+ assertConfig("api_endpointPublic", v => v != null, "A valid public API endpoint URL, ex. \"http://localhost:3001/api/v9\"");
+ assertConfig("cdn_endpointPublic", v => v != null, "A valid public CDN endpoint URL, ex. \"http://localhost:3002/\"");
+ assertConfig("cdn_endpointPrivate", v => v != null, "A valid private CDN endpoint URL, ex. \"http://localhost:3002/\" - must be routable from the API server!");
+ assertConfig("gateway_endpointPublic", v => v != null, "A valid public gateway endpoint URL, ex. \"ws://localhost:3003/\"");
+
+ if (hasErrors) {
+ console.error(
+ "[Config] Your config has invalid values. Fix them first https://docs.spacebar.chat/setup/server/configuration",
+ );
+ console.error("[Config] Hint: if you're just testing with bundle (`npm run start`), you can set all endpoint URLs to [proto]://localhost:3001");
+ process.exit(1);
+ } else console.log("[Config] Configuration validated successfully.");
+}
\ No newline at end of file
|