mirror of
https://github.com/versia-pub/server.git
synced 2026-01-26 12:16:01 +01:00
feat(plugin): ✨ Add override settings to plugin loading
This commit is contained in:
parent
c0805ff125
commit
f26ab0f0e6
2
.github/config.workflow.toml
vendored
2
.github/config.workflow.toml
vendored
|
|
@ -287,6 +287,6 @@ max_coeff = 1.0
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
|
|
||||||
[plugins."@versia/openid".keys]
|
[plugins.config."@versia/openid".keys]
|
||||||
private = "MC4CAQAwBQYDK2VwBCIEID+H5n9PY3zVKZQcq4jrnE1IiRd2EWWr8ApuHUXmuOzl"
|
private = "MC4CAQAwBQYDK2VwBCIEID+H5n9PY3zVKZQcq4jrnE1IiRd2EWWr8ApuHUXmuOzl"
|
||||||
public = "MCowBQYDK2VwAyEAzenliNkgpXYsh3gXTnAoUWzlCPjIOppmAVx2DBlLsC8="
|
public = "MCowBQYDK2VwAyEAzenliNkgpXYsh3gXTnAoUWzlCPjIOppmAVx2DBlLsC8="
|
||||||
|
|
|
||||||
11
app.ts
11
app.ts
|
|
@ -119,19 +119,24 @@ export const appFactory = async () => {
|
||||||
|
|
||||||
const loader = new PluginLoader();
|
const loader = new PluginLoader();
|
||||||
|
|
||||||
const plugins = await loader.loadPlugins(join(process.cwd(), "plugins"));
|
const plugins = await loader.loadPlugins(
|
||||||
|
join(process.cwd(), "plugins"),
|
||||||
|
config.plugins?.autoload,
|
||||||
|
config.plugins?.overrides.enabled,
|
||||||
|
config.plugins?.overrides.disabled,
|
||||||
|
);
|
||||||
|
|
||||||
for (const data of plugins) {
|
for (const data of plugins) {
|
||||||
serverLogger.info`Loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} ${chalk.gray(`[${plugins.indexOf(data) + 1}/${plugins.length}]`)}`;
|
serverLogger.info`Loading plugin ${chalk.blueBright(data.manifest.name)} ${chalk.blueBright(data.manifest.version)} ${chalk.gray(`[${plugins.indexOf(data) + 1}/${plugins.length}]`)}`;
|
||||||
try {
|
try {
|
||||||
// biome-ignore lint/complexity/useLiteralKeys: loadConfig is a private method
|
// biome-ignore lint/complexity/useLiteralKeys: loadConfig is a private method
|
||||||
await data.plugin["_loadConfig"](
|
await data.plugin["_loadConfig"](
|
||||||
config.plugins?.[data.manifest.name],
|
config.plugins?.config?.[data.manifest.name],
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
serverLogger.fatal`Plugin configuration is invalid: ${chalk.redBright(e as ValidationError)}`;
|
serverLogger.fatal`Plugin configuration is invalid: ${chalk.redBright(e as ValidationError)}`;
|
||||||
serverLogger.fatal`Put your configuration at ${chalk.blueBright(
|
serverLogger.fatal`Put your configuration at ${chalk.blueBright(
|
||||||
"plugins.<plugin-name>",
|
"plugins.config.<plugin-name>",
|
||||||
)}`;
|
)}`;
|
||||||
throw new Error("Plugin configuration is invalid");
|
throw new Error("Plugin configuration is invalid");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ describe("PluginLoader", () => {
|
||||||
default: mockPlugin,
|
default: mockPlugin,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const plugins = await pluginLoader.loadPlugins("/some/path");
|
const plugins = await pluginLoader.loadPlugins("/some/path", true);
|
||||||
expect(plugins).toEqual([
|
expect(plugins).toEqual([
|
||||||
{
|
{
|
||||||
manifest: manifestContent,
|
manifest: manifestContent,
|
||||||
|
|
|
||||||
|
|
@ -162,12 +162,42 @@ export class PluginLoader {
|
||||||
*/
|
*/
|
||||||
public async loadPlugins(
|
public async loadPlugins(
|
||||||
dir: string,
|
dir: string,
|
||||||
|
autoload: boolean,
|
||||||
|
enabled?: string[],
|
||||||
|
disabled?: string[],
|
||||||
): Promise<{ manifest: Manifest; plugin: Plugin<ZodTypeAny> }[]> {
|
): Promise<{ manifest: Manifest; plugin: Plugin<ZodTypeAny> }[]> {
|
||||||
const plugins = await PluginLoader.findPlugins(dir);
|
const plugins = await PluginLoader.findPlugins(dir);
|
||||||
|
|
||||||
|
const enabledOn = (enabled?.length ?? 0) > 0;
|
||||||
|
const disabledOn = (disabled?.length ?? 0) > 0;
|
||||||
|
|
||||||
|
if (enabledOn && disabledOn) {
|
||||||
|
this.logger
|
||||||
|
.fatal`Both enabled and disabled lists are specified. Only one of them can be used.`;
|
||||||
|
throw new Error("Invalid configuration");
|
||||||
|
}
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
plugins.map(async (plugin) => {
|
plugins.map(async (plugin) => {
|
||||||
const manifest = await this.parseManifest(dir, plugin);
|
const manifest = await this.parseManifest(dir, plugin);
|
||||||
|
|
||||||
|
// If autoload is disabled, only load plugins explicitly enabled
|
||||||
|
if (
|
||||||
|
!(autoload || enabledOn || enabled?.includes(manifest.name))
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If enabled is specified, only load plugins in the enabled list
|
||||||
|
// If disabled is specified, only load plugins not in the disabled list
|
||||||
|
if (enabledOn && !enabled?.includes(manifest.name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disabled?.includes(manifest.name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const pluginInstance = await this.loadPlugin(
|
const pluginInstance = await this.loadPlugin(
|
||||||
dir,
|
dir,
|
||||||
`${plugin}/index`,
|
`${plugin}/index`,
|
||||||
|
|
@ -175,6 +205,6 @@ export class PluginLoader {
|
||||||
|
|
||||||
return { manifest, plugin: pluginInstance };
|
return { manifest, plugin: pluginInstance };
|
||||||
}),
|
}),
|
||||||
);
|
).then((data) => data.filter((d) => d !== null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4006,10 +4006,44 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"plugins": {
|
"plugins": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"autoload": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"disabled": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"default": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"default": {
|
||||||
|
"enabled": [],
|
||||||
|
"disabled": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": {}
|
"additionalProperties": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"database",
|
"database",
|
||||||
"redis",
|
"redis",
|
||||||
|
|
@ -4019,7 +4053,8 @@
|
||||||
"http",
|
"http",
|
||||||
"smtp",
|
"smtp",
|
||||||
"filters",
|
"filters",
|
||||||
"ratelimits"
|
"ratelimits",
|
||||||
|
"plugins"
|
||||||
],
|
],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#"
|
"$schema": "http://json-schema.org/draft-07/schema#"
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,10 @@ const zUrl = z
|
||||||
.refine((arg) => URL.canParse(arg), "Invalid url")
|
.refine((arg) => URL.canParse(arg), "Invalid url")
|
||||||
.transform((arg) => arg.replace(/\/$/, ""));
|
.transform((arg) => arg.replace(/\/$/, ""));
|
||||||
|
|
||||||
export const configValidator = z.object({
|
export const configValidator = z
|
||||||
database: z.object({
|
.object({
|
||||||
|
database: z
|
||||||
|
.object({
|
||||||
host: z.string().min(1).default("localhost"),
|
host: z.string().min(1).default("localhost"),
|
||||||
port: z
|
port: z
|
||||||
.number()
|
.number()
|
||||||
|
|
@ -35,7 +37,8 @@ export const configValidator = z.object({
|
||||||
database: z.string().min(1).default("versia"),
|
database: z.string().min(1).default("versia"),
|
||||||
replicas: z
|
replicas: z
|
||||||
.array(
|
.array(
|
||||||
z.object({
|
z
|
||||||
|
.object({
|
||||||
host: z.string().min(1),
|
host: z.string().min(1),
|
||||||
port: z
|
port: z
|
||||||
.number()
|
.number()
|
||||||
|
|
@ -46,11 +49,14 @@ export const configValidator = z.object({
|
||||||
username: z.string().min(1),
|
username: z.string().min(1),
|
||||||
password: z.string().default(""),
|
password: z.string().default(""),
|
||||||
database: z.string().min(1).default("versia"),
|
database: z.string().min(1).default("versia"),
|
||||||
}),
|
})
|
||||||
|
.strict(),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
}),
|
})
|
||||||
redis: z.object({
|
.strict(),
|
||||||
|
redis: z
|
||||||
|
.object({
|
||||||
queue: z
|
queue: z
|
||||||
.object({
|
.object({
|
||||||
host: z.string().min(1).default("localhost"),
|
host: z.string().min(1).default("localhost"),
|
||||||
|
|
@ -64,6 +70,7 @@ export const configValidator = z.object({
|
||||||
database: z.number().int().default(0),
|
database: z.number().int().default(0),
|
||||||
enabled: z.boolean().default(false),
|
enabled: z.boolean().default(false),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
port: 6379,
|
port: 6379,
|
||||||
|
|
@ -84,6 +91,7 @@ export const configValidator = z.object({
|
||||||
database: z.number().int().default(1),
|
database: z.number().int().default(1),
|
||||||
enabled: z.boolean().default(false),
|
enabled: z.boolean().default(false),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
host: "localhost",
|
host: "localhost",
|
||||||
port: 6379,
|
port: 6379,
|
||||||
|
|
@ -91,8 +99,10 @@ export const configValidator = z.object({
|
||||||
database: 1,
|
database: 1,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
}),
|
}),
|
||||||
}),
|
})
|
||||||
sonic: z.object({
|
.strict(),
|
||||||
|
sonic: z
|
||||||
|
.object({
|
||||||
host: z.string().min(1).default("localhost"),
|
host: z.string().min(1).default("localhost"),
|
||||||
port: z
|
port: z
|
||||||
.number()
|
.number()
|
||||||
|
|
@ -102,24 +112,30 @@ export const configValidator = z.object({
|
||||||
.default(7700),
|
.default(7700),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
enabled: z.boolean().default(false),
|
enabled: z.boolean().default(false),
|
||||||
}),
|
})
|
||||||
signups: z.object({
|
.strict(),
|
||||||
|
signups: z
|
||||||
|
.object({
|
||||||
registration: z.boolean().default(true),
|
registration: z.boolean().default(true),
|
||||||
rules: z.array(z.string()).default([]),
|
rules: z.array(z.string()).default([]),
|
||||||
}),
|
})
|
||||||
oidc: z.object({
|
.strict(),
|
||||||
|
oidc: z
|
||||||
|
.object({
|
||||||
forced: z.boolean().default(false),
|
forced: z.boolean().default(false),
|
||||||
allow_registration: z.boolean().default(true),
|
allow_registration: z.boolean().default(true),
|
||||||
providers: z
|
providers: z
|
||||||
.array(
|
.array(
|
||||||
z.object({
|
z
|
||||||
|
.object({
|
||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
id: z.string().min(1),
|
id: z.string().min(1),
|
||||||
url: z.string().min(1),
|
url: z.string().min(1),
|
||||||
client_id: z.string().min(1),
|
client_id: z.string().min(1),
|
||||||
client_secret: z.string().min(1),
|
client_secret: z.string().min(1),
|
||||||
icon: z.string().min(1).optional(),
|
icon: z.string().min(1).optional(),
|
||||||
}),
|
})
|
||||||
|
.strict(),
|
||||||
)
|
)
|
||||||
.default([]),
|
.default([]),
|
||||||
keys: z
|
keys: z
|
||||||
|
|
@ -127,9 +143,12 @@ export const configValidator = z.object({
|
||||||
public: z.string().min(1).optional(),
|
public: z.string().min(1).optional(),
|
||||||
private: z.string().min(1).optional(),
|
private: z.string().min(1).optional(),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.optional(),
|
.optional(),
|
||||||
}),
|
})
|
||||||
http: z.object({
|
.strict(),
|
||||||
|
http: z
|
||||||
|
.object({
|
||||||
base_url: z.string().min(1).default("http://versia.social"),
|
base_url: z.string().min(1).default("http://versia.social"),
|
||||||
bind: z.string().min(1).default("0.0.0.0"),
|
bind: z.string().min(1).default("0.0.0.0"),
|
||||||
bind_port: z
|
bind_port: z
|
||||||
|
|
@ -146,6 +165,7 @@ export const configValidator = z.object({
|
||||||
enabled: z.boolean().default(false),
|
enabled: z.boolean().default(false),
|
||||||
address: zUrl.or(z.literal("")),
|
address: zUrl.or(z.literal("")),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
address: "",
|
address: "",
|
||||||
|
|
@ -166,6 +186,7 @@ export const configValidator = z.object({
|
||||||
passphrase: z.string().optional(),
|
passphrase: z.string().optional(),
|
||||||
ca: z.string().optional(),
|
ca: z.string().optional(),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
key: "",
|
key: "",
|
||||||
|
|
@ -180,13 +201,15 @@ export const configValidator = z.object({
|
||||||
bait_ips: z.array(z.string()).default([]),
|
bait_ips: z.array(z.string()).default([]),
|
||||||
bait_user_agents: z.array(z.string()).default([]),
|
bait_user_agents: z.array(z.string()).default([]),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
send_file: "",
|
send_file: "",
|
||||||
bait_ips: [],
|
bait_ips: [],
|
||||||
bait_user_agents: [],
|
bait_user_agents: [],
|
||||||
}),
|
}),
|
||||||
}),
|
})
|
||||||
|
.strict(),
|
||||||
frontend: z
|
frontend: z
|
||||||
.object({
|
.object({
|
||||||
enabled: z.boolean().default(true),
|
enabled: z.boolean().default(true),
|
||||||
|
|
@ -199,6 +222,7 @@ export const configValidator = z.object({
|
||||||
register: zUrlPath.default("/register"),
|
register: zUrlPath.default("/register"),
|
||||||
password_reset: zUrlPath.default("/oauth/reset"),
|
password_reset: zUrlPath.default("/oauth/reset"),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
home: "/",
|
home: "/",
|
||||||
login: "/oauth/authorize",
|
login: "/oauth/authorize",
|
||||||
|
|
@ -208,6 +232,7 @@ export const configValidator = z.object({
|
||||||
}),
|
}),
|
||||||
settings: z.record(z.string(), z.any()).default({}),
|
settings: z.record(z.string(), z.any()).default({}),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
enabled: true,
|
enabled: true,
|
||||||
url: "http://localhost:3000",
|
url: "http://localhost:3000",
|
||||||
|
|
@ -227,6 +252,7 @@ export const configValidator = z.object({
|
||||||
tls: z.boolean().default(true),
|
tls: z.boolean().default(true),
|
||||||
enabled: z.boolean().default(false),
|
enabled: z.boolean().default(false),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
server: "",
|
server: "",
|
||||||
port: 465,
|
port: 465,
|
||||||
|
|
@ -248,12 +274,14 @@ export const configValidator = z.object({
|
||||||
convert_to: z.string().default("image/webp"),
|
convert_to: z.string().default("image/webp"),
|
||||||
convert_vector: z.boolean().default(false),
|
convert_vector: z.boolean().default(false),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
convert_images: false,
|
convert_images: false,
|
||||||
convert_to: "image/webp",
|
convert_to: "image/webp",
|
||||||
convert_vector: false,
|
convert_vector: false,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
backend: MediaBackendType.Local,
|
backend: MediaBackendType.Local,
|
||||||
deduplicate_media: true,
|
deduplicate_media: true,
|
||||||
|
|
@ -272,6 +300,7 @@ export const configValidator = z.object({
|
||||||
bucket_name: z.string().default("versia"),
|
bucket_name: z.string().default("versia"),
|
||||||
public_url: zUrl,
|
public_url: zUrl,
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
endpoint: "",
|
endpoint: "",
|
||||||
access_key: "",
|
access_key: "",
|
||||||
|
|
@ -361,6 +390,7 @@ export const configValidator = z.object({
|
||||||
expiration: z.number().int().positive().default(300),
|
expiration: z.number().int().positive().default(300),
|
||||||
key: z.string().default(""),
|
key: z.string().default(""),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
enabled: true,
|
enabled: true,
|
||||||
difficulty: 50000,
|
difficulty: 50000,
|
||||||
|
|
@ -368,6 +398,7 @@ export const configValidator = z.object({
|
||||||
key: "",
|
key: "",
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
max_displayname_size: 50,
|
max_displayname_size: 50,
|
||||||
max_bio_size: 5000,
|
max_bio_size: 5000,
|
||||||
|
|
@ -450,6 +481,7 @@ export const configValidator = z.object({
|
||||||
header: zUrl.optional(),
|
header: zUrl.optional(),
|
||||||
placeholder_style: z.string().default("thumbs"),
|
placeholder_style: z.string().default("thumbs"),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
visibility: "public",
|
visibility: "public",
|
||||||
language: "en",
|
language: "en",
|
||||||
|
|
@ -461,7 +493,8 @@ export const configValidator = z.object({
|
||||||
.object({
|
.object({
|
||||||
blocked: z.array(zUrl).default([]),
|
blocked: z.array(zUrl).default([]),
|
||||||
followers_only: z.array(zUrl).default([]),
|
followers_only: z.array(zUrl).default([]),
|
||||||
discard: z.object({
|
discard: z
|
||||||
|
.object({
|
||||||
reports: z.array(zUrl).default([]),
|
reports: z.array(zUrl).default([]),
|
||||||
deletes: z.array(zUrl).default([]),
|
deletes: z.array(zUrl).default([]),
|
||||||
updates: z.array(zUrl).default([]),
|
updates: z.array(zUrl).default([]),
|
||||||
|
|
@ -471,7 +504,8 @@ export const configValidator = z.object({
|
||||||
reactions: z.array(zUrl).default([]),
|
reactions: z.array(zUrl).default([]),
|
||||||
banners: z.array(zUrl).default([]),
|
banners: z.array(zUrl).default([]),
|
||||||
avatars: z.array(zUrl).default([]),
|
avatars: z.array(zUrl).default([]),
|
||||||
}),
|
})
|
||||||
|
.strict(),
|
||||||
bridge: z
|
bridge: z
|
||||||
.object({
|
.object({
|
||||||
enabled: z.boolean().default(false),
|
enabled: z.boolean().default(false),
|
||||||
|
|
@ -480,6 +514,7 @@ export const configValidator = z.object({
|
||||||
token: z.string().default(""),
|
token: z.string().default(""),
|
||||||
url: zUrl.optional(),
|
url: zUrl.optional(),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
software: "versia-ap",
|
software: "versia-ap",
|
||||||
|
|
@ -491,6 +526,7 @@ export const configValidator = z.object({
|
||||||
"When bridge is enabled, url must be set",
|
"When bridge is enabled, url must be set",
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
blocked: [],
|
blocked: [],
|
||||||
followers_only: [],
|
followers_only: [],
|
||||||
|
|
@ -524,13 +560,19 @@ export const configValidator = z.object({
|
||||||
keys: z
|
keys: z
|
||||||
.object({
|
.object({
|
||||||
public: z.string().min(3).default("").or(z.literal("")),
|
public: z.string().min(3).default("").or(z.literal("")),
|
||||||
private: z.string().min(3).default("").or(z.literal("")),
|
private: z
|
||||||
|
.string()
|
||||||
|
.min(3)
|
||||||
|
.default("")
|
||||||
|
.or(z.literal("")),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
public: "",
|
public: "",
|
||||||
private: "",
|
private: "",
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
name: "Versia",
|
name: "Versia",
|
||||||
description: "A Versia instance",
|
description: "A Versia instance",
|
||||||
|
|
@ -552,20 +594,25 @@ export const configValidator = z.object({
|
||||||
default: z
|
default: z
|
||||||
.array(z.nativeEnum(RolePermissions))
|
.array(z.nativeEnum(RolePermissions))
|
||||||
.default(DEFAULT_ROLES),
|
.default(DEFAULT_ROLES),
|
||||||
admin: z.array(z.nativeEnum(RolePermissions)).default(ADMIN_ROLES),
|
admin: z
|
||||||
|
.array(z.nativeEnum(RolePermissions))
|
||||||
|
.default(ADMIN_ROLES),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
anonymous: DEFAULT_ROLES,
|
anonymous: DEFAULT_ROLES,
|
||||||
default: DEFAULT_ROLES,
|
default: DEFAULT_ROLES,
|
||||||
admin: ADMIN_ROLES,
|
admin: ADMIN_ROLES,
|
||||||
}),
|
}),
|
||||||
filters: z.object({
|
filters: z
|
||||||
|
.object({
|
||||||
note_content: z.array(z.string()).default([]),
|
note_content: z.array(z.string()).default([]),
|
||||||
emoji: z.array(z.string()).default([]),
|
emoji: z.array(z.string()).default([]),
|
||||||
username: z.array(z.string()).default([]),
|
username: z.array(z.string()).default([]),
|
||||||
displayname: z.array(z.string()).default([]),
|
displayname: z.array(z.string()).default([]),
|
||||||
bio: z.array(z.string()).default([]),
|
bio: z.array(z.string()).default([]),
|
||||||
}),
|
})
|
||||||
|
.strict(),
|
||||||
logging: z
|
logging: z
|
||||||
.object({
|
.object({
|
||||||
log_requests: z.boolean().default(false),
|
log_requests: z.boolean().default(false),
|
||||||
|
|
@ -582,11 +629,18 @@ export const configValidator = z.object({
|
||||||
dsn: z.string().url().or(z.literal("")).optional(),
|
dsn: z.string().url().or(z.literal("")).optional(),
|
||||||
debug: z.boolean().default(false),
|
debug: z.boolean().default(false),
|
||||||
sample_rate: z.number().min(0).max(1.0).default(1.0),
|
sample_rate: z.number().min(0).max(1.0).default(1.0),
|
||||||
traces_sample_rate: z.number().min(0).max(1.0).default(1.0),
|
traces_sample_rate: z
|
||||||
trace_propagation_targets: z.array(z.string()).default([]),
|
.number()
|
||||||
|
.min(0)
|
||||||
|
.max(1.0)
|
||||||
|
.default(1.0),
|
||||||
|
trace_propagation_targets: z
|
||||||
|
.array(z.string())
|
||||||
|
.default([]),
|
||||||
max_breadcrumbs: z.number().default(100),
|
max_breadcrumbs: z.number().default(100),
|
||||||
environment: z.string().optional(),
|
environment: z.string().optional(),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
debug: false,
|
debug: false,
|
||||||
|
|
@ -602,10 +656,12 @@ export const configValidator = z.object({
|
||||||
.object({
|
.object({
|
||||||
requests: z.string().default("logs/requests.log"),
|
requests: z.string().default("logs/requests.log"),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
requests: "logs/requests.log",
|
requests: "logs/requests.log",
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
log_requests: false,
|
log_requests: false,
|
||||||
log_responses: false,
|
log_responses: false,
|
||||||
|
|
@ -624,27 +680,55 @@ export const configValidator = z.object({
|
||||||
requests: "logs/requests.log",
|
requests: "logs/requests.log",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
ratelimits: z.object({
|
ratelimits: z
|
||||||
|
.object({
|
||||||
duration_coeff: z.number().default(1),
|
duration_coeff: z.number().default(1),
|
||||||
max_coeff: z.number().default(1),
|
max_coeff: z.number().default(1),
|
||||||
custom: z
|
custom: z
|
||||||
.record(
|
.record(
|
||||||
z.string(),
|
z.string(),
|
||||||
z.object({
|
z
|
||||||
|
.object({
|
||||||
duration: z.number().default(30),
|
duration: z.number().default(30),
|
||||||
max: z.number().default(60),
|
max: z.number().default(60),
|
||||||
}),
|
})
|
||||||
|
.strict(),
|
||||||
)
|
)
|
||||||
.default({}),
|
.default({}),
|
||||||
}),
|
})
|
||||||
|
.strict(),
|
||||||
debug: z
|
debug: z
|
||||||
.object({
|
.object({
|
||||||
federation: z.boolean().default(false),
|
federation: z.boolean().default(false),
|
||||||
})
|
})
|
||||||
|
.strict()
|
||||||
.default({
|
.default({
|
||||||
federation: false,
|
federation: false,
|
||||||
}),
|
}),
|
||||||
plugins: z.record(z.string(), z.any()).optional(),
|
plugins: z
|
||||||
});
|
.object({
|
||||||
|
autoload: z.boolean().default(true),
|
||||||
|
overrides: z
|
||||||
|
.object({
|
||||||
|
enabled: z.array(z.string()).default([]),
|
||||||
|
disabled: z.array(z.string()).default([]),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
.default({
|
||||||
|
enabled: [],
|
||||||
|
disabled: [],
|
||||||
|
})
|
||||||
|
.refine(
|
||||||
|
// Only one of enabled or disabled can be set
|
||||||
|
(arg) =>
|
||||||
|
arg.enabled.length === 0 ||
|
||||||
|
arg.disabled.length === 0,
|
||||||
|
"Only one of enabled or disabled can be set",
|
||||||
|
),
|
||||||
|
config: z.record(z.string(), z.any()).optional(),
|
||||||
|
})
|
||||||
|
.strict(),
|
||||||
|
})
|
||||||
|
.strict();
|
||||||
|
|
||||||
export type Config = z.infer<typeof configValidator>;
|
export type Config = z.infer<typeof configValidator>;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@ const scope = "openid profile email";
|
||||||
const secret = "test-secret";
|
const secret = "test-secret";
|
||||||
const privateKey = await crypto.subtle.importKey(
|
const privateKey = await crypto.subtle.importKey(
|
||||||
"pkcs8",
|
"pkcs8",
|
||||||
Buffer.from(config.plugins?.["@versia/openid"].keys.private, "base64"),
|
Buffer.from(
|
||||||
|
config.plugins?.config?.["@versia/openid"].keys.private,
|
||||||
|
"base64",
|
||||||
|
),
|
||||||
"Ed25519",
|
"Ed25519",
|
||||||
false,
|
false,
|
||||||
["sign"],
|
["sign"],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue