diff --git a/src/api/routes/policies/instance/config.ts b/src/api/routes/policies/instance/config.ts new file mode 100755 index 00000000..0885e95d --- /dev/null +++ b/src/api/routes/policies/instance/config.ts @@ -0,0 +1,71 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { Config, getRights } from "@spacebar/util"; +import { Request, Response, Router } from "express"; + +const router = Router(); + +router.get( + "/", + route({ + responses: { + 200: { + body: "Object", + }, + }, + }), + async (req: Request, res: Response) => { + const general = Config.get(); + let outputtedConfig; + if (req.user_id) { + const rights = await getRights(req.user_id); + if (rights.has("OPERATOR")) outputtedConfig = general; + } else { + outputtedConfig = { + limits_user_maxGuilds: general.limits.user.maxGuilds, + limits_user_maxBio: general.limits.user.maxBio, + limits_guild_maxEmojis: general.limits.guild.maxEmojis, + limits_guild_maxRoles: general.limits.guild.maxRoles, + limits_message_maxCharacters: + general.limits.message.maxCharacters, + limits_message_maxAttachmentSize: + general.limits.message.maxAttachmentSize, + limits_message_maxEmbedDownloadSize: + general.limits.message.maxEmbedDownloadSize, + limits_channel_maxWebhooks: general.limits.channel.maxWebhooks, + register_dateOfBirth_requiredc: + general.register.dateOfBirth.required, + register_password_required: general.register.password.required, + register_disabled: general.register.disabled, + register_requireInvite: general.register.requireInvite, + register_allowNewRegistration: + general.register.allowNewRegistration, + register_allowMultipleAccounts: + general.register.allowMultipleAccounts, + guild_autoJoin_canLeave: general.guild.autoJoin.canLeave, + guild_autoJoin_guilds_x: general.guild.autoJoin.guilds, + register_email_required: general.register.email.required, + }; + } + res.send(outputtedConfig); + }, +); + +export default router; diff --git a/src/api/routes/webhooks/#webhook_id/#token/index.ts b/src/api/routes/webhooks/#webhook_id/#token/index.ts index aa73b3fe..aea9ba87 100644 --- a/src/api/routes/webhooks/#webhook_id/#token/index.ts +++ b/src/api/routes/webhooks/#webhook_id/#token/index.ts @@ -13,6 +13,7 @@ import { WebhooksUpdateEvent, WebhookUpdateSchema, handleFile, + ValidateName, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; @@ -350,16 +351,20 @@ router.patch( "application", ], }); - const channel_id = webhook.channel_id; if (!body.name && !body.avatar) { - throw new HTTPError("Empty messages are not allowed", 50006); + throw new HTTPError("Empty webhook updates are not allowed", 50006); } if (body.avatar) body.avatar = await handleFile( `/avatars/${webhook_id}`, body.avatar as string, ); + + if (body.name) { + ValidateName(body.name); + } + webhook.assign(body); await Promise.all([ diff --git a/src/api/routes/webhooks/#webhook_id/index.ts b/src/api/routes/webhooks/#webhook_id/index.ts index c27b4612..9e893346 100644 --- a/src/api/routes/webhooks/#webhook_id/index.ts +++ b/src/api/routes/webhooks/#webhook_id/index.ts @@ -10,6 +10,7 @@ import { Channel, handleFile, FieldErrors, + ValidateName, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; @@ -157,7 +158,7 @@ router.patch( throw DiscordApiErrors.UNKNOWN_WEBHOOK; if (!body.name && !body.avatar && !body.channel_id) { - throw new HTTPError("Empty messages are not allowed", 50006); + throw new HTTPError("Empty webhook updates are not allowed", 50006); } if (body.avatar) @@ -167,37 +168,7 @@ router.patch( ); if (body.name) { - const check_username = body.name.replace(/\s/g, ""); - if (!check_username) { - throw FieldErrors({ - username: { - code: "BASE_TYPE_REQUIRED", - message: req.t("common:field.BASE_TYPE_REQUIRED"), - }, - }); - } - - const { maxUsername } = Config.get().limits.user; - if ( - check_username.length > maxUsername || - check_username.length < 2 - ) { - throw FieldErrors({ - username: { - code: "BASE_TYPE_BAD_LENGTH", - message: `Must be between 2 and ${maxUsername} in length.`, - }, - }); - } - - const blockedContains = ["discord", "clyde", "spacebar"]; - for (const word of blockedContains) { - if (body.name.toLowerCase().includes(word)) { - return res.status(400).json({ - username: [`Username cannot contain "${word}"`], - }); - } - } + ValidateName(body.name); } const channel_id = body.channel_id || webhook.channel_id; diff --git a/src/util/util/NameValidation.ts b/src/util/util/NameValidation.ts new file mode 100755 index 00000000..857a2517 --- /dev/null +++ b/src/util/util/NameValidation.ts @@ -0,0 +1,51 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { Config } from "./Config"; +import { FieldErrors } from "./FieldError"; +import { HTTPError } from "lambert-server"; + +export function ValidateName(name: string) { + const check_username = name.replace(/\s/g, ""); + if (!check_username) { + throw FieldErrors({ + username: { + code: "BASE_TYPE_REQUIRED", + message: "common:field.BASE_TYPE_REQUIRED", + }, + }); + } + + const { maxUsername } = Config.get().limits.user; + if (check_username.length > maxUsername || check_username.length < 2) { + throw FieldErrors({ + username: { + code: "BASE_TYPE_BAD_LENGTH", + message: `Must be between 2 and ${maxUsername} in length.`, + }, + }); + } + + const blockedContains = ["discord", "clyde", "spacebar"]; + for (const word of blockedContains) { + if (name.toLowerCase().includes(word)) { + throw new HTTPError(`Username cannot contain "${word}"`, 400); + } + } + return name; +} diff --git a/src/util/util/index.ts b/src/util/util/index.ts index 10e09b5c..f55315e3 100644 --- a/src/util/util/index.ts +++ b/src/util/util/index.ts @@ -43,3 +43,4 @@ export * from "./TraverseDirectory"; export * from "./WebAuthn"; export * from "./Gifs"; export * from "./Application"; +export * from "./NameValidation";