2024-11-19 00:20:31 +08:00
|
|
|
mod config;
|
|
|
|
mod database;
|
2024-11-20 19:53:18 +08:00
|
|
|
mod auth;
|
|
|
|
mod utils;
|
|
|
|
mod routes;
|
2024-11-19 00:20:31 +08:00
|
|
|
use chrono::Duration;
|
|
|
|
use database::relational;
|
2024-11-20 19:53:18 +08:00
|
|
|
use rocket::{
|
|
|
|
get, post,
|
|
|
|
http::Status,
|
|
|
|
launch,
|
|
|
|
response::status,
|
|
|
|
State,
|
|
|
|
};
|
2024-11-19 00:20:31 +08:00
|
|
|
use std::sync::Arc;
|
|
|
|
use tokio::sync::Mutex;
|
2024-11-11 19:31:40 +08:00
|
|
|
|
2024-11-20 19:53:18 +08:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum AppError {
|
|
|
|
Database(String),
|
|
|
|
Config(String),
|
|
|
|
Auth(String),
|
|
|
|
}
|
2024-11-09 00:05:18 +08:00
|
|
|
|
2024-11-20 19:53:18 +08:00
|
|
|
impl From<AppError> for status::Custom<String> {
|
|
|
|
fn from(error: AppError) -> Self {
|
|
|
|
match error {
|
|
|
|
AppError::Database(msg) => status::Custom(Status::InternalServerError, format!("Database error: {}", msg)),
|
|
|
|
AppError::Config(msg) => status::Custom(Status::InternalServerError, format!("Config error: {}", msg)),
|
|
|
|
AppError::Auth(msg) => status::Custom(Status::InternalServerError, format!("Auth error: {}", msg)),
|
|
|
|
}
|
|
|
|
}
|
2024-11-09 00:05:18 +08:00
|
|
|
}
|
2024-11-11 19:31:40 +08:00
|
|
|
|
2024-11-20 19:53:18 +08:00
|
|
|
type AppResult<T> = Result<T, AppError>;
|
|
|
|
|
|
|
|
struct AppState {
|
|
|
|
db: Arc<Mutex<Option<relational::Database>>>,
|
|
|
|
configure: Arc<Mutex<config::Config>>,
|
2024-11-09 00:05:18 +08:00
|
|
|
}
|
2024-11-11 19:31:40 +08:00
|
|
|
|
2024-11-20 19:53:18 +08:00
|
|
|
impl AppState {
|
|
|
|
async fn get_sql(&self) -> AppResult<relational::Database> {
|
|
|
|
self.db
|
|
|
|
.lock()
|
|
|
|
.await
|
|
|
|
.clone()
|
|
|
|
.ok_or_else(|| AppError::Database("Database not initialized".into()))
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn link_sql(&self, config: config::SqlConfig) -> AppResult<()> {
|
|
|
|
let database = relational::Database::link(config)
|
|
|
|
.await
|
|
|
|
.map_err(|e| AppError::Database(e.to_string()))?;
|
|
|
|
*self.db.lock().await = Some(database);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-11-09 00:05:18 +08:00
|
|
|
}
|
2024-11-11 19:31:40 +08:00
|
|
|
|
2024-11-20 19:53:18 +08:00
|
|
|
|
|
|
|
|
2024-11-18 01:09:28 +08:00
|
|
|
#[get("/system")]
|
2024-11-20 19:53:18 +08:00
|
|
|
async fn token_system(_state: &State<AppState>) -> Result<status::Custom<String>, status::Custom<String>> {
|
|
|
|
let claims = auth::jwt::CustomClaims {
|
|
|
|
user_id: "system".into(),
|
|
|
|
device_ua: "system".into(),
|
2024-11-18 01:09:28 +08:00
|
|
|
};
|
2024-11-20 19:53:18 +08:00
|
|
|
|
|
|
|
auth::jwt::generate_jwt(claims, Duration::seconds(1))
|
|
|
|
.map(|token| status::Custom(Status::Ok, token))
|
|
|
|
.map_err(|e| AppError::Auth(e.to_string()).into())
|
2024-11-18 01:09:28 +08:00
|
|
|
}
|
|
|
|
|
2024-11-20 19:53:18 +08:00
|
|
|
|
2024-11-09 00:05:18 +08:00
|
|
|
#[launch]
|
|
|
|
async fn rocket() -> _ {
|
2024-11-19 00:20:31 +08:00
|
|
|
let config = config::Config::read().expect("Failed to read config");
|
2024-11-20 19:53:18 +08:00
|
|
|
|
|
|
|
let state = AppState {
|
|
|
|
db: Arc::new(Mutex::new(None)),
|
|
|
|
configure: Arc::new(Mutex::new(config.clone())),
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut rocket_builder = rocket::build().manage(state);
|
2024-11-18 19:14:37 +08:00
|
|
|
|
|
|
|
if config.info.install {
|
2024-11-20 19:53:18 +08:00
|
|
|
if let Some(state) = rocket_builder.state::<AppState>() {
|
|
|
|
state.link_sql(config.sql_config.clone())
|
|
|
|
.await
|
|
|
|
.expect("Failed to connect to database");
|
|
|
|
}
|
2024-11-18 19:14:37 +08:00
|
|
|
}
|
2024-11-20 19:53:18 +08:00
|
|
|
|
|
|
|
if ! config.info.install {
|
|
|
|
rocket_builder = rocket_builder
|
|
|
|
.mount("/", rocket::routes![routes::install]);
|
|
|
|
}
|
|
|
|
|
|
|
|
rocket_builder = rocket_builder
|
|
|
|
.mount("/auth/token", routes![token_system]);
|
|
|
|
|
|
|
|
rocket_builder
|
|
|
|
}
|