This commit is contained in:
Ember Moth
2026-07-05 20:27:58 +08:00
commit 2744c70c5c
837 changed files with 53059 additions and 0 deletions
+512
View File
@@ -0,0 +1,512 @@
//! Adapter module — ports Go `server/adapter` package to Rust.
//!
//! Provides:
//! - [`Proxy`] per-proxy configuration struct (mirrors Go `Proxy`)
//! - [`User`] subscriber info (mirrors Go `User`)
//! - [`ClientConfig`] template-rendering config
//! - [`Client`] renders a Go-template with a sprig subset
//! - [`Adapter`] converts `Node`+`Server` entities into `Vec<Proxy>`
use std::collections::HashMap;
use anyhow::Context as _;
use base64::{engine::general_purpose::STANDARD as B64, Engine as _};
use chrono::TimeZone as _;
use crate::model::entity::node::{Node, Protocol as NodeProtocol, Server};
// ─────────────────────────────────────────────────────────────────────────────
// Proxy
// ─────────────────────────────────────────────────────────────────────────────
/// Full proxy configuration, mirroring the Go `Proxy` struct in `adapter/client.go`.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
pub struct Proxy {
pub sort: i32,
pub name: String,
pub server: String,
pub port: i32,
#[serde(rename = "Type")]
pub type_: String,
pub tags: Vec<String>,
// Security
pub security: Option<String>,
pub sni: Option<String>,
pub allow_insecure: bool,
pub fingerprint: Option<String>,
pub reality_server_addr: Option<String>,
pub reality_server_port: i32,
pub reality_private_key: Option<String>,
pub reality_public_key: Option<String>,
pub reality_short_id: Option<String>,
// Transport
pub transport: Option<String>,
pub host: Option<String>,
pub path: Option<String>,
pub service_name: Option<String>,
// Shadowsocks
pub method: Option<String>,
pub server_key: Option<String>,
pub uot: bool,
pub uot_version: i32,
// Vmess/Vless/Trojan
pub flow: Option<String>,
// Hysteria2
pub hop_ports: Option<String>,
pub hop_interval: i32,
pub obfs_password: Option<String>,
pub up_mbps: i32,
pub down_mbps: i32,
// TUIC
pub disable_sni: bool,
pub reduce_rtt: bool,
pub udp_relay_mode: Option<String>,
pub congestion_controller: Option<String>,
// AnyTLS
pub padding_scheme: Option<String>,
// Mieru
pub multiplex: Option<String>,
// Vless xhttp
pub xhttp_mode: Option<String>,
pub xhttp_extra: Option<String>,
// Encryption
pub encryption: Option<String>,
pub encryption_mode: Option<String>,
pub encryption_rtt: Option<String>,
pub encryption_ticket: Option<String>,
pub encryption_server_padding: Option<String>,
pub encryption_private_key: Option<String>,
pub encryption_client_padding: Option<String>,
pub encryption_password: Option<String>,
// ECH
pub ech_enable: bool,
pub ech_server_name: Option<String>,
// Misc
pub ratio: f64,
pub cert_mode: Option<String>,
pub cert_dns_provider: Option<String>,
pub cert_dns_env: Option<String>,
}
// ─────────────────────────────────────────────────────────────────────────────
// User
// ─────────────────────────────────────────────────────────────────────────────
/// Subscriber / user info passed to templates (mirrors Go `User`).
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
pub struct User {
pub password: String,
/// Unix timestamp (seconds).
pub expired_at: i64,
pub download: i64,
pub upload: i64,
pub traffic: i64,
pub subscribe_url: String,
}
// ─────────────────────────────────────────────────────────────────────────────
// ClientConfig
// ─────────────────────────────────────────────────────────────────────────────
/// Configuration for a [`Client`] instance.
#[derive(Debug, Clone, Default)]
pub struct ClientConfig {
pub site_name: String,
pub subscribe_name: String,
/// Output format, e.g. `"base64"`, `"yaml"`, `"json"`.
pub output_format: String,
pub params: HashMap<String, String>,
}
// ─────────────────────────────────────────────────────────────────────────────
// Client
// ─────────────────────────────────────────────────────────────────────────────
/// Renders a Go-compatible template with a sprig-subset function map.
pub struct Client {
pub config: ClientConfig,
}
impl Client {
/// Render `template` against `proxies` and `user`.
///
/// Mirrors Go `(*Client).Build()`.
pub fn build(&self, template: &str, proxies: &[Proxy], user: &User) -> anyhow::Result<String> {
let mut tmpl = gtmpl::Template::default();
// Register sprig-subset functions.
tmpl.add_func("toJson", sprig_to_json);
tmpl.add_func("b64enc", sprig_b64enc);
tmpl.add_func("date", sprig_date);
tmpl.parse(template)
.map_err(|e| anyhow::anyhow!("template parse error: {e}"))?;
// Serialize each proxy to a serde_json::Value, then lift to gtmpl::Value.
let proxy_values: Vec<gtmpl::Value> = proxies
.iter()
.map(|p| {
let json = serde_json::to_value(p)
.context("serialize Proxy to JSON")?;
Ok(json_to_gtmpl(json))
})
.collect::<anyhow::Result<_>>()?;
let user_value = json_to_gtmpl(
serde_json::to_value(user).context("serialize User to JSON")?,
);
let params_value = {
let map: HashMap<String, gtmpl::Value> = self
.config
.params
.iter()
.map(|(k, v)| (k.clone(), gtmpl::Value::String(v.clone())))
.collect();
gtmpl::Value::Map(map)
};
let mut ctx: HashMap<String, gtmpl::Value> = HashMap::new();
ctx.insert(
"SiteName".into(),
gtmpl::Value::String(self.config.site_name.clone()),
);
ctx.insert(
"SubscribeName".into(),
gtmpl::Value::String(self.config.subscribe_name.clone()),
);
ctx.insert(
"OutputFormat".into(),
gtmpl::Value::String(self.config.output_format.clone()),
);
ctx.insert("Proxies".into(), gtmpl::Value::Array(proxy_values));
ctx.insert("UserInfo".into(), user_value);
ctx.insert("Params".into(), params_value);
let rendered = tmpl
.render(&gtmpl::Context::from(gtmpl::Value::Map(ctx)))
.map_err(|e| anyhow::anyhow!("template render error: {e}"))?;
if self.config.output_format == "base64" {
return Ok(B64.encode(rendered.as_bytes()));
}
Ok(rendered)
}
}
// ─────────────────────────────────────────────────────────────────────────────
// JSON ↔ gtmpl::Value conversion
// ─────────────────────────────────────────────────────────────────────────────
fn json_to_gtmpl(v: serde_json::Value) -> gtmpl::Value {
match v {
serde_json::Value::Null => gtmpl::Value::Nil,
serde_json::Value::Bool(b) => gtmpl::Value::Bool(b),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
gtmpl::Value::Number(gtmpl_value::Number::from(i))
} else if let Some(f) = n.as_f64() {
gtmpl::Value::Number(gtmpl_value::Number::from(f))
} else {
gtmpl::Value::Number(gtmpl_value::Number::from(0_i64))
}
}
serde_json::Value::String(s) => gtmpl::Value::String(s),
serde_json::Value::Array(arr) => {
gtmpl::Value::Array(arr.into_iter().map(json_to_gtmpl).collect())
}
serde_json::Value::Object(map) => {
let m: HashMap<String, gtmpl::Value> =
map.into_iter().map(|(k, v)| (k, json_to_gtmpl(v))).collect();
gtmpl::Value::Map(m)
}
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Sprig-subset template functions
// ─────────────────────────────────────────────────────────────────────────────
/// `toJson` — serialises first argument to a JSON string.
fn sprig_to_json(args: &[gtmpl::Value]) -> Result<gtmpl::Value, gtmpl_value::FuncError> {
let v = args
.first()
.ok_or_else(|| gtmpl_value::FuncError::AtLeastXArgs("toJson".into(), 1))?;
// Convert gtmpl::Value back through serde to produce JSON.
let json_val = gtmpl_value_to_json(v.clone());
let s = serde_json::to_string(&json_val).unwrap_or_else(|_| "null".into());
Ok(gtmpl::Value::String(s))
}
/// `b64enc` — base64-encodes first argument as a UTF-8 string.
fn sprig_b64enc(args: &[gtmpl::Value]) -> Result<gtmpl::Value, gtmpl_value::FuncError> {
let v = args
.first()
.ok_or_else(|| gtmpl_value::FuncError::AtLeastXArgs("b64enc".into(), 1))?;
let s = match v {
gtmpl::Value::String(s) => s.clone(),
other => format!("{other:?}"),
};
Ok(gtmpl::Value::String(B64.encode(s.as_bytes())))
}
/// `date` — formats a Unix timestamp using a Go-style layout string.
///
/// Signature: `date <layout-string> <unix-timestamp>`
fn sprig_date(args: &[gtmpl::Value]) -> Result<gtmpl::Value, gtmpl_value::FuncError> {
if args.len() < 2 {
return Err(gtmpl_value::FuncError::AtLeastXArgs("date".into(), 2));
}
let layout = match &args[0] {
gtmpl::Value::String(s) => s.as_str(),
_ => {
return Err(gtmpl_value::FuncError::Generic(
"date: first arg must be a string layout".into(),
))
}
};
let ts: i64 = match &args[1] {
gtmpl::Value::Number(n) => n
.as_i64()
.unwrap_or_else(|| n.as_f64().map(|f| f as i64).unwrap_or(0)),
_ => {
return Err(gtmpl_value::FuncError::Generic(
"date: second arg must be a number (Unix timestamp)".into(),
))
}
};
let dt = chrono::Utc
.timestamp_opt(ts, 0)
.single()
.unwrap_or_else(chrono::Utc::now);
// Map common Go reference-time tokens to chrono format specifiers.
let chrono_fmt = go_layout_to_chrono(layout);
Ok(gtmpl::Value::String(dt.format(&chrono_fmt).to_string()))
}
/// Translate a Go time-layout string to a chrono format string.
///
/// Only the most common reference-time tokens are mapped.
fn go_layout_to_chrono(layout: &str) -> String {
layout
.replace("2006", "%Y")
.replace("01", "%m")
.replace("02", "%d")
.replace("15", "%H")
.replace("04", "%M")
.replace("05", "%S")
.replace("Jan", "%b")
.replace("Monday", "%A")
.replace("Mon", "%a")
}
/// Convert a `gtmpl::Value` to a `serde_json::Value` (best-effort).
fn gtmpl_value_to_json(v: gtmpl::Value) -> serde_json::Value {
match v {
gtmpl::Value::Nil | gtmpl::Value::NoValue => serde_json::Value::Null,
gtmpl::Value::Bool(b) => serde_json::Value::Bool(b),
gtmpl::Value::String(s) => serde_json::Value::String(s),
gtmpl::Value::Number(n) => {
if let Some(i) = n.as_i64() {
serde_json::Value::Number(i.into())
} else if let Some(f) = n.as_f64() {
serde_json::Number::from_f64(f)
.map(serde_json::Value::Number)
.unwrap_or(serde_json::Value::Null)
} else {
serde_json::Value::Null
}
}
gtmpl::Value::Array(arr) => {
serde_json::Value::Array(arr.into_iter().map(gtmpl_value_to_json).collect())
}
gtmpl::Value::Map(map) | gtmpl::Value::Object(map) => {
let obj: serde_json::Map<String, serde_json::Value> = map
.into_iter()
.map(|(k, v)| (k, gtmpl_value_to_json(v)))
.collect();
serde_json::Value::Object(obj)
}
// Functions have no meaningful JSON representation.
gtmpl::Value::Function(_) => serde_json::Value::Null,
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Adapter
// ─────────────────────────────────────────────────────────────────────────────
/// Converts node+server entities into a sorted list of [`Proxy`] values.
pub struct Adapter;
impl Adapter {
/// Build a `Vec<Proxy>` from `(Node, Server)` pairs.
///
/// Mirrors Go `(*Adapter).Proxies()`.
pub fn proxies(pairs: &[(Node, Server)]) -> Vec<Proxy> {
let mut out: Vec<Proxy> = Vec::new();
for (node, server) in pairs {
// Deserialise the JSON protocols array stored in `server.protocols`.
let protocols: Vec<NodeProtocol> = match serde_json::from_str(&server.protocols) {
Ok(v) => v,
Err(e) => {
tracing::error!(
server_id = server.id,
error = %e,
"failed to parse server protocols JSON"
);
continue;
}
};
// Find the protocol entry whose `type_` matches `node.protocol`.
let proto = match protocols.iter().find(|p| p.type_ == node.protocol) {
Some(p) => p,
None => {
tracing::warn!(
node_id = node.id,
protocol = %node.protocol,
"no matching protocol entry in server.protocols"
);
continue;
}
};
let tags: Vec<String> = if node.tags.is_empty() {
vec![]
} else {
node.tags.split(',').map(str::trim).map(String::from).collect()
};
out.push(Proxy {
sort: node.sort,
name: node.name.clone(),
server: node.address.clone(),
port: node.port,
type_: node.protocol.clone(),
tags,
security: proto.security.clone(),
sni: proto.sni.clone(),
allow_insecure: proto.allow_insecure,
fingerprint: proto.fingerprint.clone(),
reality_server_addr: proto.reality_server_addr.clone(),
reality_server_port: proto.reality_server_port,
reality_private_key: proto.reality_private_key.clone(),
reality_public_key: proto.reality_public_key.clone(),
reality_short_id: proto.reality_short_id.clone(),
transport: proto.transport.clone(),
host: proto.host.clone(),
path: proto.path.clone(),
service_name: proto.service_name.clone(),
method: proto.cipher.clone(),
server_key: proto.server_key.clone(),
uot: proto.uot,
uot_version: proto.uot_version,
flow: proto.flow.clone(),
hop_ports: proto.hop_ports.clone(),
hop_interval: proto.hop_interval,
obfs_password: proto.obfs_password.clone(),
up_mbps: proto.up_mbps,
down_mbps: proto.down_mbps,
disable_sni: proto.disable_sni,
reduce_rtt: proto.reduce_rtt,
udp_relay_mode: proto.udp_relay_mode.clone(),
congestion_controller: proto.congestion_controller.clone(),
padding_scheme: proto.padding_scheme.clone(),
multiplex: proto.multiplex.clone(),
xhttp_mode: proto.xhttp_mode.clone(),
xhttp_extra: proto.xhttp_extra.clone(),
encryption: proto.encryption.clone(),
encryption_mode: proto.encryption_mode.clone(),
encryption_rtt: proto.encryption_rtt.clone(),
encryption_ticket: proto.encryption_ticket.clone(),
encryption_server_padding: proto.encryption_server_padding.clone(),
encryption_private_key: proto.encryption_private_key.clone(),
encryption_client_padding: proto.encryption_client_padding.clone(),
encryption_password: proto.encryption_password.clone(),
ech_enable: proto.ech_enable,
ech_server_name: proto.ech_server_name.clone(),
ratio: proto.ratio,
cert_mode: proto.cert_mode.clone(),
cert_dns_provider: proto.cert_dns_provider.clone(),
cert_dns_env: proto.cert_dns_env.clone(),
});
}
// Sort by `node.sort` ascending (mirrors Go slice sort in original code).
out.sort_by_key(|p| p.sort);
out
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Tests
// ─────────────────────────────────────────────────────────────────────────────
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_proxy_default() {
let _ = Proxy::default();
}
#[test]
fn test_b64enc() {
let args = vec![gtmpl::Value::String("hello".into())];
let result = sprig_b64enc(&args).expect("b64enc should succeed");
assert_eq!(result, gtmpl::Value::String("aGVsbG8=".into()));
}
#[test]
fn test_client_build_simple() {
let config = ClientConfig {
site_name: "TestSite".into(),
subscribe_name: "TestSub".into(),
output_format: "text".into(),
params: HashMap::new(),
};
let client = Client { config };
let proxies = vec![Proxy::default(), Proxy::default()];
let user = User::default();
// Go template: render the count of proxies.
let out = client
.build("{{ len .Proxies }}", &proxies, &user)
.expect("build should succeed");
assert_eq!(out.trim(), "2");
}
#[test]
fn test_client_build_base64() {
let config = ClientConfig {
output_format: "base64".into(),
..Default::default()
};
let client = Client { config };
let out = client
.build("hello", &[], &User::default())
.expect("build should succeed");
// base64("hello") == "aGVsbG8="
assert_eq!(out, "aGVsbG8=");
}
}
+109
View File
@@ -0,0 +1,109 @@
use redis::aio::ConnectionManager;
use tokio::sync::Mutex;
use crate::config::RedisConfig;
#[derive(Clone)]
pub struct Cache {
con: std::sync::Arc<Mutex<ConnectionManager>>,
}
impl std::fmt::Debug for Cache {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Cache").finish_non_exhaustive()
}
}
impl Cache {
pub async fn new(cfg: &RedisConfig) -> Result<Self, redis::RedisError> {
let dsn = format!("redis://:{}@{}", cfg.pass, cfg.host);
let client = redis::Client::open(dsn)?;
let mut con = client.get_connection_manager().await?;
if cfg.db != 0 {
redis::cmd("SELECT")
.arg(cfg.db)
.query_async::<()>(&mut con)
.await?;
}
Ok(Self {
con: std::sync::Arc::new(Mutex::new(con)),
})
}
pub async fn get(&self, key: &str) -> Result<Option<String>, redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("GET")
.arg(key)
.query_async(&mut *con)
.await
.map(|v: Option<String>| v)
}
pub async fn set_ex(
&self,
key: &str,
value: &str,
seconds: i64,
) -> Result<(), redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("SET")
.arg(key)
.arg(value)
.arg("EX")
.arg(seconds)
.query_async(&mut *con)
.await
}
pub async fn del(&self, key: &str) -> Result<(), redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("DEL")
.arg(key)
.query_async(&mut *con)
.await
}
pub async fn exists(&self, key: &str) -> Result<bool, redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("EXISTS")
.arg(key)
.query_async(&mut *con)
.await
}
pub async fn incr(&self, key: &str) -> Result<i64, redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("INCR")
.arg(key)
.query_async(&mut *con)
.await
}
pub async fn expire(&self, key: &str, seconds: i64) -> Result<(), redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("EXPIRE")
.arg(key)
.arg(seconds)
.query_async(&mut *con)
.await
}
pub async fn get_int(&self, key: &str) -> Result<Option<i64>, redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("GET")
.arg(key)
.query_async(&mut *con)
.await
.map(|v: Option<String>| v.and_then(|s| s.parse().ok()))
}
pub async fn ttl(&self, key: &str) -> Result<i64, redis::RedisError> {
let mut con = self.con.lock().await;
redis::cmd("TTL")
.arg(key)
.query_async(&mut *con)
.await
}
}
+29
View File
@@ -0,0 +1,29 @@
//! Redis / cache key constants, ported from `server/internal/config/cacheKey.go`.
//!
//! TODO: these constants are defined ahead of the cache layer. The root
//! `Cargo.toml` does not yet pull a Redis client (e.g. `redis` / `deadpool-redis`)
//! and `config::RedisConfig` is a dead leaf until the cache service is wired
//! up. When introducing the cache layer, add the dependency and a `cache`
//! module that consumes these keys.
pub const CURRENCY_CONFIG_KEY: &str = "system:currency_config";
pub const SMS_CONFIG_KEY: &str = "system:sms_config";
pub const SITE_CONFIG_KEY: &str = "system:site_config";
pub const SUBSCRIBE_CONFIG_KEY: &str = "system:subscribe_config";
pub const REGISTER_CONFIG_KEY: &str = "system:register_config";
pub const VERIFY_CONFIG_KEY: &str = "system:verify_config";
pub const EMAIL_SMTP_CONFIG_KEY: &str = "system:email_smtp_config";
pub const NODE_CONFIG_KEY: &str = "system:node_config";
pub const INVITE_CONFIG_KEY: &str = "system:invite_config";
pub const TELEGRAM_CONFIG_KEY: &str = "system:telegram_config";
pub const ADMIN_TELEGRAM_CHAT_IDS_KEY: &str = "system:telegram_admin_chat_ids";
pub const TOS_CONFIG_KEY: &str = "system:tos_config";
pub const VERIFY_CODE_CONFIG_KEY: &str = "system:verify_code_config";
pub const SESSION_ID_KEY: &str = "auth:session_id";
pub const GLOBAL_CONFIG_KEY: &str = "system:global_config";
pub const AUTH_CODE_CACHE_KEY: &str = "auth:verify:email";
pub const AUTH_CODE_TELEPHONE_CACHE_KEY: &str = "auth:verify:telephone";
pub const COMMON_STAT_CACHE_KEY: &str = "common:stat";
pub const SERVER_COUNT_CACHE_KEY: &str = "server:count";
pub const SEND_INTERVAL_KEY_PREFIX: &str = "send:interval:";
pub const SEND_COUNT_LIMIT_KEY_PREFIX: &str = "send:limit:";
+715
View File
@@ -0,0 +1,715 @@
pub mod cache_key;
use serde::Deserialize;
use std::path::Path;
// ═══════════════════════════════════════════════════════════════════════════
// Top-level Config
// ═══════════════════════════════════════════════════════════════════════════
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Config {
#[serde(default = "default_model")]
pub model: String,
#[serde(default = "default_host")]
pub host: String,
#[serde(default = "default_port")]
pub port: u16,
#[serde(default)]
pub debug: bool,
#[serde(default)]
pub transport: TransportConfig,
#[serde(default)]
pub tls: Tls,
#[serde(rename = "JwtAuth")]
pub jwt_auth: JwtAuth,
#[serde(default)]
pub logger: LogConfig,
#[serde(default)]
pub database: DatabaseConfig,
pub mysql: Option<DatabaseConfig>,
#[serde(default)]
pub redis: RedisConfig,
#[serde(default)]
pub site: SiteConfig,
#[serde(default)]
pub node: NodeConfig,
#[serde(default)]
pub mobile: MobileConfig,
#[serde(default)]
pub email: EmailConfig,
#[serde(default)]
pub device: DeviceConfig,
#[serde(default)]
pub verify: Verify,
#[serde(rename = "VerifyCode")]
pub verify_code: VerifyCode,
#[serde(default)]
pub register: RegisterConfig,
#[serde(default)]
pub subscribe: SubscribeConfig,
#[serde(default)]
pub invite: InviteConfig,
#[serde(default)]
pub telegram: Telegram,
#[serde(default)]
pub log: Log,
#[serde(default)]
pub currency: Currency,
#[serde(default)]
pub plugin: PluginConfig,
#[serde(default)]
pub trace: TraceConfig,
#[serde(default)]
pub administrator: Administrator,
}
impl Config {
pub fn load() -> Self {
let path = std::env::var("PPANEL_CONFIG").unwrap_or_else(|_| "config.yaml".to_string());
Self::from_file(&path)
}
pub fn from_file(path: impl AsRef<Path>) -> Self {
let path = path.as_ref();
let content = std::fs::read_to_string(path).unwrap_or_else(|e| {
panic!("failed to read config file {}: {e}", path.display())
});
serde_yaml::from_str(&content).unwrap_or_else(|e| {
panic!("failed to parse config file {}: {e}", path.display())
})
}
pub fn database_config(&self) -> &DatabaseConfig {
if self.database.addr.is_some() || !self.database.dbname.is_empty() {
&self.database
} else if let Some(ref mysql) = self.mysql {
mysql
} else {
&self.database
}
}
}
// ═══════════════════════════════════════════════════════════════════════════
// Default helpers
// ═══════════════════════════════════════════════════════════════════════════
fn default_model() -> String { "prod".into() }
fn default_host() -> String { "0.0.0.0".into() }
fn default_port() -> u16 { 8080 }
// ═══════════════════════════════════════════════════════════════════════════
// Sub-config structs
// ═══════════════════════════════════════════════════════════════════════════
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct RedisConfig {
#[serde(default = "default_redis_host")]
pub host: String,
#[serde(default)]
pub pass: String,
#[serde(default)]
pub db: i32,
}
fn default_redis_host() -> String { "localhost:6379".into() }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct TransportConfig {
#[serde(default = "default_transport_driver")]
pub driver: String,
}
fn default_transport_driver() -> String { "hertz".into() }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct JwtAuth {
#[serde(default)]
pub access_secret: String,
#[serde(default = "default_access_expire")]
pub access_expire: i64,
}
fn default_access_expire() -> i64 { 604800 }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Verify {
#[serde(default)]
pub turnstile_site_key: String,
#[serde(default)]
pub turnstile_secret: String,
#[serde(default)]
pub login_verify: bool,
#[serde(default)]
pub register_verify: bool,
#[serde(default)]
pub reset_password_verify: bool,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SubscribeConfig {
#[serde(default)]
pub single_model: bool,
#[serde(default = "default_subscribe_path")]
pub subscribe_path: String,
#[serde(default)]
pub subscribe_domain: String,
#[serde(default)]
pub pan_domain: bool,
#[serde(default)]
pub user_agent_limit: bool,
#[serde(default)]
pub user_agent_list: String,
#[serde(default = "default_show_tutorial")]
pub show_tutorial: bool,
}
fn default_subscribe_path() -> String { "/v1/subscribe/config".into() }
fn default_show_tutorial() -> bool { true }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct RegisterConfig {
#[serde(default)]
pub stop_register: bool,
#[serde(default)]
pub enable_trial: bool,
#[serde(default)]
pub trial_subscribe: i64,
#[serde(default)]
pub trial_time: i64,
#[serde(default)]
pub trial_time_unit: String,
#[serde(default)]
pub ip_register_limit: i64,
#[serde(default)]
pub ip_register_limit_duration: i64,
#[serde(default)]
pub enable_ip_register_limit: bool,
}
#[derive(Debug, Clone, Deserialize)]
pub struct EmailConfig {
#[serde(rename = "Enable", default = "default_email_enable")]
pub enable: bool,
#[serde(default)]
pub platform: String,
#[serde(default)]
pub platform_config: String,
#[serde(default)]
pub enable_verify: bool,
#[serde(default)]
pub enable_notify: bool,
#[serde(default)]
pub enable_domain_suffix: bool,
#[serde(default)]
pub domain_suffix_list: String,
#[serde(default)]
pub verify_email_template: String,
#[serde(default)]
pub expiration_email_template: String,
#[serde(default)]
pub maintenance_email_template: String,
#[serde(default)]
pub traffic_exceed_email_template: String,
}
fn default_email_enable() -> bool { true }
#[derive(Debug, Clone, Deserialize)]
pub struct MobileConfig {
#[serde(rename = "Enable", default = "default_mobile_enable")]
pub enable: bool,
#[serde(default)]
pub platform: String,
#[serde(default)]
pub platform_config: String,
#[serde(default)]
pub enable_verify: bool,
#[serde(default)]
pub enable_whitelist: bool,
#[serde(default)]
pub whitelist: Vec<String>,
}
fn default_mobile_enable() -> bool { true }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct DeviceConfig {
#[serde(default = "default_device_enable")]
pub enable: bool,
#[serde(default)]
pub show_ads: bool,
#[serde(default)]
pub enable_security: bool,
#[serde(default)]
pub only_real_device: bool,
#[serde(default)]
pub security_secret: String,
}
fn default_device_enable() -> bool { true }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SiteConfig {
#[serde(default)]
pub host: String,
#[serde(default)]
pub site_name: String,
#[serde(default)]
pub site_desc: String,
#[serde(default)]
pub site_logo: String,
#[serde(default)]
pub keywords: String,
#[serde(default)]
pub custom_html: String,
#[serde(default)]
pub custom_data: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct NodeConfig {
#[serde(default)]
pub node_secret: String,
#[serde(default = "default_node_pull_interval")]
pub node_pull_interval: i64,
#[serde(default = "default_node_push_interval")]
pub node_push_interval: i64,
#[serde(default)]
pub traffic_report_threshold: i64,
#[serde(default)]
pub ip_strategy: String,
#[serde(default)]
pub dns: Vec<NodeDns>,
#[serde(default)]
pub block: Vec<String>,
#[serde(default)]
pub outbound: Vec<NodeOutbound>,
}
fn default_node_pull_interval() -> i64 { 60 }
fn default_node_push_interval() -> i64 { 60 }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct NodeDns {
pub proto: String,
pub address: String,
#[serde(default)]
pub domains: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct NodeOutbound {
pub name: String,
pub protocol: String,
pub address: String,
pub port: i64,
#[serde(default)]
pub user: String,
#[serde(default)]
pub password: String,
#[serde(default)]
pub uuid: String,
#[serde(default)]
pub cipher: String,
#[serde(default)]
pub security: String,
#[serde(default)]
pub sni: String,
#[serde(default)]
pub allow_insecure: bool,
#[serde(default)]
pub fingerprint: String,
#[serde(default)]
pub transport: String,
#[serde(default)]
pub host: String,
#[serde(default)]
pub path: String,
#[serde(default)]
pub service_name: String,
#[serde(default)]
pub flow: String,
#[serde(default)]
pub uot: bool,
#[serde(default)]
pub uot_version: i32,
#[serde(default)]
pub congestion_controller: String,
#[serde(default)]
pub udp_stream: bool,
#[serde(default)]
pub reduce_rtt: bool,
#[serde(default)]
pub heartbeat: i32,
#[serde(default)]
pub reality_public_key: String,
#[serde(default)]
pub reality_short_id: String,
#[serde(default)]
pub spider_x: String,
#[serde(default)]
pub settings: String,
#[serde(default)]
pub stream_settings: String,
#[serde(default)]
pub rules: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct InviteConfig {
#[serde(default)]
pub forced_invite: bool,
#[serde(default)]
pub referral_percentage: i64,
#[serde(default)]
pub only_first_purchase: bool,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Telegram {
#[serde(default)]
pub enable: bool,
#[serde(default)]
pub bot_id: i64,
#[serde(default)]
pub bot_name: String,
#[serde(default)]
pub bot_token: String,
#[serde(default)]
pub enable_notify: bool,
#[serde(default)]
pub web_hook_domain: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Tls {
#[serde(default)]
pub enable: bool,
#[serde(default)]
pub cert_file: String,
#[serde(default)]
pub key_file: String,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct VerifyCode {
#[serde(default = "default_verify_code_expire")]
pub expire_time: i64,
#[serde(default = "default_verify_code_limit")]
pub limit: i64,
#[serde(default = "default_verify_code_interval")]
pub interval: i64,
}
fn default_verify_code_expire() -> i64 { 300 }
fn default_verify_code_limit() -> i64 { 15 }
fn default_verify_code_interval() -> i64 { 60 }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Log {
#[serde(default = "default_log_auto_clear")]
pub auto_clear: bool,
#[serde(default = "default_log_clear_days")]
pub clear_days: i64,
}
fn default_log_auto_clear() -> bool { true }
fn default_log_clear_days() -> i64 { 7 }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Currency {
#[serde(default = "default_currency_unit")]
pub unit: String,
#[serde(default = "default_currency_symbol")]
pub symbol: String,
#[serde(default)]
pub access_key: String,
}
fn default_currency_unit() -> String { "CNY".into() }
fn default_currency_symbol() -> String { "¥".into() }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct PluginConfig {
#[serde(default = "default_plugin_enabled")]
pub enabled: bool,
#[serde(default = "default_plugin_directory")]
pub directory: String,
#[serde(default = "default_plugin_max_memory")]
pub max_memory_mb: i64,
#[serde(default = "default_plugin_timeout")]
pub timeout_sec: i64,
#[serde(default)]
pub allow_list: Vec<String>,
#[serde(default)]
pub block_list: Vec<String>,
}
fn default_plugin_enabled() -> bool { true }
fn default_plugin_directory() -> String { "plugins".into() }
fn default_plugin_max_memory() -> i64 { 64 }
fn default_plugin_timeout() -> i64 { 30 }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct Administrator {
#[serde(default = "default_admin_email")]
pub email: String,
#[serde(default = "default_admin_password")]
pub password: String,
}
fn default_admin_email() -> String { "admin@ppanel.dev".into() }
fn default_admin_password() -> String { "password".into() }
// ─── Trace / OpenTelemetry ───────────────────────────────────────────────────
/// Mirrors `pkg/trace/config.go → Config`.
///
/// Supported batcher values: `"jaeger"` | `"zipkin"` | `"otlpgrpc"` | `"otlphttp"` | `"stdout"`
/// Leave `endpoint` empty (or set `disabled = true`) to disable tracing.
#[derive(Debug, Clone, Deserialize, Default)]
#[serde(rename_all = "PascalCase")]
pub struct TraceConfig {
/// Service name reported to the tracing backend (default "ppanel").
#[serde(default = "default_trace_name")]
pub name: String,
/// Exporter endpoint URL (e.g. `http://localhost:14268/api/traces` for Jaeger HTTP).
#[serde(default)]
pub endpoint: String,
/// Fraction of traces to sample, 0.01.0 (default 1.0 = 100 %).
#[serde(default = "default_trace_sampler")]
pub sampler: f64,
/// Exporter backend: `jaeger` | `otlpgrpc` | `otlphttp` | `stdout`.
#[serde(default = "default_trace_batcher")]
pub batcher: String,
/// Extra headers forwarded to the OTLP exporter.
#[serde(default)]
pub otlp_headers: std::collections::HashMap<String, String>,
/// URL path override for OTLP HTTP (e.g. `"/v1/traces"`).
#[serde(default)]
pub otlp_http_path: String,
/// Use TLS for OTLP HTTP transport.
#[serde(default)]
pub otlp_http_secure: bool,
/// Disable tracing entirely (shortcut to skip initialisation).
#[serde(default)]
pub disabled: bool,
}
fn default_trace_name() -> String { "ppanel".into() }
fn default_trace_sampler() -> f64 { 1.0 }
fn default_trace_batcher() -> String { "stdout".into() }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct LogConfig {
#[serde(default = "default_log_service_name")]
pub service_name: String,
#[serde(default = "default_log_mode")]
pub mode: String,
#[serde(default = "default_log_encoding")]
pub encoding: String,
#[serde(default = "default_log_time_format")]
pub time_format: String,
#[serde(default = "default_log_path")]
pub path: String,
#[serde(default = "default_log_level")]
pub level: String,
#[serde(default)]
pub max_content_length: u32,
#[serde(default)]
pub compress: bool,
#[serde(default = "default_log_stat")]
pub stat: bool,
#[serde(default)]
pub keep_days: i32,
#[serde(default = "default_log_stack_cooldown")]
pub stack_cooldown_millis: i32,
#[serde(default)]
pub max_backups: i32,
#[serde(default)]
pub max_size: i32,
#[serde(default = "default_log_rotation")]
pub rotation: String,
#[serde(default = "default_log_file_time_format")]
pub file_time_format: String,
}
fn default_log_service_name() -> String { "PPanel".into() }
fn default_log_mode() -> String { "file".into() }
fn default_log_encoding() -> String { "json".into() }
fn default_log_time_format() -> String { "2006-01-02 15:04:05.000".into() }
fn default_log_path() -> String { "logs".into() }
fn default_log_level() -> String { "info".into() }
fn default_log_stat() -> bool { true }
fn default_log_stack_cooldown() -> i32 { 100 }
fn default_log_rotation() -> String { "daily".into() }
fn default_log_file_time_format() -> String { "2006-01-02T15:04:05.000Z07:00".into() }
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct DatabaseConfig {
#[serde(default = "default_db_driver")]
pub driver: String,
#[serde(default)]
pub addr: Option<String>,
#[serde(default)]
pub username: String,
#[serde(default)]
pub password: String,
#[serde(default)]
pub dbname: String,
#[serde(default = "default_db_config")]
pub config: String,
#[serde(default = "default_db_max_idle")]
pub max_idle_conns: i32,
#[serde(default = "default_db_max_open")]
pub max_open_conns: i32,
#[serde(default = "default_db_slow_threshold")]
pub slow_threshold: i64,
}
fn default_db_driver() -> String { "mysql".into() }
fn default_db_config() -> String { "charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai".into() }
fn default_db_max_idle() -> i32 { 10 }
fn default_db_max_open() -> i32 { 10 }
fn default_db_slow_threshold() -> i64 { 1000 }
// ═══════════════════════════════════════════════════════════════════════════
// Default trait — enables #[serde(default)] on all optional fields
// ═══════════════════════════════════════════════════════════════════════════
macro_rules! impl_default {
($ty:ty { $($field:ident: $val:expr),* $(,)? }) => {
impl Default for $ty {
fn default() -> Self {
Self { $($field: $val),* }
}
}
};
}
impl_default!(Config {
model: default_model(),
host: default_host(),
port: default_port(),
debug: false,
transport: TransportConfig::default(),
tls: Tls::default(),
jwt_auth: JwtAuth::default(),
logger: LogConfig::default(),
database: DatabaseConfig::default(),
mysql: None,
redis: RedisConfig::default(),
site: SiteConfig::default(),
node: NodeConfig::default(),
mobile: MobileConfig::default(),
email: EmailConfig::default(),
device: DeviceConfig::default(),
verify: Verify::default(),
verify_code: VerifyCode::default(),
register: RegisterConfig::default(),
subscribe: SubscribeConfig::default(),
invite: InviteConfig::default(),
telegram: Telegram::default(),
log: Log::default(),
currency: Currency::default(),
plugin: PluginConfig::default(),
trace: TraceConfig::default(),
administrator: Administrator::default(),
});
impl_default!(RedisConfig { host: default_redis_host(), pass: String::new(), db: 0 });
impl_default!(TransportConfig { driver: default_transport_driver() });
impl_default!(JwtAuth { access_secret: String::new(), access_expire: default_access_expire() });
impl_default!(Verify { turnstile_site_key: String::new(), turnstile_secret: String::new(), login_verify: false, register_verify: false, reset_password_verify: false });
impl_default!(SubscribeConfig { single_model: false, subscribe_path: default_subscribe_path(), subscribe_domain: String::new(), pan_domain: false, user_agent_limit: false, user_agent_list: String::new(), show_tutorial: default_show_tutorial() });
impl_default!(RegisterConfig { stop_register: false, enable_trial: false, trial_subscribe: 0, trial_time: 0, trial_time_unit: String::new(), ip_register_limit: 0, ip_register_limit_duration: 0, enable_ip_register_limit: false });
impl_default!(EmailConfig { enable: default_email_enable(), platform: String::new(), platform_config: String::new(), enable_verify: false, enable_notify: false, enable_domain_suffix: false, domain_suffix_list: String::new(), verify_email_template: String::new(), expiration_email_template: String::new(), maintenance_email_template: String::new(), traffic_exceed_email_template: String::new() });
impl_default!(MobileConfig { enable: default_mobile_enable(), platform: String::new(), platform_config: String::new(), enable_verify: false, enable_whitelist: false, whitelist: Vec::new() });
impl_default!(DeviceConfig { enable: default_device_enable(), show_ads: false, enable_security: false, only_real_device: false, security_secret: String::new() });
impl_default!(SiteConfig { host: String::new(), site_name: String::new(), site_desc: String::new(), site_logo: String::new(), keywords: String::new(), custom_html: String::new(), custom_data: String::new() });
impl_default!(NodeConfig { node_secret: String::new(), node_pull_interval: default_node_pull_interval(), node_push_interval: default_node_push_interval(), traffic_report_threshold: 0, ip_strategy: String::new(), dns: Vec::new(), block: Vec::new(), outbound: Vec::new() });
impl_default!(NodeDns { proto: String::new(), address: String::new(), domains: Vec::new() });
impl_default!(NodeOutbound { name: String::new(), protocol: String::new(), address: String::new(), port: 0, user: String::new(), password: String::new(), uuid: String::new(), cipher: String::new(), security: String::new(), sni: String::new(), allow_insecure: false, fingerprint: String::new(), transport: String::new(), host: String::new(), path: String::new(), service_name: String::new(), flow: String::new(), uot: false, uot_version: 0, congestion_controller: String::new(), udp_stream: false, reduce_rtt: false, heartbeat: 0, reality_public_key: String::new(), reality_short_id: String::new(), spider_x: String::new(), settings: String::new(), stream_settings: String::new(), rules: Vec::new() });
impl_default!(InviteConfig { forced_invite: false, referral_percentage: 0, only_first_purchase: false });
impl_default!(Telegram { enable: false, bot_id: 0, bot_name: String::new(), bot_token: String::new(), enable_notify: false, web_hook_domain: String::new() });
impl_default!(Tls { enable: false, cert_file: String::new(), key_file: String::new() });
impl_default!(VerifyCode { expire_time: default_verify_code_expire(), limit: default_verify_code_limit(), interval: default_verify_code_interval() });
impl_default!(Log { auto_clear: default_log_auto_clear(), clear_days: default_log_clear_days() });
impl_default!(Currency { unit: default_currency_unit(), symbol: default_currency_symbol(), access_key: String::new() });
impl_default!(PluginConfig { enabled: default_plugin_enabled(), directory: default_plugin_directory(), max_memory_mb: default_plugin_max_memory(), timeout_sec: default_plugin_timeout(), allow_list: Vec::new(), block_list: Vec::new() });
impl_default!(Administrator { email: default_admin_email(), password: default_admin_password() });
impl_default!(LogConfig {
service_name: default_log_service_name(),
mode: default_log_mode(),
encoding: default_log_encoding(),
time_format: default_log_time_format(),
path: default_log_path(),
level: default_log_level(),
max_content_length: 0,
compress: false,
stat: default_log_stat(),
keep_days: 0,
stack_cooldown_millis: default_log_stack_cooldown(),
max_backups: 0,
max_size: 0,
rotation: default_log_rotation(),
file_time_format: default_log_file_time_format(),
});
impl_default!(DatabaseConfig { driver: default_db_driver(), addr: None, username: String::new(), password: String::new(), dbname: String::new(), config: default_db_config(), max_idle_conns: default_db_max_idle(), max_open_conns: default_db_max_open(), slow_threshold: default_db_slow_threshold() });
+34
View File
@@ -0,0 +1,34 @@
/// Supported proxy protocols, ported from `server/internal/config/protocol.go`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Protocol {
Shadowsocks,
Trojan,
Vmess,
Vless,
}
impl Protocol {
pub fn as_str(&self) -> &'static str {
match self {
Protocol::Shadowsocks => "shadowsocks",
Protocol::Trojan => "trojan",
Protocol::Vmess => "vmess",
Protocol::Vless => "vless",
}
}
}
impl TryFrom<&str> for Protocol {
type Error = String;
fn try_from(s: &str) -> Result<Self, Self::Error> {
match s {
"shadowsocks" => Ok(Protocol::Shadowsocks),
"trojan" => Ok(Protocol::Trojan),
"vmess" => Ok(Protocol::Vmess),
"vless" => Ok(Protocol::Vless),
other => Err(format!("unknown protocol: {other}")),
}
}
}
+89
View File
@@ -0,0 +1,89 @@
//! Database connection initialisation.
//!
//! Reads the [`DatabaseConfig`] and creates a native `Pool<Postgres>` or
//! `Pool<MySql>` wrapped in [`Db`]. Using concrete pool types (instead of
//! `AnyPool`) lets each repository impl write native SQL with `$N` / `?`
//! placeholders and use `FromRow` against the correct row type.
use std::time::Duration;
use crate::config::DatabaseConfig;
use crate::repository::{Db, Dialect};
/// Build a pool + dialect wrapper from the config subsection.
pub async fn init_pool(cfg: &DatabaseConfig) -> Result<Db, sqlx::Error> {
let dsn = build_dsn(cfg);
let dialect = detect_dialect(cfg);
let max_conn = cfg.max_open_conns.max(1) as u32;
match dialect {
Dialect::Postgres => {
let pool = sqlx::postgres::PgPoolOptions::new()
.max_connections(max_conn)
.acquire_timeout(Duration::from_secs(10))
.connect(&dsn)
.await?;
Ok(Db::new_pg(pool))
}
Dialect::Mysql => {
let pool = sqlx::mysql::MySqlPoolOptions::new()
.max_connections(max_conn)
.acquire_timeout(Duration::from_secs(10))
.connect(&dsn)
.await?;
Ok(Db::new_mysql(pool))
}
}
}
// ─── DSN builder ─────────────────────────────────────────────────────────
fn build_dsn(cfg: &DatabaseConfig) -> String {
let addr = cfg
.addr
.as_deref()
.filter(|a| !a.is_empty())
.unwrap_or(match detect_dialect(cfg) {
Dialect::Postgres => "localhost:5432",
Dialect::Mysql => "localhost:3306",
});
let password = url_encode_password(&cfg.password);
let query = if cfg.config.is_empty() {
default_query(cfg)
} else {
&cfg.config
};
match detect_dialect(cfg) {
Dialect::Postgres => format!(
"postgres://{}:{}@{}/{}?{}",
cfg.username, password, addr, cfg.dbname, query,
),
Dialect::Mysql => format!(
"mysql://{}:{}@{}/{}?{}",
cfg.username, password, addr, cfg.dbname, query,
),
}
}
fn detect_dialect(cfg: &DatabaseConfig) -> Dialect {
Dialect::from_driver(&cfg.driver)
}
fn default_query(cfg: &DatabaseConfig) -> &'static str {
match detect_dialect(cfg) {
Dialect::Postgres => "sslmode=disable&TimeZone=Asia/Shanghai",
Dialect::Mysql => "charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai",
}
}
fn url_encode_password(s: &str) -> String {
s.chars()
.map(|c| match c {
'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' | '.' | '~' => c.to_string(),
' ' => "%20".into(),
other => format!("%{:02X}", other as u8),
})
.collect()
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::ads::create_ads_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_ads(
State(state): State<AppState>,
Json(req): Json<CreateAdsRequest>,
) -> HttpResult {
match create_ads_service::create_ads(state.repos.ads.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::ads::delete_ads_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_ads(
State(state): State<AppState>,
Json(req): Json<DeleteAdsRequest>,
) -> HttpResult {
match delete_ads_service::delete_ads(state.repos.ads.as_ref(), req.id).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::ads::get_ads_detail_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_ads_detail(
State(state): State<AppState>,
Query(req): Query<GetAdsDetailRequest>,
) -> HttpResult {
match get_ads_detail_service::get_ads_detail(state.repos.ads.as_ref(), req.id).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::ads::get_ads_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_ads_list(
State(state): State<AppState>,
Query(req): Query<GetAdsListRequest>,
) -> HttpResult {
match get_ads_list_service::get_ads_list(state.repos.ads.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+10
View File
@@ -0,0 +1,10 @@
mod create_ads_handler;
pub use create_ads_handler::create_ads;
mod update_ads_handler;
pub use update_ads_handler::update_ads;
mod delete_ads_handler;
pub use delete_ads_handler::delete_ads;
mod get_ads_detail_handler;
pub use get_ads_detail_handler::get_ads_detail;
mod get_ads_list_handler;
pub use get_ads_list_handler::get_ads_list;
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::ads::update_ads_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_ads(
State(state): State<AppState>,
Json(req): Json<UpdateAdsRequest>,
) -> HttpResult {
match update_ads_service::update_ads(state.repos.ads.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::announcement::create_announcement_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_announcement(
State(state): State<AppState>,
Json(req): Json<CreateAnnouncementRequest>,
) -> HttpResult {
match create_announcement_service::create_announcement(state.repos.announcement.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::announcement::delete_announcement_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_announcement(
State(state): State<AppState>,
Json(req): Json<DeleteAnnouncementRequest>,
) -> HttpResult {
match delete_announcement_service::delete_announcement(state.repos.announcement.as_ref(), req.id).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::announcement::get_announcement_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_announcement(
State(state): State<AppState>,
Query(req): Query<GetAnnouncementRequest>,
) -> HttpResult {
match get_announcement_service::get_announcement(state.repos.announcement.as_ref(), req.id).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::announcement::get_announcement_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_announcement_list(
State(state): State<AppState>,
Query(req): Query<GetAnnouncementListRequest>,
) -> HttpResult {
match get_announcement_list_service::get_announcement_list(state.repos.announcement.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+10
View File
@@ -0,0 +1,10 @@
mod create_announcement_handler;
pub use create_announcement_handler::create_announcement;
mod update_announcement_handler;
pub use update_announcement_handler::update_announcement;
mod delete_announcement_handler;
pub use delete_announcement_handler::delete_announcement;
mod get_announcement_handler;
pub use get_announcement_handler::get_announcement;
mod get_announcement_list_handler;
pub use get_announcement_list_handler::get_announcement_list;
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::announcement::update_announcement_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_announcement(
State(state): State<AppState>,
Json(req): Json<UpdateAnnouncementRequest>,
) -> HttpResult {
match update_announcement_service::update_announcement(state.repos.announcement.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,22 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::application::create_subscribe_application_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_subscribe_application(
State(state): State<AppState>,
Json(req): Json<CreateSubscribeApplicationRequest>,
) -> HttpResult {
match create_subscribe_application_service::create_subscribe_application(
state.repos.client.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,22 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::application::delete_subscribe_application_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_subscribe_application(
State(state): State<AppState>,
Json(req): Json<DeleteSubscribeApplicationRequest>,
) -> HttpResult {
match delete_subscribe_application_service::delete_subscribe_application(
state.repos.client.as_ref(),
req.id,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,21 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::application::get_subscribe_application_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_subscribe_application_list(
State(state): State<AppState>,
Query(req): Query<GetSubscribeApplicationListRequest>,
) -> HttpResult {
match get_subscribe_application_list_service::get_subscribe_application_list(
state.repos.client.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+10
View File
@@ -0,0 +1,10 @@
mod create_subscribe_application_handler;
pub use create_subscribe_application_handler::create_subscribe_application;
mod update_subscribe_application_handler;
pub use update_subscribe_application_handler::update_subscribe_application;
mod delete_subscribe_application_handler;
pub use delete_subscribe_application_handler::delete_subscribe_application;
mod get_subscribe_application_list_handler;
pub use get_subscribe_application_list_handler::get_subscribe_application_list;
mod preview_subscribe_template_handler;
pub use preview_subscribe_template_handler::preview_subscribe_template;
@@ -0,0 +1,21 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::application::preview_subscribe_template_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn preview_subscribe_template(
State(state): State<AppState>,
Query(req): Query<PreviewSubscribeTemplateRequest>,
) -> HttpResult {
match preview_subscribe_template_service::preview_subscribe_template(
state.repos.client.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,22 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::application::update_subscribe_application_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_subscribe_application(
State(state): State<AppState>,
Json(req): Json<UpdateSubscribeApplicationRequest>,
) -> HttpResult {
match update_subscribe_application_service::update_subscribe_application(
state.repos.client.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,15 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::auth::GetAuthMethodConfigRequest;
use crate::service::admin::auth_method::get_auth_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_auth_method_config(
State(state): State<AppState>,
Query(req): Query<GetAuthMethodConfigRequest>,
) -> HttpResult {
match get_auth_method_list_service::get_auth_method_config(state.repos.auth.as_ref(), req).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,13 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::auth_method::get_auth_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_auth_method_list(
State(state): State<AppState>,
) -> HttpResult {
match get_auth_method_list_service::get_auth_method_list(state.repos.auth.as_ref()).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,13 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::auth_method::get_auth_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_email_platform(
State(_state): State<AppState>,
) -> HttpResult {
match get_auth_method_list_service::get_email_platform().await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,13 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::auth_method::get_auth_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_sms_platform(
State(_state): State<AppState>,
) -> HttpResult {
match get_auth_method_list_service::get_sms_platform().await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+14
View File
@@ -0,0 +1,14 @@
mod get_auth_method_config_handler;
pub use get_auth_method_config_handler::get_auth_method_config;
mod update_auth_method_config_handler;
pub use update_auth_method_config_handler::update_auth_method_config;
mod get_auth_method_list_handler;
pub use get_auth_method_list_handler::get_auth_method_list;
mod get_email_platform_handler;
pub use get_email_platform_handler::get_email_platform;
mod get_sms_platform_handler;
pub use get_sms_platform_handler::get_sms_platform;
mod test_email_send_handler;
pub use test_email_send_handler::test_email_send;
mod test_sms_send_handler;
pub use test_sms_send_handler::test_sms_send;
@@ -0,0 +1,21 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::service::admin::auth_method::get_auth_method_list_service;
use result::http_result::{build_http_result, HttpResult};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct TestEmailSendRequest {
pub to: String,
}
pub async fn test_email_send(
State(state): State<AppState>,
Json(req): Json<TestEmailSendRequest>,
) -> HttpResult {
match get_auth_method_list_service::test_email_send(&state.config, req.to).await {
Ok(_) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,21 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::service::admin::auth_method::get_auth_method_list_service;
use result::http_result::{build_http_result, HttpResult};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct TestSmsSendRequest {
pub to: String,
}
pub async fn test_sms_send(
State(state): State<AppState>,
Json(req): Json<TestSmsSendRequest>,
) -> HttpResult {
match get_auth_method_list_service::test_sms_send(&state.config, req.to).await {
Ok(_) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::auth::UpdateAuthMethodConfigRequest;
use crate::service::admin::auth_method::get_auth_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_auth_method_config(
State(state): State<AppState>,
Json(req): Json<UpdateAuthMethodConfigRequest>,
) -> HttpResult {
match get_auth_method_list_service::update_auth_method_config(state.repos.auth.as_ref(), req).await {
Ok(_) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+8
View File
@@ -0,0 +1,8 @@
mod query_revenue_statistics_handler;
pub use query_revenue_statistics_handler::query_revenue_statistics;
mod query_server_total_data_handler;
pub use query_server_total_data_handler::query_server_total_data;
mod query_ticket_wait_reply_handler;
pub use query_ticket_wait_reply_handler::query_ticket_wait_reply;
mod query_user_statistics_handler;
pub use query_user_statistics_handler::query_user_statistics;
@@ -0,0 +1,14 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::console::query_revenue_statistics_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn query_revenue_statistics(State(state): State<AppState>) -> HttpResult {
match query_revenue_statistics_service::query_revenue_statistics(state.repos.order.as_ref())
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,12 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::console::query_server_total_data_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn query_server_total_data(State(state): State<AppState>) -> HttpResult {
match query_server_total_data_service::query_server_total_data(&state.repos).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,14 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::console::query_ticket_wait_reply_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn query_ticket_wait_reply(State(state): State<AppState>) -> HttpResult {
match query_ticket_wait_reply_service::query_ticket_wait_reply(state.repos.ticket.as_ref())
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::console::query_user_statistics_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn query_user_statistics(State(state): State<AppState>) -> HttpResult {
match query_user_statistics_service::query_user_statistics(
state.repos.user.as_ref(),
state.repos.order.as_ref(),
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::coupon::batch_delete_coupon_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn batch_delete_coupon(
State(state): State<AppState>,
Json(req): Json<BatchDeleteCouponRequest>,
) -> HttpResult {
match batch_delete_coupon_service::batch_delete_coupon(state.repos.coupon.as_ref(), req).await {
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::coupon::create_coupon_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_coupon(
State(state): State<AppState>,
Json(req): Json<CreateCouponRequest>,
) -> HttpResult {
match create_coupon_service::create_coupon(state.repos.coupon.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::coupon::delete_coupon_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_coupon(
State(state): State<AppState>,
Json(req): Json<DeleteCouponRequest>,
) -> HttpResult {
match delete_coupon_service::delete_coupon(state.repos.coupon.as_ref(), req.id).await {
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::coupon::get_coupon_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_coupon_list(
State(state): State<AppState>,
Query(req): Query<GetCouponListRequest>,
) -> HttpResult {
match get_coupon_list_service::get_coupon_list(state.repos.coupon.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+10
View File
@@ -0,0 +1,10 @@
mod create_coupon_handler;
pub use create_coupon_handler::create_coupon;
mod update_coupon_handler;
pub use update_coupon_handler::update_coupon;
mod delete_coupon_handler;
pub use delete_coupon_handler::delete_coupon;
mod batch_delete_coupon_handler;
pub use batch_delete_coupon_handler::batch_delete_coupon;
mod get_coupon_list_handler;
pub use get_coupon_list_handler::get_coupon_list;
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::coupon::update_coupon_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_coupon(
State(state): State<AppState>,
Json(req): Json<UpdateCouponRequest>,
) -> HttpResult {
match update_coupon_service::update_coupon(state.repos.coupon.as_ref(), req).await {
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,19 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::document::batch_delete_document_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn batch_delete_document(
State(state): State<AppState>,
Json(req): Json<BatchDeleteDocumentRequest>,
) -> HttpResult {
match batch_delete_document_service::batch_delete_document(state.repos.document.as_ref(), req)
.await
{
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::document::create_document_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_document(
State(state): State<AppState>,
Json(req): Json<CreateDocumentRequest>,
) -> HttpResult {
match create_document_service::create_document(state.repos.document.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::document::delete_document_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_document(
State(state): State<AppState>,
Json(req): Json<DeleteDocumentRequest>,
) -> HttpResult {
match delete_document_service::delete_document(state.repos.document.as_ref(), req.id).await {
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,18 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::document::get_document_detail_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_document_detail(
State(state): State<AppState>,
Query(req): Query<GetDocumentDetailRequest>,
) -> HttpResult {
match get_document_detail_service::get_document_detail(state.repos.document.as_ref(), req.id)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::document::get_document_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_document_list(
State(state): State<AppState>,
Query(req): Query<GetDocumentListRequest>,
) -> HttpResult {
match get_document_list_service::get_document_list(state.repos.document.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+12
View File
@@ -0,0 +1,12 @@
mod create_document_handler;
pub use create_document_handler::create_document;
mod update_document_handler;
pub use update_document_handler::update_document;
mod delete_document_handler;
pub use delete_document_handler::delete_document;
mod batch_delete_document_handler;
pub use batch_delete_document_handler::batch_delete_document;
mod get_document_detail_handler;
pub use get_document_detail_handler::get_document_detail;
mod get_document_list_handler;
pub use get_document_list_handler::get_document_list;
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::document::update_document_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_document(
State(state): State<AppState>,
Json(req): Json<UpdateDocumentRequest>,
) -> HttpResult {
match update_document_service::update_document(state.repos.document.as_ref(), req).await {
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_balance_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_balance_log(
State(state): State<AppState>,
Query(req): Query<FilterBalanceLogRequest>,
) -> HttpResult {
match filter_balance_log_service::filter_balance_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_commission_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_commission_log(
State(state): State<AppState>,
Query(req): Query<FilterCommissionLogRequest>,
) -> HttpResult {
match filter_commission_log_service::filter_commission_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,14 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::service::admin::log::filter_balance_log_service::{self, FilterEmailMobileLogRequest};
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_email_log(
State(state): State<AppState>,
Query(req): Query<FilterEmailMobileLogRequest>,
) -> HttpResult {
match filter_balance_log_service::filter_email_log(state.repos.log.as_ref(), req).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_gift_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_gift_log(
State(state): State<AppState>,
Query(req): Query<FilterGiftLogRequest>,
) -> HttpResult {
match filter_gift_log_service::filter_gift_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_login_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_login_log(
State(state): State<AppState>,
Query(req): Query<FilterLoginLogRequest>,
) -> HttpResult {
match filter_login_log_service::filter_login_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,14 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::service::admin::log::filter_balance_log_service::{self, FilterEmailMobileLogRequest};
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_mobile_log(
State(state): State<AppState>,
Query(req): Query<FilterEmailMobileLogRequest>,
) -> HttpResult {
match filter_balance_log_service::filter_mobile_log(state.repos.log.as_ref(), req).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_register_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_register_log(
State(state): State<AppState>,
Query(req): Query<FilterRegisterLogRequest>,
) -> HttpResult {
match filter_register_log_service::filter_register_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_reset_subscribe_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_reset_subscribe_log(
State(state): State<AppState>,
Query(req): Query<FilterResetSubscribeLogRequest>,
) -> HttpResult {
match filter_reset_subscribe_log_service::filter_reset_subscribe_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_server_traffic_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_server_traffic_log(
State(state): State<AppState>,
Query(req): Query<FilterServerTrafficLogRequest>,
) -> HttpResult {
match filter_server_traffic_log_service::filter_server_traffic_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::log::filter_subscribe_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_subscribe_log(
State(state): State<AppState>,
Query(req): Query<FilterSubscribeLogRequest>,
) -> HttpResult {
match filter_subscribe_log_service::filter_subscribe_log(state.repos.log.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,15 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::log::FilterTrafficLogDetailsRequest;
use crate::service::admin::log::filter_balance_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_traffic_log_details(
State(state): State<AppState>,
Query(req): Query<FilterTrafficLogDetailsRequest>,
) -> HttpResult {
match filter_balance_log_service::filter_traffic_log_details(state.repos.log.as_ref(), req).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,15 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::service::admin::log::filter_balance_log_service;
use crate::model::dto::log::FilterSubscribeTrafficRequest;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_user_subscribe_traffic_log(
State(state): State<AppState>,
Query(req): Query<FilterSubscribeTrafficRequest>,
) -> HttpResult {
match filter_balance_log_service::filter_user_subscribe_traffic_log(state.repos.log.as_ref(), req).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,13 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::log::filter_balance_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_log_setting(
State(state): State<AppState>,
) -> HttpResult {
match filter_balance_log_service::get_log_setting(&state.config).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,15 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::log::GetMessageLogListRequest;
use crate::service::admin::log::filter_balance_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_message_log_list(
State(state): State<AppState>,
Query(req): Query<GetMessageLogListRequest>,
) -> HttpResult {
match filter_balance_log_service::get_message_log_list(state.repos.log.as_ref(), req).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+30
View File
@@ -0,0 +1,30 @@
mod filter_balance_log_handler;
pub use filter_balance_log_handler::filter_balance_log;
mod filter_commission_log_handler;
pub use filter_commission_log_handler::filter_commission_log;
mod filter_email_log_handler;
pub use filter_email_log_handler::filter_email_log;
mod filter_gift_log_handler;
pub use filter_gift_log_handler::filter_gift_log;
mod filter_login_log_handler;
pub use filter_login_log_handler::filter_login_log;
mod filter_mobile_log_handler;
pub use filter_mobile_log_handler::filter_mobile_log;
mod filter_register_log_handler;
pub use filter_register_log_handler::filter_register_log;
mod filter_reset_subscribe_log_handler;
pub use filter_reset_subscribe_log_handler::filter_reset_subscribe_log;
mod filter_server_traffic_log_handler;
pub use filter_server_traffic_log_handler::filter_server_traffic_log;
mod filter_subscribe_log_handler;
pub use filter_subscribe_log_handler::filter_subscribe_log;
mod filter_traffic_log_details_handler;
pub use filter_traffic_log_details_handler::filter_traffic_log_details;
mod filter_user_subscribe_traffic_log_handler;
pub use filter_user_subscribe_traffic_log_handler::filter_user_subscribe_traffic_log;
mod get_log_setting_handler;
pub use get_log_setting_handler::get_log_setting;
mod get_message_log_list_handler;
pub use get_message_log_list_handler::get_message_log_list;
mod update_log_setting_handler;
pub use update_log_setting_handler::update_log_setting;
@@ -0,0 +1,16 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::log::LogSetting;
use crate::service::admin::log::filter_balance_log_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_log_setting(
State(state): State<AppState>,
Json(req): Json<LogSetting>,
) -> HttpResult {
match filter_balance_log_service::update_log_setting(&state.config, req).await {
Ok(_) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,23 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::create_batch_send_email_task_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_batch_send_email_task(
State(state): State<AppState>,
Json(req): Json<CreateBatchSendEmailTaskRequest>,
) -> HttpResult {
match create_batch_send_email_task_service::create_batch_send_email_task(
state.repos.task.as_ref(),
&state.config,
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::create_quota_task_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_quota_task(
State(state): State<AppState>,
Json(req): Json<CreateQuotaTaskRequest>,
) -> HttpResult {
match create_quota_task_service::create_quota_task(state.repos.task.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,21 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::get_batch_send_email_task_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_batch_send_email_task_list(
State(state): State<AppState>,
Query(req): Query<GetBatchSendEmailTaskListRequest>,
) -> HttpResult {
match get_batch_send_email_task_list_service::get_batch_send_email_task_list(
state.repos.task.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,22 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::get_batch_send_email_task_status_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_batch_send_email_task_status(
State(state): State<AppState>,
Json(req): Json<GetBatchSendEmailTaskStatusRequest>,
) -> HttpResult {
match get_batch_send_email_task_status_service::get_batch_send_email_task_status(
state.repos.task.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,22 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::get_pre_send_email_count_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_pre_send_email_count(
State(state): State<AppState>,
Json(req): Json<GetPreSendEmailCountRequest>,
) -> HttpResult {
match get_pre_send_email_count_service::get_pre_send_email_count(
state.repos.user.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+18
View File
@@ -0,0 +1,18 @@
mod create_batch_send_email_task_handler;
pub use create_batch_send_email_task_handler::create_batch_send_email_task;
mod create_quota_task_handler;
pub use create_quota_task_handler::create_quota_task;
mod get_batch_send_email_task_list_handler;
pub use get_batch_send_email_task_list_handler::get_batch_send_email_task_list;
mod get_batch_send_email_task_status_handler;
pub use get_batch_send_email_task_status_handler::get_batch_send_email_task_status;
mod get_pre_send_email_count_handler;
pub use get_pre_send_email_count_handler::get_pre_send_email_count;
mod query_quota_task_list_handler;
pub use query_quota_task_list_handler::query_quota_task_list;
mod query_quota_task_pre_count_handler;
pub use query_quota_task_pre_count_handler::query_quota_task_pre_count;
mod query_quota_task_status_handler;
pub use query_quota_task_status_handler::query_quota_task_status;
mod stop_batch_send_email_task_handler;
pub use stop_batch_send_email_task_handler::stop_batch_send_email_task;
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::query_quota_task_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn query_quota_task_list(
State(state): State<AppState>,
Query(req): Query<QueryQuotaTaskListRequest>,
) -> HttpResult {
match query_quota_task_list_service::query_quota_task_list(state.repos.task.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,22 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::query_quota_task_pre_count_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn query_quota_task_pre_count(
State(state): State<AppState>,
Json(req): Json<QueryQuotaTaskPreCountRequest>,
) -> HttpResult {
match query_quota_task_pre_count_service::query_quota_task_pre_count(
state.repos.user.as_ref(),
req,
)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,19 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::query_quota_task_status_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn query_quota_task_status(
State(state): State<AppState>,
Json(req): Json<QueryQuotaTaskStatusRequest>,
) -> HttpResult {
match query_quota_task_status_service::query_quota_task_status(state.repos.task.as_ref(), req)
.await
{
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,22 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::marketing::stop_batch_send_email_task_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn stop_batch_send_email_task(
State(state): State<AppState>,
Json(req): Json<StopBatchSendEmailTaskRequest>,
) -> HttpResult {
match stop_batch_send_email_task_service::stop_batch_send_email_task(
state.repos.task.as_ref(),
req,
)
.await
{
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+18
View File
@@ -0,0 +1,18 @@
pub mod ads;
pub mod announcement;
pub mod application;
pub mod auth_method;
pub mod console;
pub mod coupon;
pub mod document;
pub mod log;
pub mod marketing;
pub mod order;
pub mod payment;
pub mod plugin;
pub mod server;
pub mod subscribe;
pub mod system;
pub mod ticket;
pub mod tool;
pub mod user;
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::order::create_order_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_order(
State(state): State<AppState>,
Json(req): Json<CreateOrderRequest>,
) -> HttpResult {
match create_order_service::create_order(state.repos.order.as_ref(), req).await {
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::order::get_order_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_order_list(
State(state): State<AppState>,
Query(req): Query<GetOrderListRequest>,
) -> HttpResult {
match get_order_list_service::get_order_list(state.repos.order.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+6
View File
@@ -0,0 +1,6 @@
mod create_order_handler;
pub use create_order_handler::create_order;
mod get_order_list_handler;
pub use get_order_list_handler::get_order_list;
mod update_order_status_handler;
pub use update_order_status_handler::update_order_status;
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::order::update_order_status_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_order_status(
State(state): State<AppState>,
Json(req): Json<UpdateOrderStatusRequest>,
) -> HttpResult {
match update_order_status_service::update_order_status(state.repos.order.as_ref(), req).await {
Ok(()) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::payment::CreatePaymentMethodRequest;
use crate::service::admin::payment::get_payment_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_payment_method(
State(state): State<AppState>,
Json(req): Json<CreatePaymentMethodRequest>,
) -> HttpResult {
match get_payment_method_list_service::create_payment_method(state.repos.payment.as_ref(), req).await {
Ok(_) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::payment::DeletePaymentMethodRequest;
use crate::service::admin::payment::get_payment_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_payment_method(
State(state): State<AppState>,
Json(req): Json<DeletePaymentMethodRequest>,
) -> HttpResult {
match get_payment_method_list_service::delete_payment_method(state.repos.payment.as_ref(), req).await {
Ok(_) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,15 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::payment::GetPaymentMethodListRequest;
use crate::service::admin::payment::get_payment_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_payment_method_list(
State(state): State<AppState>,
Query(req): Query<GetPaymentMethodListRequest>,
) -> HttpResult {
match get_payment_method_list_service::get_payment_method_list(state.repos.payment.as_ref(), req).await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,13 @@
use axum::extract::State;
use crate::handler::AppState;
use crate::service::admin::payment::get_payment_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn get_payment_platform(
State(_state): State<AppState>,
) -> HttpResult {
match get_payment_method_list_service::get_payment_platform().await {
Ok(d) => build_http_result(Some(d), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+10
View File
@@ -0,0 +1,10 @@
mod create_payment_method_handler;
pub use create_payment_method_handler::create_payment_method;
mod update_payment_method_handler;
pub use update_payment_method_handler::update_payment_method;
mod delete_payment_method_handler;
pub use delete_payment_method_handler::delete_payment_method;
mod get_payment_method_list_handler;
pub use get_payment_method_list_handler::get_payment_method_list;
mod get_payment_platform_handler;
pub use get_payment_platform_handler::get_payment_platform;
@@ -0,0 +1,16 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::payment::UpdatePaymentMethodRequest;
use crate::service::admin::payment::get_payment_method_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn update_payment_method(
State(state): State<AppState>,
Json(req): Json<UpdatePaymentMethodRequest>,
) -> HttpResult {
match get_payment_method_list_service::update_payment_method(state.repos.payment.as_ref(), req).await {
Ok(_) => build_http_result(Some(()), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
+1
View File
@@ -0,0 +1 @@
// Plugin API types and helpers
+7
View File
@@ -0,0 +1,7 @@
use result::http_result::HttpResult;
pub async fn detail(
) -> HttpResult {
todo!()
}
+7
View File
@@ -0,0 +1,7 @@
use result::http_result::HttpResult;
pub async fn disable_handler(
) -> HttpResult {
todo!()
}
+7
View File
@@ -0,0 +1,7 @@
use result::http_result::HttpResult;
pub async fn enable_handler(
) -> HttpResult {
todo!()
}
+7
View File
@@ -0,0 +1,7 @@
use result::http_result::HttpResult;
pub async fn list(
) -> HttpResult {
todo!()
}
+11
View File
@@ -0,0 +1,11 @@
mod api;
mod detail;
pub use detail::detail;
mod disable;
pub use disable::disable_handler;
mod enable;
pub use enable::enable_handler;
mod list;
pub use list::list;
mod reload;
pub use reload::reload_handler;
+7
View File
@@ -0,0 +1,7 @@
use result::http_result::HttpResult;
pub async fn reload_handler(
) -> HttpResult {
todo!()
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::server::create_node_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_node(
State(state): State<AppState>,
Json(req): Json<CreateNodeRequest>,
) -> HttpResult {
match create_node_service::create_node(state.repos.node.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::server::create_server_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn create_server(
State(state): State<AppState>,
Json(req): Json<CreateServerRequest>,
) -> HttpResult {
match create_server_service::create_server(state.repos.node.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::server::delete_node_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_node(
State(state): State<AppState>,
Json(req): Json<DeleteNodeRequest>,
) -> HttpResult {
match delete_node_service::delete_node(state.repos.node.as_ref(), req.id).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,17 @@
use axum::extract::State;
use axum::Json;
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::server::delete_server_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn delete_server(
State(state): State<AppState>,
Json(req): Json<DeleteServerRequest>,
) -> HttpResult {
match delete_server_service::delete_server(state.repos.node.as_ref(), req.id).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,15 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::service::admin::server::filter_node_list_service::{self, FilterNodeListRequest};
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_node_list(
State(state): State<AppState>,
Query(req): Query<FilterNodeListRequest>,
) -> HttpResult {
match filter_node_list_service::filter_node_list(state.repos.node.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}
@@ -0,0 +1,16 @@
use axum::extract::{Query, State};
use crate::handler::AppState;
use crate::model::dto::*;
use crate::service::admin::server::filter_server_list_service;
use result::http_result::{build_http_result, HttpResult};
pub async fn filter_server_list(
State(state): State<AppState>,
Query(req): Query<FilterServerListRequest>,
) -> HttpResult {
match filter_server_list_service::filter_server_list(state.repos.node.as_ref(), req).await {
Ok(data) => build_http_result(Some(data), None),
Err(e) => build_http_result::<()>(None, Some(e)),
}
}

Some files were not shown because too many files have changed in this diff Show More