feat: add WeChat session authentication
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
use std::{env, net::IpAddr, path::PathBuf};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub enum SpeechProviderConfig {
|
||||
Local { api_url: String },
|
||||
Tencent(TencentSpeechConfig),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct TencentSpeechConfig {
|
||||
pub app_id: u64,
|
||||
pub secret_id: String,
|
||||
@@ -14,7 +14,7 @@ pub struct TencentSpeechConfig {
|
||||
pub engine_type: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct SpeechConfig {
|
||||
pub provider: SpeechProviderConfig,
|
||||
pub request_timeout_seconds: u64,
|
||||
@@ -22,14 +22,28 @@ pub struct SpeechConfig {
|
||||
pub job_lease_seconds: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct SummaryConfig {
|
||||
pub api_url: String,
|
||||
pub api_key: Option<String>,
|
||||
pub model: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct WechatAuthConfig {
|
||||
pub app_id: String,
|
||||
pub app_secret: String,
|
||||
pub code2session_url: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AuthConfig {
|
||||
pub wechat: Option<WechatAuthConfig>,
|
||||
pub session_ttl_days: i64,
|
||||
pub allow_development_user_header: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Config {
|
||||
pub host: IpAddr,
|
||||
pub port: u16,
|
||||
@@ -39,6 +53,7 @@ pub struct Config {
|
||||
pub audio_storage_dir: PathBuf,
|
||||
pub speech: Option<SpeechConfig>,
|
||||
pub summary: Option<SummaryConfig>,
|
||||
pub auth: AuthConfig,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
@@ -58,6 +73,7 @@ impl Config {
|
||||
|
||||
let speech = speech_config()?;
|
||||
let summary = summary_config()?;
|
||||
let auth = auth_config()?;
|
||||
|
||||
Ok(Self {
|
||||
host,
|
||||
@@ -74,10 +90,41 @@ impl Config {
|
||||
.unwrap_or_else(|_| PathBuf::from("./data/audio")),
|
||||
speech,
|
||||
summary,
|
||||
auth,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn auth_config() -> Result<AuthConfig, String> {
|
||||
let app_id = optional_env("WECHAT_APP_ID");
|
||||
let app_secret = optional_env("WECHAT_APP_SECRET");
|
||||
let wechat = match (app_id, app_secret) {
|
||||
(Some(app_id), Some(app_secret)) => Some(WechatAuthConfig {
|
||||
app_id,
|
||||
app_secret,
|
||||
code2session_url: optional_env("WECHAT_CODE2SESSION_URL")
|
||||
.unwrap_or_else(|| "https://api.weixin.qq.com/sns/jscode2session".to_owned()),
|
||||
}),
|
||||
(None, None) => None,
|
||||
_ => {
|
||||
return Err(
|
||||
"WECHAT_APP_ID and WECHAT_APP_SECRET must be configured together".to_owned(),
|
||||
);
|
||||
}
|
||||
};
|
||||
let session_ttl_days = parse_env("AUTH_SESSION_TTL_DAYS", 30_i64)?;
|
||||
if !(1..=365).contains(&session_ttl_days) {
|
||||
return Err("AUTH_SESSION_TTL_DAYS must be between 1 and 365".to_owned());
|
||||
}
|
||||
let allow_development_user_header = parse_bool_env("ALLOW_DEVELOPMENT_USER_HEADER", false)?;
|
||||
|
||||
Ok(AuthConfig {
|
||||
wechat,
|
||||
session_ttl_days,
|
||||
allow_development_user_header,
|
||||
})
|
||||
}
|
||||
|
||||
fn speech_config() -> Result<Option<SpeechConfig>, String> {
|
||||
let provider = optional_env("ASR_PROVIDER").unwrap_or_else(|| "local".to_owned());
|
||||
if matches!(provider.as_str(), "disabled" | "none") {
|
||||
@@ -165,3 +212,14 @@ where
|
||||
|value| value.parse().map_err(|_| format!("{name} is invalid")),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_bool_env(name: &str, default: bool) -> Result<bool, String> {
|
||||
let Some(value) = optional_env(name) else {
|
||||
return Ok(default);
|
||||
};
|
||||
match value.to_ascii_lowercase().as_str() {
|
||||
"1" | "true" | "yes" | "on" => Ok(true),
|
||||
"0" | "false" | "no" | "off" => Ok(false),
|
||||
_ => Err(format!("{name} must be true or false")),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user