mirror of
https://github.com/versia-pub/server.git
synced 2026-03-13 13:59:16 +01:00
refactor(config): ♻️ Redo config structure from scratch, simplify validation code, improve checks, add support for loading sensitive data from paths
This commit is contained in:
parent
d4afd84019
commit
54fd81f076
118 changed files with 3892 additions and 5291 deletions
|
|
@ -12,7 +12,7 @@ import {
|
|||
eq,
|
||||
inArray,
|
||||
} from "drizzle-orm";
|
||||
import { config } from "~/packages/config-manager/index.ts";
|
||||
import { config } from "~/config.ts";
|
||||
import { ApiError } from "../errors/api-error.ts";
|
||||
import { BaseInterface } from "./base.ts";
|
||||
import { User } from "./user.ts";
|
||||
|
|
@ -147,7 +147,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
const { ok, raw, data } = await requester
|
||||
.get(wellKnownUrl, {
|
||||
// @ts-expect-error Bun extension
|
||||
proxy: config.http.proxy.address,
|
||||
proxy: config.http.proxy_address,
|
||||
})
|
||||
.catch((e) => ({
|
||||
...(e as ResponseError).response,
|
||||
|
|
@ -204,7 +204,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
links: { rel: string; href: string }[];
|
||||
}>(wellKnownUrl, {
|
||||
// @ts-expect-error Bun extension
|
||||
proxy: config.http.proxy.address,
|
||||
proxy: config.http.proxy_address,
|
||||
})
|
||||
.catch((e) => ({
|
||||
...(
|
||||
|
|
@ -256,7 +256,7 @@ export class Instance extends BaseInterface<typeof Instances> {
|
|||
software: { version: string };
|
||||
}>(metadataUrl.href, {
|
||||
// @ts-expect-error Bun extension
|
||||
proxy: config.http.proxy.address,
|
||||
proxy: config.http.proxy_address,
|
||||
})
|
||||
.catch((e) => ({
|
||||
...(
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import {
|
|||
eq,
|
||||
inArray,
|
||||
} from "drizzle-orm";
|
||||
import { config } from "~/packages/config-manager/index.ts";
|
||||
import { config } from "~/config.ts";
|
||||
import { BaseInterface } from "./base.ts";
|
||||
import { Note } from "./note.ts";
|
||||
import { User } from "./user.ts";
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ import {
|
|||
inArray,
|
||||
} from "drizzle-orm";
|
||||
import sharp from "sharp";
|
||||
import { MediaBackendType } from "~/classes/config/schema.ts";
|
||||
import type { Attachment as AttachmentSchema } from "~/classes/schemas/attachment.ts";
|
||||
import { MediaBackendType } from "~/packages/config-manager/config.type";
|
||||
import { config } from "~/packages/config-manager/index.ts";
|
||||
import { config } from "~/config.ts";
|
||||
import { ApiError } from "../errors/api-error.ts";
|
||||
import { getMediaHash } from "../media/media-hasher.ts";
|
||||
import { MediaJobType, mediaQueue } from "../queues/media.ts";
|
||||
|
|
@ -135,11 +135,7 @@ export class Media extends BaseInterface<typeof Medias> {
|
|||
|
||||
switch (config.media.backend) {
|
||||
case MediaBackendType.Local: {
|
||||
const path = join(
|
||||
config.media.local_uploads_folder,
|
||||
hash,
|
||||
fileName,
|
||||
);
|
||||
const path = join(config.media.uploads_path, hash, fileName);
|
||||
|
||||
await write(path, file);
|
||||
|
||||
|
|
@ -154,7 +150,7 @@ export class Media extends BaseInterface<typeof Medias> {
|
|||
}
|
||||
|
||||
const client = new S3Client({
|
||||
endpoint: config.s3.endpoint,
|
||||
endpoint: config.s3.endpoint.origin,
|
||||
region: config.s3.region,
|
||||
bucket: config.s3.bucket_name,
|
||||
accessKeyId: config.s3.access_key,
|
||||
|
|
@ -260,21 +256,21 @@ export class Media extends BaseInterface<typeof Medias> {
|
|||
}
|
||||
|
||||
private static checkFile(file: File): void {
|
||||
if (file.size > config.validation.max_media_size) {
|
||||
if (file.size > config.validation.media.max_bytes) {
|
||||
throw new ApiError(
|
||||
413,
|
||||
`File too large, max size is ${config.validation.max_media_size} bytes`,
|
||||
`File too large, max size is ${config.validation.media.max_bytes} bytes`,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
config.validation.enforce_mime_types &&
|
||||
!config.validation.allowed_mime_types.includes(file.type)
|
||||
config.validation.media.allowed_mime_types.length > 0 &&
|
||||
!config.validation.media.allowed_mime_types.includes(file.type)
|
||||
) {
|
||||
throw new ApiError(
|
||||
415,
|
||||
`File type ${file.type} is not allowed`,
|
||||
`Allowed types: ${config.validation.allowed_mime_types.join(", ")}`,
|
||||
`Allowed types: ${config.validation.media.allowed_mime_types.join(", ")}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import {
|
|||
parseTextMentions,
|
||||
} from "~/classes/functions/status";
|
||||
import type { Status as StatusSchema } from "~/classes/schemas/status.ts";
|
||||
import { config } from "~/packages/config-manager";
|
||||
import { config } from "~/config.ts";
|
||||
import { DeliveryJobType, deliveryQueue } from "../queues/delivery.ts";
|
||||
import type { Status } from "../schemas/status.ts";
|
||||
import { Application } from "./application.ts";
|
||||
|
|
@ -594,7 +594,7 @@ export class Note extends BaseInterface<typeof Notes, NoteTypeWithRelations> {
|
|||
|
||||
const { data } = await requester.get(uri, {
|
||||
// @ts-expect-error Bun extension
|
||||
proxy: config.http.proxy.address,
|
||||
proxy: config.http.proxy_address,
|
||||
});
|
||||
|
||||
const note = await new EntityValidator().Note(data);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
eq,
|
||||
inArray,
|
||||
} from "drizzle-orm";
|
||||
import { config } from "~/packages/config-manager/index.ts";
|
||||
import { config } from "~/config.ts";
|
||||
import { BaseInterface } from "./base.ts";
|
||||
|
||||
type ReactionType = InferSelectModel<typeof Reactions> & {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
eq,
|
||||
inArray,
|
||||
} from "drizzle-orm";
|
||||
import { config } from "~/packages/config-manager/index.ts";
|
||||
import { config } from "~/config.ts";
|
||||
import { BaseInterface } from "./base.ts";
|
||||
|
||||
type RoleType = InferSelectModel<typeof Roles>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Notes, Notifications, Users } from "@versia/kit/tables";
|
||||
import { type SQL, gt } from "drizzle-orm";
|
||||
import { config } from "~/packages/config-manager";
|
||||
import { config } from "~/config.ts";
|
||||
import { Note } from "./note.ts";
|
||||
import { Notification } from "./notification.ts";
|
||||
import { User } from "./user.ts";
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ import {
|
|||
import { htmlToText } from "html-to-text";
|
||||
import { findManyUsers } from "~/classes/functions/user";
|
||||
import { searchManager } from "~/classes/search/search-manager";
|
||||
import { type Config, config } from "~/packages/config-manager";
|
||||
import { config } from "~/config.ts";
|
||||
import type { KnownEntity } from "~/types/api.ts";
|
||||
import { DeliveryJobType, deliveryQueue } from "../queues/delivery.ts";
|
||||
import { PushJobType, pushQueue } from "../queues/push.ts";
|
||||
|
|
@ -522,7 +522,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
});
|
||||
|
||||
// Also do push notifications
|
||||
if (config.notifications.push.enabled) {
|
||||
if (config.notifications.push) {
|
||||
await this.notifyPush(notification.id, type, relatedUser, note);
|
||||
}
|
||||
}
|
||||
|
|
@ -603,7 +603,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
}
|
||||
|
||||
if (instance.data.protocol === "activitypub") {
|
||||
if (!config.federation.bridge.enabled) {
|
||||
if (!config.federation.bridge) {
|
||||
throw new Error("ActivityPub bridge is not enabled");
|
||||
}
|
||||
|
||||
|
|
@ -627,7 +627,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
const requester = await User.getFederationRequester();
|
||||
const output = await requester.get<Partial<VersiaUser>>(uri, {
|
||||
// @ts-expect-error Bun extension
|
||||
proxy: config.http.proxy.address,
|
||||
proxy: config.http.proxy_address,
|
||||
});
|
||||
|
||||
const { data: json } = output;
|
||||
|
|
@ -815,10 +815,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
|
||||
/**
|
||||
* Get the user's avatar in raw URL format
|
||||
* @param config The config to use
|
||||
* @returns The raw URL for the user's avatar
|
||||
*/
|
||||
public getAvatarUrl(config: Config): URL {
|
||||
public getAvatarUrl(): URL {
|
||||
if (!this.avatar) {
|
||||
return (
|
||||
config.defaults.avatar ||
|
||||
|
|
@ -912,10 +911,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
|
||||
/**
|
||||
* Get the user's header in raw URL format
|
||||
* @param config The config to use
|
||||
* @returns The raw URL for the user's header
|
||||
*/
|
||||
public getHeaderUrl(config: Config): URL | null {
|
||||
public getHeaderUrl(): URL | null {
|
||||
if (!this.header) {
|
||||
return config.defaults.header ?? null;
|
||||
}
|
||||
|
|
@ -996,7 +994,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
JSON.stringify(entity),
|
||||
);
|
||||
|
||||
if (config.debug.federation) {
|
||||
if (config.debug?.federation) {
|
||||
const logger = getLogger("federation");
|
||||
|
||||
// Log public key
|
||||
|
|
@ -1014,8 +1012,8 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
*
|
||||
* @returns The requester
|
||||
*/
|
||||
public static async getFederationRequester(): Promise<FederationRequester> {
|
||||
const signatureConstructor = await SignatureConstructor.fromStringKey(
|
||||
public static getFederationRequester(): FederationRequester {
|
||||
const signatureConstructor = new SignatureConstructor(
|
||||
config.instance.keys.private,
|
||||
config.http.base_url,
|
||||
);
|
||||
|
|
@ -1087,7 +1085,7 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
try {
|
||||
await new FederationRequester().post(inbox, entity, {
|
||||
// @ts-expect-error Bun extension
|
||||
proxy: config.http.proxy.address,
|
||||
proxy: config.http.proxy_address,
|
||||
headers: {
|
||||
...headers.toJSON(),
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
|
|
@ -1117,9 +1115,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
url:
|
||||
user.uri ||
|
||||
new URL(`/@${user.username}`, config.http.base_url).toString(),
|
||||
avatar: proxyUrl(this.getAvatarUrl(config)).toString(),
|
||||
header: this.getHeaderUrl(config)
|
||||
? proxyUrl(this.getHeaderUrl(config) as URL).toString()
|
||||
avatar: proxyUrl(this.getAvatarUrl()).toString(),
|
||||
header: this.getHeaderUrl()
|
||||
? proxyUrl(this.getHeaderUrl() as URL).toString()
|
||||
: "",
|
||||
locked: user.isLocked,
|
||||
created_at: new Date(user.createdAt).toISOString(),
|
||||
|
|
@ -1135,9 +1133,9 @@ export class User extends BaseInterface<typeof Users, UserWithRelations> {
|
|||
bot: user.isBot,
|
||||
source: isOwnAccount ? user.source : undefined,
|
||||
// TODO: Add static avatar and header
|
||||
avatar_static: proxyUrl(this.getAvatarUrl(config)).toString(),
|
||||
header_static: this.getHeaderUrl(config)
|
||||
? proxyUrl(this.getHeaderUrl(config) as URL).toString()
|
||||
avatar_static: proxyUrl(this.getAvatarUrl()).toString(),
|
||||
header_static: this.getHeaderUrl()
|
||||
? proxyUrl(this.getHeaderUrl() as URL).toString()
|
||||
: "",
|
||||
acct: this.getAcct(),
|
||||
// TODO: Add these fields
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue