fastcloud/src/main.rs
2022-03-02 00:17:19 -05:00

140 lines
4.4 KiB
Rust

#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
#[macro_use]
extern crate lazy_static;
use std::path::{PathBuf, Path};
use std::env;
use std::fs;
use std::ffi::OsStr;
use std::collections::HashMap;
use rocket::response::{NamedFile, Redirect};
use rocket::http::ContentType;
use rocket_contrib::templates::Template;
use rocket_upload::MultipartDatas;
use serde::{Serialize, Deserialize};
#[derive(Serialize)]
struct DirPath {
is_file: bool,
path: String,
name: String,
}
#[derive(FromForm, Deserialize)]
struct LoginInfo {
key: String,
}
lazy_static! {
static ref DIR: PathBuf = Path::new(env::var("FASTCLOUD_DIR").unwrap_or_else(|_| String::from("")).as_str()).to_path_buf();
static ref ADMIN_KEY: PathBuf = Path::new(env::var("FASTCLOUD_ADMIN_KEY").unwrap_or_else(|_| String::from("")).as_str()).to_path_buf();
static ref USER_KEY: PathBuf = Path::new(env::var("FASTCLOUD_USER_KEY").unwrap_or_else(|_| String::from("")).as_str()).to_path_buf();
}
#[get("/serve")]
fn get_root() -> Template {
let path = DIR.as_path().to_str().unwrap_or("");
Template::render("dir", directory_structure(path.to_string()))
}
#[get("/serve/<path..>")]
fn get_dir_entry(path: PathBuf) -> Template {
let dir = DIR.as_path().join(path);
let path = dir.to_str().unwrap_or("");
Template::render("dir", directory_structure(path.to_string()))
}
#[post("/dir/<path..>")]
fn create_dir(path: PathBuf) {
let dir = DIR.as_path().join(path);
fs::create_dir_all(dir).unwrap();
}
#[post("/del/<path..>")]
fn delete(path: PathBuf) -> Redirect {
let dir = DIR.as_path().join(path.clone());
if dir.is_file() {
fs::remove_file(dir).unwrap();
} else {
fs::remove_dir_all(dir).unwrap();
}
let npath = path.parent().unwrap().to_path_buf();
Redirect::to(uri!(get_dir_entry: npath))
}
fn directory_structure(path: String) -> HashMap<&'static str, HashMap<i32, DirPath>> {
let dir = Path::new(path.as_str());
let paths = fs::read_dir(dir).unwrap()
.map(|x| x.unwrap().path().into_os_string().into_string().unwrap())
.enumerate()
.map(|x| (x.0 as i32, DirPath {
is_file: Path::new(&x.1).is_file(),
path: Path::new(&x.1).strip_prefix(DIR.clone().into_os_string().into_string().unwrap()).unwrap().to_str().unwrap().to_string(),
name: Path::new(&x.1).file_name().unwrap().to_str().unwrap().to_string(),
}))
.collect::<HashMap<i32, DirPath>>();
let mut context: HashMap<&str, HashMap<i32, DirPath>> = HashMap::new();
let parent = DirPath {
is_file: false,
path: dir.strip_prefix(DIR.clone().into_os_string().into_string().unwrap()).unwrap().parent().unwrap_or_else(|| Path::new("")).to_str().unwrap().to_string(),
name: dir.parent().unwrap().file_name().unwrap_or_else(|| OsStr::new("")).to_str().unwrap().to_string(),
};
let current = DirPath {
is_file: false,
path: dir.strip_prefix(DIR.clone().into_os_string().into_string().unwrap()).unwrap_or_else(|_| Path::new("")).to_str().unwrap().to_string(),
name: dir.file_name().unwrap_or_else(|| OsStr::new("")).to_str().unwrap().to_string(),
};
let mut pt = HashMap::new();
pt.insert(0, parent);
context.insert("parent", pt);
let mut pt = HashMap::new();
pt.insert(0, current);
context.insert("current", pt);
context.insert("ctx", paths);
context
}
#[get("/file/<path..>")]
fn file_get(path: PathBuf) -> Option<NamedFile> {
let dir = DIR.as_path().join(path);
rocket::response::NamedFile::open(dir.as_path()).ok()
}
#[post("/upload/<path..>", data = "<data>")]
fn upload_file(path: PathBuf, _content_type: &ContentType, data:MultipartDatas) -> Redirect {
let dir = DIR.as_path().join(path.clone());
for f in data.files {
if !Path::new(&format!("{}/{}", dir.to_str().unwrap(), f.filename)).exists() {
f.persist(&dir);
}
for i in 0.. {
if !Path::new(&format!("{}/{}.{}", dir.to_str().unwrap(), f.filename, i)).exists() {
f.persist(&dir);
break
}
}
}
Redirect::to(uri!(get_dir_entry: path))
}
// TODO: move files
// TODO: rename files
// TODO: rewrite frontend
fn main() {
rocket::ignite()
.attach(Template::fairing())
.mount("/", routes![get_root, get_dir_entry, create_dir, file_get, upload_file, delete]).launch();
}