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:
parent
3f918f9dcc
commit
e1345e4e29
3 changed files with 76 additions and 21 deletions
|
@ -1,6 +1,19 @@
|
||||||
import { Entity, PrimaryColumn, Index, Column } from "typeorm";
|
import { Entity, PrimaryColumn, Index, Column } from "typeorm";
|
||||||
import { id } from "../id.js";
|
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()
|
@Entity()
|
||||||
export class Instance {
|
export class Instance {
|
||||||
@PrimaryColumn(id())
|
@PrimaryColumn(id())
|
||||||
|
@ -20,7 +33,7 @@ export class Instance {
|
||||||
*/
|
*/
|
||||||
@Index({ unique: true })
|
@Index({ unique: true })
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 512,
|
length: MAX_LENGTH_INSTANCE.host,
|
||||||
comment: "The host of the Instance.",
|
comment: "The host of the Instance.",
|
||||||
})
|
})
|
||||||
public host: string;
|
public host: string;
|
||||||
|
@ -107,14 +120,14 @@ export class Instance {
|
||||||
public isSuspended: boolean;
|
public isSuspended: boolean;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: MAX_LENGTH_INSTANCE.softwareName,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
comment: "The software of the Instance.",
|
comment: "The software of the Instance.",
|
||||||
})
|
})
|
||||||
public softwareName: string | null;
|
public softwareName: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: MAX_LENGTH_INSTANCE.softwareVersion,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public softwareVersion: string | null;
|
public softwareVersion: string | null;
|
||||||
|
@ -125,43 +138,43 @@ export class Instance {
|
||||||
public openRegistrations: boolean | null;
|
public openRegistrations: boolean | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: MAX_LENGTH_INSTANCE.name,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public name: string | null;
|
public name: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 4096,
|
length: MAX_LENGTH_INSTANCE.description,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 128,
|
length: MAX_LENGTH_INSTANCE.maintainerName,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public maintainerName: string | null;
|
public maintainerName: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 256,
|
length: MAX_LENGTH_INSTANCE.maintainerEmail,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public maintainerEmail: string | null;
|
public maintainerEmail: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 4096,
|
length: MAX_LENGTH_INSTANCE.iconUrl,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public iconUrl: string | null;
|
public iconUrl: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 4096,
|
length: MAX_LENGTH_INSTANCE.faviconUrl,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public faviconUrl: string | null;
|
public faviconUrl: string | null;
|
||||||
|
|
||||||
@Column("varchar", {
|
@Column("varchar", {
|
||||||
length: 64,
|
length: MAX_LENGTH_INSTANCE.themeColor,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
public themeColor: string | null;
|
public themeColor: string | null;
|
||||||
|
|
|
@ -3,7 +3,10 @@ import { Window } from "happy-dom";
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import tinycolor from "tinycolor2";
|
import tinycolor from "tinycolor2";
|
||||||
import { getJson, getAgentByUrl } from "@/misc/fetch.js";
|
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 { Instances } from "@/models/index.js";
|
||||||
import { getFetchInstanceMetadataLock } from "@/misc/app-lock.js";
|
import { getFetchInstanceMetadataLock } from "@/misc/app-lock.js";
|
||||||
import Logger from "@/services/logger.js";
|
import Logger from "@/services/logger.js";
|
||||||
|
@ -53,26 +56,52 @@ export async function fetchInstanceMetadata(
|
||||||
} as Record<string, any>;
|
} as Record<string, any>;
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
updates.softwareName = info.software?.name?.toLowerCase() || null;
|
updates.softwareName =
|
||||||
updates.softwareVersion = info.software?.version;
|
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.openRegistrations = info.openRegistrations;
|
||||||
updates.maintainerName = info.metadata
|
updates.maintainerName = info.metadata
|
||||||
? info.metadata.maintainer
|
? info.metadata.maintainer
|
||||||
? info.metadata.maintainer.name || null
|
? info.metadata.maintainer.name?.substring(
|
||||||
|
0,
|
||||||
|
MAX_LENGTH_INSTANCE.maintainerName,
|
||||||
|
) || null
|
||||||
: null
|
: null
|
||||||
: null;
|
: null;
|
||||||
updates.maintainerEmail = info.metadata
|
updates.maintainerEmail = info.metadata
|
||||||
? info.metadata.maintainer
|
? info.metadata.maintainer
|
||||||
? info.metadata.maintainer.email || null
|
? info.metadata.maintainer.email?.substring(
|
||||||
|
0,
|
||||||
|
MAX_LENGTH_INSTANCE.maintainerEmail,
|
||||||
|
) || null
|
||||||
: null
|
: null
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name) updates.name = name;
|
if (name) updates.name = name.substring(0, MAX_LENGTH_INSTANCE.name);
|
||||||
if (description) updates.description = description;
|
if (description)
|
||||||
if (icon || favicon) updates.iconUrl = icon || favicon;
|
updates.description = description.substring(
|
||||||
if (favicon) updates.faviconUrl = favicon;
|
0,
|
||||||
if (themeColor) updates.themeColor = themeColor;
|
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);
|
await Instances.update(instance.id, updates);
|
||||||
|
|
||||||
|
|
|
@ -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 { Instances } from "@/models/index.js";
|
||||||
import { genId } from "@/misc/gen-id.js";
|
import { genId } from "@/misc/gen-id.js";
|
||||||
import { toPuny } from "@/misc/convert-host.js";
|
import { toPuny } from "@/misc/convert-host.js";
|
||||||
import { Cache } from "@/misc/cache.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);
|
const cache = new Cache<Instance>("registerOrFetchInstanceDoc", 60 * 60);
|
||||||
|
|
||||||
export async function registerOrFetchInstanceDoc(
|
export async function registerOrFetchInstanceDoc(
|
||||||
|
@ -11,6 +16,14 @@ export async function registerOrFetchInstanceDoc(
|
||||||
): Promise<Instance> {
|
): Promise<Instance> {
|
||||||
const _host = toPuny(host);
|
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);
|
const cached = await cache.get(_host);
|
||||||
if (cached) return cached;
|
if (cached) return cached;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue