diff --git a/packages/backend/src/models/entities/instance.ts b/packages/backend/src/models/entities/instance.ts index ab7b2fa456..afdedd2d3f 100644 --- a/packages/backend/src/models/entities/instance.ts +++ b/packages/backend/src/models/entities/instance.ts @@ -1,6 +1,19 @@ import { Entity, PrimaryColumn, Index, Column } from "typeorm"; import { id } from "../id.js"; +export const MAX_LENGTH_INSTANCE = { + host: 512, + softwareName: 64, + softwareVersion: 64, + name: 256, + description: 4096, + maintainerName: 128, + maintainerEmail: 256, + iconUrl: 4096, + faviconUrl: 4096, + themeColor: 64, +}; + @Entity() export class Instance { @PrimaryColumn(id()) @@ -20,7 +33,7 @@ export class Instance { */ @Index({ unique: true }) @Column("varchar", { - length: 512, + length: MAX_LENGTH_INSTANCE.host, comment: "The host of the Instance.", }) public host: string; @@ -107,14 +120,14 @@ export class Instance { public isSuspended: boolean; @Column("varchar", { - length: 64, + length: MAX_LENGTH_INSTANCE.softwareName, nullable: true, comment: "The software of the Instance.", }) public softwareName: string | null; @Column("varchar", { - length: 64, + length: MAX_LENGTH_INSTANCE.softwareVersion, nullable: true, }) public softwareVersion: string | null; @@ -125,43 +138,43 @@ export class Instance { public openRegistrations: boolean | null; @Column("varchar", { - length: 256, + length: MAX_LENGTH_INSTANCE.name, nullable: true, }) public name: string | null; @Column("varchar", { - length: 4096, + length: MAX_LENGTH_INSTANCE.description, nullable: true, }) public description: string | null; @Column("varchar", { - length: 128, + length: MAX_LENGTH_INSTANCE.maintainerName, nullable: true, }) public maintainerName: string | null; @Column("varchar", { - length: 256, + length: MAX_LENGTH_INSTANCE.maintainerEmail, nullable: true, }) public maintainerEmail: string | null; @Column("varchar", { - length: 4096, + length: MAX_LENGTH_INSTANCE.iconUrl, nullable: true, }) public iconUrl: string | null; @Column("varchar", { - length: 4096, + length: MAX_LENGTH_INSTANCE.faviconUrl, nullable: true, }) public faviconUrl: string | null; @Column("varchar", { - length: 64, + length: MAX_LENGTH_INSTANCE.themeColor, nullable: true, }) public themeColor: string | null; diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts index 6795db0690..18e6411e88 100644 --- a/packages/backend/src/services/fetch-instance-metadata.ts +++ b/packages/backend/src/services/fetch-instance-metadata.ts @@ -3,7 +3,10 @@ import { Window } from "happy-dom"; import fetch from "node-fetch"; import tinycolor from "tinycolor2"; import { getJson, getAgentByUrl } from "@/misc/fetch.js"; -import type { Instance } from "@/models/entities/instance.js"; +import { + type Instance, + MAX_LENGTH_INSTANCE, +} from "@/models/entities/instance.js"; import { Instances } from "@/models/index.js"; import { getFetchInstanceMetadataLock } from "@/misc/app-lock.js"; import Logger from "@/services/logger.js"; @@ -53,26 +56,52 @@ export async function fetchInstanceMetadata( } as Record; if (info) { - updates.softwareName = info.software?.name?.toLowerCase() || null; - updates.softwareVersion = info.software?.version; + updates.softwareName = + info.software?.name + ?.toLowerCase() + .substring(0, MAX_LENGTH_INSTANCE.softwareName) || null; + updates.softwareVersion = + info.software?.version?.substring( + 0, + MAX_LENGTH_INSTANCE.softwareVersion, + ) || null; updates.openRegistrations = info.openRegistrations; updates.maintainerName = info.metadata ? info.metadata.maintainer - ? info.metadata.maintainer.name || null + ? info.metadata.maintainer.name?.substring( + 0, + MAX_LENGTH_INSTANCE.maintainerName, + ) || null : null : null; updates.maintainerEmail = info.metadata ? info.metadata.maintainer - ? info.metadata.maintainer.email || null + ? info.metadata.maintainer.email?.substring( + 0, + MAX_LENGTH_INSTANCE.maintainerEmail, + ) || null : null : null; } - if (name) updates.name = name; - if (description) updates.description = description; - if (icon || favicon) updates.iconUrl = icon || favicon; - if (favicon) updates.faviconUrl = favicon; - if (themeColor) updates.themeColor = themeColor; + if (name) updates.name = name.substring(0, MAX_LENGTH_INSTANCE.name); + if (description) + updates.description = description.substring( + 0, + MAX_LENGTH_INSTANCE.description, + ); + if (icon || favicon) + updates.iconUrl = (icon || favicon)?.substring( + 0, + MAX_LENGTH_INSTANCE.iconUrl, + ); + if (favicon) + updates.faviconUrl = favicon.substring(0, MAX_LENGTH_INSTANCE.faviconUrl); + if (themeColor) + updates.themeColor = themeColor.substring( + 0, + MAX_LENGTH_INSTANCE.themeColor, + ); await Instances.update(instance.id, updates); diff --git a/packages/backend/src/services/register-or-fetch-instance-doc.ts b/packages/backend/src/services/register-or-fetch-instance-doc.ts index c0ead08190..be26d8689b 100644 --- a/packages/backend/src/services/register-or-fetch-instance-doc.ts +++ b/packages/backend/src/services/register-or-fetch-instance-doc.ts @@ -1,9 +1,14 @@ -import type { Instance } from "@/models/entities/instance.js"; +import { + type Instance, + MAX_LENGTH_INSTANCE, +} from "@/models/entities/instance.js"; import { Instances } from "@/models/index.js"; import { genId } from "@/misc/gen-id.js"; import { toPuny } from "@/misc/convert-host.js"; import { Cache } from "@/misc/cache.js"; +import Logger from "@/services/logger.js"; +const logger = new Logger("register-or-fetch-instance"); const cache = new Cache("registerOrFetchInstanceDoc", 60 * 60); export async function registerOrFetchInstanceDoc( @@ -11,6 +16,14 @@ export async function registerOrFetchInstanceDoc( ): Promise { const _host = toPuny(host); + if (_host.length > MAX_LENGTH_INSTANCE.host) { + logger.error( + `Instance host name must not be longer than ${MAX_LENGTH_INSTANCE.host} characters`, + ); + logger.error(`hostname: ${_host}`); + throw new Error("Instance host name is too long"); + } + const cached = await cache.get(_host); if (cached) return cached;