127 lines
3.3 KiB
Rust
127 lines
3.3 KiB
Rust
use actix_cors::Cors;
|
|
use actix_web::{http::header, middleware, web, App, HttpRequest, HttpResponse, HttpServer};
|
|
use anyhow::Result;
|
|
use diesel::prelude::*;
|
|
use std::fs;
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
#[cfg(not(target_env = "msvc"))]
|
|
use tikv_jemallocator::Jemalloc;
|
|
use uuidv7::Uuid;
|
|
|
|
use juniper_actix::graphql_handler;
|
|
|
|
use fiddle::{api, db, init, prune_job, prune_many, CONFIG};
|
|
|
|
#[cfg(not(target_env = "msvc"))]
|
|
#[global_allocator]
|
|
static GLOBAL: Jemalloc = Jemalloc;
|
|
|
|
fn tamper_prune() -> Result<()> {
|
|
let db_conn = &mut db::POOL.get()?;
|
|
|
|
let entries = fs::read_dir(&CONFIG.data_dir)?;
|
|
let allowed: Vec<String> = db::schema::directories::table
|
|
.select(db::schema::directories::id)
|
|
.load::<Uuid>(db_conn)?
|
|
.iter()
|
|
.map(|id| id.to_string())
|
|
.collect();
|
|
let mut prunes: Vec<String> = vec![];
|
|
|
|
for p in entries {
|
|
let path = match p {
|
|
Ok(x) => x.path(),
|
|
Err(e) => {
|
|
log::error!("{:?}", e);
|
|
continue;
|
|
}
|
|
};
|
|
let relative = match path.strip_prefix(&CONFIG.data_dir) {
|
|
Ok(x) => x.to_string_lossy().to_string(),
|
|
Err(e) => {
|
|
log::error!("{:?}", e);
|
|
continue;
|
|
}
|
|
};
|
|
|
|
if path.is_file() || (path.is_dir() && !allowed.contains(&relative)) {
|
|
log::warn!("Invalid entry found: {}", relative);
|
|
prunes.push(relative);
|
|
}
|
|
}
|
|
|
|
prune_many(&prunes)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn not_found() -> &'static str {
|
|
"Not found!"
|
|
}
|
|
|
|
async fn graphql_route(
|
|
req: HttpRequest,
|
|
payload: web::Payload,
|
|
schema: web::Data<api::Schema>,
|
|
) -> Result<HttpResponse, actix_web::Error> {
|
|
let context = api::Context {
|
|
db_pool: db::POOL.clone(),
|
|
loaders: api::context::Loaders::default(),
|
|
};
|
|
|
|
graphql_handler(&schema, &context, req, payload).await
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
env_logger::init();
|
|
|
|
init();
|
|
|
|
thread::spawn(move || {
|
|
let sleep_dur = Duration::from_secs(CONFIG.auto_prune_sleep);
|
|
loop {
|
|
prune_job();
|
|
thread::sleep(sleep_dur);
|
|
}
|
|
});
|
|
|
|
thread::spawn(move || {
|
|
let sleep_dur = Duration::from_secs(CONFIG.tamper_sleep);
|
|
loop {
|
|
if let Err(e) = tamper_prune() {
|
|
log::error!("{:?}", e);
|
|
}
|
|
thread::sleep(sleep_dur);
|
|
}
|
|
});
|
|
|
|
HttpServer::new(move || {
|
|
App::new()
|
|
.app_data(web::Data::new(api::schema()))
|
|
.wrap(middleware::Logger::default())
|
|
.wrap(middleware::Compress::default())
|
|
.wrap(
|
|
Cors::default()
|
|
.allow_any_origin()
|
|
.allowed_methods(["POST", "GET"])
|
|
.allowed_headers([header::ACCEPT])
|
|
.allowed_header(header::CONTENT_TYPE)
|
|
.supports_credentials()
|
|
.max_age(3600),
|
|
)
|
|
.service(
|
|
web::resource("/graphql")
|
|
.route(web::post().to(graphql_route))
|
|
.route(web::get().to(graphql_route)),
|
|
)
|
|
.default_service(web::to(not_found))
|
|
})
|
|
.bind(("0.0.0.0", 80))?
|
|
.run()
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|