diff --git a/Makefile b/Makefile index 1e692d7..302fa19 100644 --- a/Makefile +++ b/Makefile @@ -31,3 +31,10 @@ buildweb: @cd oaweb && yarn build @rm -rf ./oab/dist/* @mv ./oaweb/dist/spa/* ./oab/dist/ + +nats: + @nats-server -c ./script/nats.cfg + +.PHONY:oab +oab: + @cd oab && cargo run -- -c ./cfg-demo.yml diff --git a/oab/Cargo.lock b/oab/Cargo.lock index 0708c9c..2b5beb9 100644 --- a/oab/Cargo.lock +++ b/oab/Cargo.lock @@ -381,12 +381,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - [[package]] name = "arrayvec" version = "0.7.4" @@ -880,6 +874,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.8" @@ -2060,7 +2064,6 @@ dependencies = [ "actix-multipart", "actix-web", "aes-gcm", - "anyhow", "async-nats", "base64 0.13.1", "block-padding", @@ -2091,6 +2094,7 @@ dependencies = [ "thiserror", "tokio", "tracing", + "tracing-appender", "tracing-subscriber", "uuid", ] @@ -3797,6 +3801,17 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" +dependencies = [ + "crossbeam-channel", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" version = "0.1.26" diff --git a/oab/Cargo.toml b/oab/Cargo.toml index 5a43a72..a2516b4 100644 --- a/oab/Cargo.toml +++ b/oab/Cargo.toml @@ -57,7 +57,7 @@ rust-embed = "8.0.0" mime_guess = "2.0.4" service-manager = "0.3.0" async-nats = "0.32.1" -anyhow = "1.0.75" bytes = "1.5.0" nkeys = "0.3.2" +tracing-appender = "0.2.2" diff --git a/oab/Makefile b/oab/Makefile index 69c3422..13b10b8 100644 --- a/oab/Makefile +++ b/oab/Makefile @@ -6,7 +6,7 @@ # run: - @cargo run + @cargo run -- -c ./cfg-demo.yml init: @cargo run -- init diff --git a/oab/cfg-demo.yml b/oab/cfg-demo.yml new file mode 100644 index 0000000..22a32ba --- /dev/null +++ b/oab/cfg-demo.yml @@ -0,0 +1,29 @@ + +uuid: FR9P5t8debxc11aFF +key: AMpjwQHwVjGsb1WC4WG6 +debug: true +server_url: 127.0.0.1:4001 +media_path: /Users/veypi/test/media +db_url: localhost:3306 +db_user: root +db_pass: '123456' +db_name: oneauth +log_dir: null +fs_root: /Users/veypi/test/media +log_level: info +nats_usr: +- UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL +- SUACQNAAFKDKRBXS62J4JYZ7DWZS7UNUQI52BOFGGBUACHTDHRQP7I66GI +nats_node: +- UAU6HPAHVIQWODQ365HMSHGZPSXJHR35T6ACURR3STGXFZNWXFNG5EA6 +- SUACZVC4UWLCKFA3DJFIYO5XYYGPJRQEKCBC773PKCD4TZS52GDU6JJ2JE +nats_sys: +- UCOKXBGDAXXQOR4XUPUJ4O22HZ2A3KQN3JLCCYM3ISSKHLBZJXXQ3NLF +- SUAEILQZDD2UT2ZNR6DCA44YCRKAZDYDOJRUPAUA7AOWFVGSSPFPCLXF24 +info: + ws_url: http://127.0.0.1:4221 + nats_url: http://127.0.0.1:4222 + api_url: http://127.0.0.1:4001 +user_init_space: 300 + + diff --git a/oab/src/api/token.rs b/oab/src/api/token.rs index 5d4316c..777561e 100644 --- a/oab/src/api/token.rs +++ b/oab/src/api/token.rs @@ -49,9 +49,9 @@ pub async fn get( let token = models::Token::from(&query.token, &key)?; if aid.starts_with("nats") { let nonce = &query.nonce.clone().unwrap(); - let u = nkeys::KeyPair::from_seed(&stat.nats_secret).unwrap(); + let u = nkeys::KeyPair::from_seed(&stat.nats_usr[1].clone()).unwrap(); let res = base64::encode(u.sign(nonce.as_bytes()).unwrap()); - return Ok(format!("{}@{}", res, &stat.nats_key)); + return Ok(format!("{}@{}", res, &stat.nats_usr[0].clone())); }; if !aid.is_empty() { // 从OA token 转向其他app token diff --git a/oab/src/cfg.rs b/oab/src/cfg.rs index 03eadde..45a504d 100644 --- a/oab/src/cfg.rs +++ b/oab/src/cfg.rs @@ -15,16 +15,17 @@ use std::{ }; use clap::{Args, Parser, Subcommand}; -use lazy_static::lazy_static; use sea_orm::{ConnectOptions, Database, DatabaseConnection}; +use serde::{Deserialize, Serialize}; use sqlx::{mysql::MySqlPoolOptions, Pool}; use tracing::{info, Level}; use crate::Result; -lazy_static! { - pub static ref CLI: AppCli = AppCli::new(); -} +// lazy_static! { +// pub static ref CLI: AppCli = AppCli::new(); +// } +// use lazy_static::lazy_static; // lazy_static! { // pub static ref CONFIG: ApplicationConfig = ApplicationConfig::new(); @@ -48,12 +49,13 @@ pub enum Clis { Start, Stop, Web, - Stash(StashData), + Dump, + Cfg(CfgOpt), } #[derive(Debug, Args)] #[clap(args_conflicts_with_subcommands = true)] -pub struct StashData { +pub struct CfgOpt { command: Option, } @@ -61,14 +63,14 @@ impl AppCli { pub fn new() -> Self { AppCli::parse() } - pub fn handle_service(&self) -> Result<()> { + pub fn handle_service(&self, data: AppState) -> Result { let label: service_manager::ServiceLabel = "v.oa".parse().unwrap(); // Get generic service by detecting what is available on the platform let manager = ::native() .expect("Failed to detect management platform"); - if let Some(c) = &CLI.command { + if let Some(c) = &self.command { match c { Clis::Install => { let p = std::env::current_exe()?; @@ -89,10 +91,15 @@ impl AppCli { Clis::Stop => manager.stop(service_manager::ServiceStopCtx { label: label.clone(), })?, - _ => {} + Clis::Dump => { + let res = serde_yaml::to_string(&data)?; + println!("{}", res); + } + _ => return Ok(false), } + return Ok(true); }; - Ok(()) + Ok(false) } } @@ -102,6 +109,14 @@ pub struct ApplicationConfig { pub db: DatabaseConnection, } +#[derive(Debug, Clone, Deserialize, Serialize, Default)] +pub struct InfoOpt { + nats_url: String, + ws_url: String, + api_url: String, + token: Option, +} + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct AppState { pub uuid: String, @@ -115,12 +130,12 @@ pub struct AppState { pub db_name: String, pub log_dir: Option, pub fs_root: String, - pub nats_key: String, - pub nats_secret: String, + pub nats_usr: [String; 2], + pub nats_node: [String; 2], + pub nats_sys: [String; 2], + + pub info: InfoOpt, - /// "100MB" 日志分割尺寸-单位KB,MB,GB - pub log_temp_size: Option, - pub log_pack_compress: Option, pub log_level: Option, pub user_init_space: i64, @@ -131,9 +146,9 @@ pub struct AppState { } impl AppState { - pub fn new() -> Self { + pub fn new(cli: &AppCli) -> Self { let mut res = Self::defaut(); - let mut f = match File::open(CLI.cfg.clone()) { + let mut f = match File::open(cli.cfg.clone()) { Ok(f) => f, Err(ref e) if e.kind() == io::ErrorKind::NotFound => { // res.connect_sqlx().unwrap(); @@ -141,17 +156,11 @@ impl AppState { } Err(e) => panic!("{}", e), }; - File::open(CLI.cfg.clone()).unwrap(); + File::open(cli.cfg.clone()).unwrap(); let mut yml_data = String::new(); f.read_to_string(&mut yml_data).unwrap(); //读取配置 res = serde_yaml::from_str(&yml_data).expect("load config file fail"); - if res.debug { - println!("load config:{:?}", res); - println!("///////////////////// Start On Debug Mode ////////////////////////////"); - } else { - println!("release_mode is enable!") - } res } pub fn defaut() -> Self { @@ -165,16 +174,30 @@ impl AppState { db_pass: "123456".to_string(), db_name: "oneauth".to_string(), log_dir: None, - log_temp_size: None, - log_pack_compress: None, media_path: "/Users/veypi/test/media".to_string(), fs_root: "/Users/veypi/test/media".to_string(), log_level: None, _sqlx: None, _db: None, - nats_key: "UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL".to_string(), - nats_secret: "SUACQNAAFKDKRBXS62J4JYZ7DWZS7UNUQI52BOFGGBUACHTDHRQP7I66GI".to_string(), + nats_usr: [ + String::from("UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL"), + String::from("SUACQNAAFKDKRBXS62J4JYZ7DWZS7UNUQI52BOFGGBUACHTDHRQP7I66GI"), + ], + nats_node: [ + String::from("UAU6HPAHVIQWODQ365HMSHGZPSXJHR35T6ACURR3STGXFZNWXFNG5EA6"), + String::from("SUACZVC4UWLCKFA3DJFIYO5XYYGPJRQEKCBC773PKCD4TZS52GDU6JJ2JE"), + ], + nats_sys: [ + String::from("UCOKXBGDAXXQOR4XUPUJ4O22HZ2A3KQN3JLCCYM3ISSKHLBZJXXQ3NLF"), + String::from("SUAEILQZDD2UT2ZNR6DCA44YCRKAZDYDOJRUPAUA7AOWFVGSSPFPCLXF24"), + ], user_init_space: 300, + info: InfoOpt { + ws_url: "http://127.0.0.1:4221".to_string(), + nats_url: "http://127.0.0.1:4222".to_string(), + api_url: "http://127.0.0.1:4001".to_string(), + token: None, + }, } } pub fn save(&self) {} @@ -232,12 +255,34 @@ impl tracing_subscriber::fmt::time::FormatTime for FormatTime { } } -pub fn init_log() { - tracing_subscriber::fmt() - .with_line_number(true) - .with_timer(FormatTime {}) - .with_max_level(Level::INFO) - // .with_target(false) - // .with_file(true) - .init(); +pub fn init_log(stat: &AppState) -> Option { + let level = stat.log_level.clone().unwrap_or("info".to_string()); + let level = match level.as_str() { + "trace" => Level::TRACE, + "debug" => Level::DEBUG, + "warn" => Level::WARN, + "error" => Level::ERROR, + "info" => Level::INFO, + _ => Level::INFO, + }; + if let Some(log_dir) = stat.log_dir.clone() { + let file_appender = tracing_appender::rolling::hourly(log_dir, "oab.log"); + let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); + tracing_subscriber::fmt() + .with_writer(non_blocking) + .with_line_number(true) + .with_timer(FormatTime {}) + .with_max_level(level) + .with_ansi(false) + .init(); + info!("asd"); + Some(_guard) + } else { + tracing_subscriber::fmt() + .with_line_number(true) + .with_timer(FormatTime {}) + .with_max_level(level) + .init(); + None + } } diff --git a/oab/src/lib.rs b/oab/src/lib.rs index 51d4d17..2fc1d1a 100644 --- a/oab/src/lib.rs +++ b/oab/src/lib.rs @@ -10,5 +10,5 @@ mod cfg; pub mod libs; pub mod models; mod result; -pub use cfg::{init_log, AppState, ApplicationConfig, Clis, CLI}; +pub use cfg::{init_log, AppCli, AppState, ApplicationConfig, Clis, InfoOpt}; pub use result::{Error, Result}; diff --git a/oab/src/main.rs b/oab/src/main.rs index fa9fab2..188b817 100644 --- a/oab/src/main.rs +++ b/oab/src/main.rs @@ -10,6 +10,7 @@ use bytes::Bytes; use actix_files as fs; use actix_web::{ dev::{self, Service}, + get, http::StatusCode, middleware::{self, ErrorHandlerResponse, ErrorHandlers}, web::{self}, @@ -20,37 +21,42 @@ use mime_guess::from_path; use rust_embed::RustEmbed; use http::{HeaderName, HeaderValue}; -use oab::{api, init_log, libs, models, AppState, Clis, Result, CLI}; +use oab::{api, init_log, libs, models, AppCli, AppState, Clis, Result}; use tracing::{error, info, warn}; #[tokio::main] async fn main() -> Result<()> { - std::env::set_var("RUST_LOG", "debug"); - std::env::set_var("RUST_BACKTRACE", "1"); - std::env::set_var("asd", "asd"); - init_log(); - let mut data = AppState::new(); - if let Some(c) = &CLI.command { + let cli = AppCli::new(); + let mut data = AppState::new(&cli); + if data.debug { + std::env::set_var("RUST_LOG", "debug"); + std::env::set_var("RUST_BACKTRACE", "1"); + } + let _log = init_log(&data); + if cli.handle_service(data.clone())? { + info!("2"); + return Ok(()); + } + if let Some(c) = &cli.command { match c { Clis::Init => { data.connect_sqlx()?; models::init(data).await; return Ok(()); } - Clis::Install | Clis::Uninstall | Clis::Start | Clis::Stop => { - return CLI.handle_service(); - } _ => {} }; }; data.connect().await?; data.connect_sqlx()?; web(data).await?; + info!("1"); + info!("12"); Ok(()) } async fn web(data: AppState) -> Result<()> { let client = match async_nats::ConnectOptions::new() - .nkey(data.nats_secret.clone()) + .nkey(data.nats_sys[1].clone()) .connect("127.0.0.1:4222") .await { @@ -88,6 +94,7 @@ async fn web(data: AppState) -> Result<()> { app.wrap(logger) .wrap(middleware::Compress::default()) .app_data(web::Data::new(data.clone())) + .service(info) .service(fs::Files::new("/media", data.media_path.clone()).show_files_listing()) .service( web::scope("api") @@ -162,3 +169,8 @@ async fn index(p: web::Path) -> impl Responder { .body(Asset::get("index.html").unwrap().data.into_owned()), } } + +#[get("/info")] +pub async fn info(stat: web::Data) -> Result { + Ok(web::Json(stat.info.clone())) +} diff --git a/oab/src/result.rs b/oab/src/result.rs index 14f31be..6c98fd4 100644 --- a/oab/src/result.rs +++ b/oab/src/result.rs @@ -126,11 +126,13 @@ pub enum Error { #[error("invalid header (expected {expected:?}, found {found:?})")] InvalidHeader { expected: String, found: String }, + // #[error("serde yaml error")] + // SerdeYamlError{#[from] serde_yaml::Error} + #[error("serde yaml error")] + SerdeYamlError(#[from] serde_yaml::Error), + #[error("unknown error")] Unknown, - - #[error(transparent)] - Other(#[from] anyhow::Error), } impl From for Error { diff --git a/script/nats.cfg b/script/nats.cfg new file mode 100644 index 0000000..2380a5b --- /dev/null +++ b/script/nats.cfg @@ -0,0 +1,53 @@ +# nats cfg +# +host: 0.0.0.0 +port: 4222 + +# 监控端口 +http: 127.0.0.1:8222 +websocket: { + listen: '0.0.0.0:4221', + no_tls: true +} + +jetstream: { +} + +accounts: { + usrs: { + users: [ + { nkey: UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL}, + ], + exports: [ + {stream: pub.>}, + {service: psrv.>}, + ], + imports: [ + {stream: {account: SYS, subject: usr.>}, prefix: a}, + ], + }, + nodes: { + users: [ + { nkey: UAU6HPAHVIQWODQ365HMSHGZPSXJHR35T6ACURR3STGXFZNWXFNG5EA6}, + ], + exports: [ + {stream: pub.>}, + {service: psrv.>}, + ], + }, + SYS: { + users: [ + { nkey: UCOKXBGDAXXQOR4XUPUJ4O22HZ2A3KQN3JLCCYM3ISSKHLBZJXXQ3NLF}, + { user: cli, password: cli}, + ], + exports: [ + {stream: usr.>}, + {stream: node.>}, + {service: usr.>}, + {service: node.>}, + ], + }, +} + +system_account: SYS + diff --git a/script/nats.yml b/script/nats.yml deleted file mode 100644 index 292ccff..0000000 --- a/script/nats.yml +++ /dev/null @@ -1,22 +0,0 @@ -# nats cfg -# -host: 127.0.0.1 -port: 4222 - -# 监控端口 -http: 127.0.0.1:8222 - -jetstream: { -} - -authorization: { - users: [ - { nkey: UCXFAAVMCPTATZUZX6H24YF6FI3NKPQBPLM6BNN2EDFPNSUUEZPNFKEL}, - { user: cli, password: cli}, - ] -} - -websocket: { - listen: '0.0.0.0:4221', - no_tls: true -}