refactor (backend): port config loader to backend-rs

Co-authored-by: sup39 <dev@sup39.dev>
This commit is contained in:
naskya 2024-04-12 14:25:27 +09:00
parent 3e32fc7b04
commit e2cd25ea4f
No known key found for this signature in database
GPG key ID: 712D413B3A9FED5C
13 changed files with 324 additions and 158 deletions

20
Cargo.lock generated
View file

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

View file

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

View file

@ -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"] }

View file

@ -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<string>
allowedPrivateNetworks?: Array<string>
/** `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<string>
syslog?: SysLogConfig
proxyRemoteFiles?: boolean
mediaProxy?: string
summalyProxyUrl?: string
reservedUsernames?: Array<string>
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

View file

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

View file

@ -0,0 +1 @@
pub mod server;

View file

@ -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<String>,
pub disable_hsts: Option<bool>,
pub db: DbConfig,
pub redis: RedisConfig,
pub cache_server: Option<RedisConfig>,
pub proxy: Option<String>,
pub proxy_smtp: Option<String>,
pub proxy_bypass_hosts: Option<Vec<String>>,
pub allowed_private_networks: Option<Vec<String>>,
/// `NapiValue` is not implemented for `u64`
pub max_file_size: Option<i64>,
pub access_log: Option<String>,
pub cluster_limits: Option<WorkerConfig>,
pub cuid: Option<IdConfig>,
pub outgoing_address: Option<String>,
pub deliver_job_concurrency: Option<u32>,
pub inbox_job_concurrency: Option<u32>,
pub deliver_job_per_sec: Option<u32>,
pub inbox_job_per_sec: Option<u32>,
pub deliver_job_max_attempts: Option<u32>,
pub inbox_job_max_attempts: Option<u32>,
pub log_level: Option<Vec<String>>,
pub syslog: Option<SysLogConfig>,
pub proxy_remote_files: Option<bool>,
pub media_proxy: Option<String>,
pub summaly_proxy_url: Option<String>,
pub reserved_usernames: Option<Vec<String>>,
pub max_user_signups: Option<u32>,
pub is_managed_hosting: Option<bool>,
pub max_note_length: Option<u32>,
pub max_caption_length: Option<u32>,
pub deepl: Option<DeepLConfig>,
pub libre_translate: Option<LibreTranslateConfig>,
pub email: Option<EmailConfig>,
pub object_storage: Option<ObjectStorageConfig>,
}
#[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<bool>,
pub extra: Option<serde_json::Value>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[crate::export(object, use_nullable = false)]
pub struct RedisConfig {
pub host: String,
pub port: u16,
pub family: Option<u8>,
pub user: Option<String>,
pub pass: Option<String>,
pub tls: Option<TlsConfig>,
#[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<u32>,
pub queue: Option<u32>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
#[crate::export(object, use_nullable = false)]
pub struct IdConfig {
pub length: Option<u8>,
pub fingerprint: Option<String>,
}
#[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<bool>,
pub auth_key: Option<String>,
pub is_pro: Option<bool>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
#[crate::export(object, use_nullable = false)]
pub struct LibreTranslateConfig {
pub managed: Option<bool>,
pub api_url: Option<String>,
pub api_key: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
#[crate::export(object, use_nullable = false)]
pub struct EmailConfig {
pub managed: Option<bool>,
pub address: Option<String>,
pub host: Option<String>,
pub port: Option<u16>,
pub user: Option<String>,
pub pass: Option<String>,
pub use_implicit_ssl_tls: Option<bool>,
}
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
#[crate::export(object, use_nullable = false)]
pub struct ObjectStorageConfig {
pub managed: Option<bool>,
pub base_url: Option<String>,
pub bucket: Option<String>,
pub prefix: Option<String>,
pub endpoint: Option<String>,
pub region: Option<String>,
pub access_key: Option<String>,
pub secret_key: Option<String>,
pub use_ssl: Option<bool>,
pub connnect_over_proxy: Option<bool>,
pub set_public_read_on_upload: Option<bool>,
pub s3_force_path_style: Option<bool>,
}
#[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<ServerConfig> = Lazy::new(read_server_config);

View file

@ -1,5 +1,6 @@
pub use macro_rs::export;
pub mod config;
pub mod database;
pub mod misc;
pub mod model;

View file

@ -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",

View file

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

View file

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

View file

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

View file

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