diff --git a/Cargo.lock b/Cargo.lock index 3b7e70c186..09c4946e17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,6 +209,7 @@ dependencies = [ "sea-orm", "serde", "serde_json", + "serde_yaml", "thiserror", "tokio", ] @@ -2157,6 +2158,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2849,6 +2863,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 993fa06924..fcb5be2f0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ schemars = "0.8.16" sea-orm = "0.12.15" serde = "1.0.197" serde_json = "1.0.115" +serde_yaml = "0.9.34" syn = "2.0.58" thiserror = "1.0.58" tokio = "1.37.0" diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index 48bdebc470..1429548a67 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -31,6 +31,7 @@ schemars = { workspace = true, features = ["chrono"] } sea-orm = { workspace = true, features = ["sqlx-postgres", "runtime-tokio-rustls"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +serde_yaml = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 44c8aa6660..3168aa7105 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -3,6 +3,115 @@ /* auto-generated by NAPI-RS */ +export interface ServerConfig { + url: string + port: number + /** host to listen on */ + bind?: string + disableHsts?: boolean + db: DbConfig + redis: RedisConfig + cacheServer?: RedisConfig + proxy?: string + proxySmtp?: string + proxyBypassHosts?: Array + allowedPrivateNetworks?: Array + /** `NapiValue` is not implemented for `u64` */ + maxFileSize?: number + accessLog?: string + clusterLimits?: WorkerConfig + cuid?: IdConfig + outgoingAddress?: string + deliverJobConcurrency?: number + inboxJobConcurrency?: number + deliverJobPerSec?: number + inboxJobPerSec?: number + deliverJobMaxAttempts?: number + inboxJobMaxAttempts?: number + logLevel?: Array + syslog?: SysLogConfig + proxyRemoteFiles?: boolean + mediaProxy?: string + summalyProxyUrl?: string + reservedUsernames?: Array + maxUserSignups?: number + isManagedHosting?: boolean + maxNoteLength?: number + maxCaptionLength?: number + deepl?: DeepLConfig + libreTranslate?: LibreTranslateConfig + email?: EmailConfig + objectStorage?: ObjectStorageConfig +} +export interface DbConfig { + host: string + port: number + db: string + user: string + pass: string + disableCache?: boolean + extra?: any +} +export interface RedisConfig { + host: string + port: number + family?: number + user?: string + pass?: string + tls?: TlsConfig + db: number + prefix: string +} +export interface TlsConfig { + host: string + rejectUnauthorized: boolean +} +export interface WorkerConfig { + web?: number + queue?: number +} +export interface IdConfig { + length?: number + fingerprint?: string +} +export interface SysLogConfig { + host: string + port: number +} +export interface DeepLConfig { + managed?: boolean + authKey?: string + isPro?: boolean +} +export interface LibreTranslateConfig { + managed?: boolean + apiUrl?: string + apiKey?: string +} +export interface EmailConfig { + managed?: boolean + address?: string + host?: string + port?: number + user?: string + pass?: string + useImplicitSslTls?: boolean +} +export interface ObjectStorageConfig { + managed?: boolean + baseUrl?: string + bucket?: string + prefix?: string + endpoint?: string + region?: string + accessKey?: string + secretKey?: string + useSsl?: boolean + connnectOverProxy?: boolean + setPublicReadOnUpload?: boolean + s3ForcePathStyle?: boolean +} +export function readServerConfig(): ServerConfig export interface Acct { username: string host: string | null diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index d3a197e5f0..800baabeb2 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,8 +310,9 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { stringToAcct, acctToString, nyaify, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr, IdConvertType, convertId } = nativeBinding +const { readServerConfig, stringToAcct, acctToString, nyaify, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr, IdConvertType, convertId } = nativeBinding +module.exports.readServerConfig = readServerConfig module.exports.stringToAcct = stringToAcct module.exports.acctToString = acctToString module.exports.nyaify = nyaify diff --git a/packages/backend-rs/src/config/mod.rs b/packages/backend-rs/src/config/mod.rs new file mode 100644 index 0000000000..74f47ad347 --- /dev/null +++ b/packages/backend-rs/src/config/mod.rs @@ -0,0 +1 @@ +pub mod server; diff --git a/packages/backend-rs/src/config/server.rs b/packages/backend-rs/src/config/server.rs new file mode 100644 index 0000000000..200b97dc4c --- /dev/null +++ b/packages/backend-rs/src/config/server.rs @@ -0,0 +1,176 @@ +use once_cell::sync::Lazy; +use serde::Deserialize; +use std::env; +use std::fs; + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct ServerConfig { + pub url: String, + pub port: u16, + /// host to listen on + pub bind: Option, + pub disable_hsts: Option, + + pub db: DbConfig, + pub redis: RedisConfig, + pub cache_server: Option, + + pub proxy: Option, + pub proxy_smtp: Option, + pub proxy_bypass_hosts: Option>, + + pub allowed_private_networks: Option>, + /// `NapiValue` is not implemented for `u64` + pub max_file_size: Option, + pub access_log: Option, + pub cluster_limits: Option, + pub cuid: Option, + pub outgoing_address: Option, + + pub deliver_job_concurrency: Option, + pub inbox_job_concurrency: Option, + pub deliver_job_per_sec: Option, + pub inbox_job_per_sec: Option, + pub deliver_job_max_attempts: Option, + pub inbox_job_max_attempts: Option, + + pub log_level: Option>, + + pub syslog: Option, + + pub proxy_remote_files: Option, + pub media_proxy: Option, + pub summaly_proxy_url: Option, + + pub reserved_usernames: Option>, + + pub max_user_signups: Option, + pub is_managed_hosting: Option, + pub max_note_length: Option, + pub max_caption_length: Option, + + pub deepl: Option, + pub libre_translate: Option, + pub email: Option, + pub object_storage: Option, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[crate::export(object, use_nullable = false)] +pub struct DbConfig { + pub host: String, + pub port: u16, + pub db: String, + pub user: String, + pub pass: String, + pub disable_cache: Option, + pub extra: Option, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[crate::export(object, use_nullable = false)] +pub struct RedisConfig { + pub host: String, + pub port: u16, + pub family: Option, + pub user: Option, + pub pass: Option, + pub tls: Option, + #[serde(default)] + pub db: u32, + #[serde(default)] + pub prefix: String, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct TlsConfig { + pub host: String, + pub reject_unauthorized: bool, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct WorkerConfig { + pub web: Option, + pub queue: Option, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct IdConfig { + pub length: Option, + pub fingerprint: Option, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct SysLogConfig { + pub host: String, + pub port: u16, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct DeepLConfig { + pub managed: Option, + pub auth_key: Option, + pub is_pro: Option, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct LibreTranslateConfig { + pub managed: Option, + pub api_url: Option, + pub api_key: Option, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct EmailConfig { + pub managed: Option, + pub address: Option, + pub host: Option, + pub port: Option, + pub user: Option, + pub pass: Option, + pub use_implicit_ssl_tls: Option, +} + +#[derive(Clone, Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, use_nullable = false)] +pub struct ObjectStorageConfig { + pub managed: Option, + pub base_url: Option, + pub bucket: Option, + pub prefix: Option, + pub endpoint: Option, + pub region: Option, + pub access_key: Option, + pub secret_key: Option, + pub use_ssl: Option, + pub connnect_over_proxy: Option, + pub set_public_read_on_upload: Option, + pub s3_force_path_style: Option, +} + +#[crate::export] +pub fn read_server_config() -> ServerConfig { + let cwd = env::current_dir().unwrap(); + let yml = fs::File::open(cwd.join("../../.config/default.yml")) + .expect("Failed to open '.config/default.yml'"); + serde_yaml::from_reader(yml).expect("Failed to parse yaml") +} + +pub static SERVER_CONFIG: Lazy = Lazy::new(read_server_config); diff --git a/packages/backend-rs/src/lib.rs b/packages/backend-rs/src/lib.rs index 3a8bb4550e..dff5073d34 100644 --- a/packages/backend-rs/src/lib.rs +++ b/packages/backend-rs/src/lib.rs @@ -1,5 +1,6 @@ pub use macro_rs::export; +pub mod config; pub mod database; pub mod misc; pub mod model; diff --git a/packages/backend/package.json b/packages/backend/package.json index d5cc8bd665..a9e3ded008 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -67,7 +67,6 @@ "ioredis": "5.3.2", "ip-cidr": "4.0.0", "is-svg": "5.0.0", - "js-yaml": "4.1.0", "json5": "2.2.3", "jsonld": "8.3.2", "jsrsasign": "11.1.0", @@ -137,7 +136,6 @@ "@types/content-disposition": "^0.5.8", "@types/escape-regexp": "0.0.3", "@types/fluent-ffmpeg": "2.1.24", - "@types/js-yaml": "4.0.9", "@types/jsonld": "1.5.13", "@types/jsrsasign": "10.5.13", "@types/katex": "0.16.7", diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts index 2ff3309264..2b286b9439 100644 --- a/packages/backend/src/config/load.ts +++ b/packages/backend/src/config/load.ts @@ -5,8 +5,8 @@ import * as fs from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname } from "node:path"; -import * as yaml from "js-yaml"; -import type { Source, Mixin } from "./types.js"; +import type { Mixin } from "./types.js"; +import { readServerConfig } from "backend-rs"; const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); @@ -32,7 +32,7 @@ export default function load() { "utf-8", ), ); - const config = yaml.load(fs.readFileSync(path, "utf-8")) as Source; + const config = readServerConfig(); const mixin = {} as Mixin; diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 882e429c79..6b593d3b2d 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -1,134 +1,7 @@ -/** - * ユーザーが設定する必要のある情報 - */ -export type Source = { - repository_url?: string; - feedback_url?: string; - url: string; - port: number; - bind?: string; - disableHsts?: boolean; - db: { - host: string; - port: number; - db: string; - user: string; - pass: string; - disableCache?: boolean; - extra?: { [x: string]: string }; - }; - redis: { - host: string; - port: number; - family?: number; - pass?: string; - db?: number; - prefix?: string; - user?: string; - tls?: { [y: string]: string }; - }; - cacheServer?: { - host: string; - port: number; - family?: number; - pass?: string; - db?: number; - prefix?: string; - user?: string; - tls?: { [z: string]: string }; - }; - - proxy?: string; - proxySmtp?: string; - proxyBypassHosts?: string[]; - - allowedPrivateNetworks?: string[]; - - maxFileSize?: number; - - accesslog?: string; - - clusterLimits?: { - web?: number; - queue?: number; - }; - - cuid?: { - length?: number; - fingerprint?: string; - }; - - outgoingAddress?: string; - outgoingAddressFamily?: "ipv4" | "ipv6" | "dual"; - - deliverJobConcurrency?: number; - inboxJobConcurrency?: number; - deliverJobPerSec?: number; - inboxJobPerSec?: number; - deliverJobMaxAttempts?: number; - inboxJobMaxAttempts?: number; - - logLevel?: string[]; - - syslog: { - host: string; - port: number; - }; - - mediaProxy?: string; - proxyRemoteFiles?: boolean; - - twa: { - nameSpace?: string; - packageName?: string; - sha256CertFingerprints?: string[]; - }; - - reservedUsernames?: string[]; - - // Managed hosting stuff - maxUserSignups?: number; - isManagedHosting?: boolean; - maxNoteLength?: number; - maxCaptionLength?: number; - deepl: { - managed?: boolean; - authKey?: string; - isPro?: boolean; - }; - libreTranslate: { - managed?: boolean; - apiUrl?: string; - apiKey?: string; - }; - email: { - managed?: boolean; - address?: string; - host?: string; - port?: number; - user?: string; - pass?: string; - useImplicitSslTls?: boolean; - }; - objectStorage: { - managed?: boolean; - baseUrl?: string; - bucket?: string; - prefix?: string; - endpoint?: string; - region?: string; - accessKey?: string; - secretKey?: string; - useSsl?: boolean; - connnectOverProxy?: boolean; - setPublicReadOnUpload?: boolean; - s3ForcePathStyle?: boolean; - }; - summalyProxyUrl?: string; -}; +import type { ServerConfig } from "backend-rs"; /** - * Misskeyが自動的に(ユーザーが設定した情報から推論して)設定する情報 + * Firefish が自動的に(ユーザーが設定した情報から推論して)設定する情報 */ export type Mixin = { version: string; @@ -144,4 +17,4 @@ export type Mixin = { clientEntry: string; }; -export type Config = Source & Mixin; +export type Config = ServerConfig & Mixin; diff --git a/packages/backend/src/server/well-known.ts b/packages/backend/src/server/well-known.ts index 5177c36908..fc339eaad6 100644 --- a/packages/backend/src/server/well-known.ts +++ b/packages/backend/src/server/well-known.ts @@ -74,22 +74,6 @@ router.get("/.well-known/host-meta.json", async (ctx) => { }; }); -if (config.twa != null) { - router.get("/.well-known/assetlinks.json", async (ctx) => { - ctx.set("Content-Type", "application/json"); - ctx.body = [ - { - relation: ["delegate_permission/common.handle_all_urls"], - target: { - namespace: config.twa.nameSpace, - package_name: config.twa.packageName, - sha256_cert_fingerprints: config.twa.sha256CertFingerprints, - }, - }, - ]; - }); -} - router.get("/.well-known/nodeinfo", async (ctx) => { ctx.body = { links }; }); diff --git a/packages/macro-rs/src/lib.rs b/packages/macro-rs/src/lib.rs index 668d366cb1..c1a24a93cf 100644 --- a/packages/macro-rs/src/lib.rs +++ b/packages/macro-rs/src/lib.rs @@ -7,13 +7,14 @@ pub fn export( attr: proc_macro::TokenStream, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - let attr: TokenStream = attr.into(); - let item: TokenStream = item.into(); + let attr: TokenStream = attr.into(); + let item: TokenStream = item.into(); - quote! { - #[cfg_attr(feature = "napi", macro_rs::napi(#attr))] - #item - }.into() + quote! { + #[cfg_attr(feature = "napi", macro_rs::napi(#attr))] + #item + } + .into() } /// Creates extra wrapper function for napi.