diff --git a/assets/openapi.json b/assets/openapi.json index f7bc123af..a06d0d782 100644 Binary files a/assets/openapi.json and b/assets/openapi.json differ diff --git a/assets/schemas.json b/assets/schemas.json index 3d4b7447d..f10afc4a4 100644 Binary files a/assets/schemas.json and b/assets/schemas.json differ diff --git a/src/api/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts index a1db91373..37767574d 100644 --- a/src/api/routes/channels/#channel_id/index.ts +++ b/src/api/routes/channels/#channel_id/index.ts @@ -17,7 +17,19 @@ */ import { route } from "@spacebar/api"; -import { Channel, ChannelDeleteEvent, ChannelUpdateEvent, Recipient, emitEvent, handleFile } from "@spacebar/util"; +import { + Channel, + ChannelDeleteEvent, + ChannelUpdateEvent, + Recipient, + emitEvent, + handleFile, + Config, + FieldError, + ErrorList, + ObjectErrorContent, + makeObjectErrorContent, +} from "@spacebar/util"; import { Request, Response, Router } from "express"; import { ChannelModifySchema, ChannelType } from "@spacebar/schemas"; @@ -174,6 +186,7 @@ router.patch( channel.available_tags = channel.available_tags.filter((_) => filter.has(_.id)); } } + if (payload.applied_tags) { if (channel.isThread()) { const parent = await Channel.findOneOrFail({ @@ -201,6 +214,19 @@ router.patch( if (payload.icon) payload.icon = await handleFile(`/channel-icons/${channel_id}`, payload.icon); + const channelLimits = Config.get().limits.channel; + + const errors: ErrorList = {}; + if (payload.name && (payload.name.length < 1 || payload.name.length > channelLimits.maxName)) + errors["name"] = makeObjectErrorContent("BASE_TYPE_BAD_LENGTH", `Channel name must be between 1 and ${channelLimits.maxName} characters`); + if (payload.topic !== undefined && payload.topic.length > channelLimits.maxTopic) + errors["topic"] = makeObjectErrorContent("BASE_TYPE_BAD_LENGTH", `Channel topic must be less than ${channelLimits.maxTopic} characters`); + if (payload.user_limit !== undefined && payload.user_limit < 0) errors["user_limit"] = makeObjectErrorContent("BASE_TYPE_BAD_VALUE", "User limit must be 0 or higher"); + + if (Object.keys(errors).length) { + throw new FieldError(400, "Invalid form body", errors); + } + channel.assign(payload); if (channel.thread_metadata) { if (payload.archived !== undefined) { diff --git a/src/schemas/uncategorised/ChannelModifySchema.ts b/src/schemas/uncategorised/ChannelModifySchema.ts index b83dc12e9..093da8e64 100644 --- a/src/schemas/uncategorised/ChannelModifySchema.ts +++ b/src/schemas/uncategorised/ChannelModifySchema.ts @@ -19,9 +19,6 @@ import { ChannelPermissionOverwriteType, ChannelType, TagCreateSchema } from "@spacebar/schemas"; export interface ChannelModifySchema { - /** - * @maxLength 100 - */ name?: string; type?: ChannelType; topic?: string; diff --git a/src/util/config/types/subconfigurations/limits/ChannelLimits.ts b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts index 266e6a327..6d5d28f86 100644 --- a/src/util/config/types/subconfigurations/limits/ChannelLimits.ts +++ b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts @@ -20,4 +20,5 @@ export class ChannelLimits { maxPins: number = 500; maxTopic: number = 1024; maxWebhooks: number = 100; + maxName: number = 32; } diff --git a/src/util/util/FieldError.ts b/src/util/util/FieldError.ts index eb91a0ecb..f0ba4aeed 100644 --- a/src/util/util/FieldError.ts +++ b/src/util/util/FieldError.ts @@ -28,6 +28,10 @@ export type ErrorList = Record; export type ErrorContent = { code: string; message: string }; export type ObjectErrorContent = { _errors: ErrorContent[] }; +export function makeObjectErrorContent(code: string, message: string): ObjectErrorContent { + return { _errors: [{ code, message }] }; +} + export function FieldErrors(fields: Record, errors?: ErrorObject[]) { const errorObj: ErrorList = {}; for (const [key, { message, code }] of Object.entries(fields)) {