Newer
Older
percord / src / util / Config.ts
@Diego Magdaleno Diego Magdaleno on 18 May 2021 4 KB Config: Start working on the config refactor
import Ajv, {JTDSchemaType} from "ajv/dist/jtd"

export interface RateLimitOptions {
	count: number;
	timespan: number;
}

export interface DefaultOptions {
	general: {
		instance_id: string;
	};
	permissions: {
		user: {
			createGuilds: boolean;
		};
	};
	limits: {
		user: {
			maxGuilds: number;
			maxUsername: number;
			maxFriends: number;
		};
		guild: {
			maxRoles: number;
			maxMembers: number;
			maxChannels: number;
			maxChannelsInCategory: number;
			hideOfflineMember: number;
		};
		message: {
			characters: number;
			ttsCharacters: number;
			maxReactions: number;
			maxAttachmentSize: number;
			maxBulkDelete: number;
		};
		channel: {
			maxPins: number;
			maxTopic: number;
		};
		rate: {
			ip: {
				enabled: boolean;
				count: number;
				timespan: number;
			};
			routes: {
				auth?: {
					login?: RateLimitOptions;
					register?: RateLimitOptions;
				};
				channel?: string;
				// TODO: rate limit configuration for all routes
			};
		};
	};
	security: {
		jwtSecret: string;
		forwadedFor: string | null;
		captcha: {
			enabled: boolean;
			service: "recaptcha" | "hcaptcha" | null; // TODO: hcaptcha, custom
			sitekey: string | null;
			secret: string | null;
		};
	};
	login: {
		requireCaptcha: boolean;
	};
	register: {
		email: {
			required: boolean;
			allowlist: boolean;
			blocklist: boolean;
			domains: string[];
		};
		dateOfBirth: {
			required: boolean;
			minimum: number; // in years
		};
		requireCaptcha: boolean;
		requireInvite: boolean;
		allowNewRegistration: boolean;
		allowMultipleAccounts: boolean;
		password: {
			minLength: number;
			minNumbers: number;
			minUpperCase: number;
			minSymbols: number;
			blockInsecureCommonPasswords: boolean; // TODO: efficiently save password blocklist in database
		};
	};
}

const schema: JTDSchemaType<DefaultOptions, {rateLimitOptions: RateLimitOptions}> = {
	definitions: {
		rateLimitOptions: {
			properties: {
				count: {type: "int32"},
				timespan: {type: "int32"}
			}
		}
	},
	properties: {
		general: {
			properties: {
				instance_id: {type: "string"}
			}
		},
		permissions: {
			properties: {
				user: {
					properties: {
						createGuilds: {type: "boolean"}
					}
				}
			}
		},
		limits: {
			properties: {
				user: {
					properties: {
						maxGuilds: {type: "int32"},
						maxFriends: {type: "int32"},
						maxUsername: {type: "int32"}
					}
				},
				guild: {
					properties: {
						maxRoles: {type: "int32"},
						maxMembers: {type: "int32"},
						maxChannels: {type: "int32"},
						maxChannelsInCategory: {type: "int32"},
						hideOfflineMember: {type: "int32"}
					}
				},
				message: {
					properties: {
						characters: {type: "int32"},
						ttsCharacters: {type: "int32"},
						maxReactions: {type: "int32"},
						maxAttachmentSize: {type: "int32"},
						maxBulkDelete: {type: "int32"}
					}
				},
				channel: {
					properties: {
						maxPins: {type: "int32"},
						maxTopic: {type: "int32"},
					},
				},
				rate: {
					properties: {
						ip: {
							properties: {
								enabled: {type: "boolean"},
								count: {type: "int32"},
								timespan: {type: "int32"},
							}
						},
						routes: {
							optionalProperties: {
								auth: {
									optionalProperties: {
										login: {ref: 'rateLimitOptions'},
										register: {ref: 'rateLimitOptions'}
									}
								},
								channel: {type: "string"}
							}
						}
					}
				}
			}
		},
		security: {
			properties: {
				jwtSecret: {type: "string"},
				forwadedFor: {type: "string", nullable: true},
				captcha: {
					properties: {
						enabled: {type: "boolean"},
						service: {enum: ['hcaptcha', 'recaptcha'], nullable: true},
						sitekey: {type: "string", nullable: true},
						secret: {type: "string", nullable: true}
					}
				}
			}
		},
		login: {
			properties: {
				requireCaptcha: {type: "boolean"}
			}
		},
		register: {
			properties: {
				email: {
					properties: {
						required: {type: "boolean"},
						allowlist: {type: "boolean"},
						blocklist: {type: "boolean"},
						domains: { elements: {
							type: "string"
						}
					}
				}
			},
			dateOfBirth: {
				properties: {
					required: {type: "boolean"},
					minimum: {type: "int32"}
				}
			},
			requireCaptcha: {type: "boolean"},
			requireInvite: {type: "boolean"},
			allowNewRegistration: {type: "boolean"},
			allowMultipleAccounts: {type: "boolean"},
			password: {
				properties: {
					minLength: {type: "int32"},
					minNumbers: {type: "int32"},
					minUpperCase: {type: "int32"},
					minSymbols: {type: "int32"},
					blockInsecureCommonPasswords: {type: "boolean"}
				}
			}
		}
	}
}
}