fix (backend): make sure that instance info fit in the database (close #10891)

I guess there is a better way to do this...
This commit is contained in:
naskya 2024-04-08 20:52:14 +09:00
parent 3f918f9dcc
commit e1345e4e29
No known key found for this signature in database
GPG Key ID: 712D413B3A9FED5C
3 changed files with 76 additions and 21 deletions

View File

@ -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;

View File

@ -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<string, any>;
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);

View File

@ -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<Instance>("registerOrFetchInstanceDoc", 60 * 60);
export async function registerOrFetchInstanceDoc(
@ -11,6 +16,14 @@ export async function registerOrFetchInstanceDoc(
): Promise<Instance> {
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;