This commit is contained in:
EvilMuffinHa 2022-03-02 02:08:29 -05:00
parent ad9cf01d90
commit 294348a72e
2 changed files with 105 additions and 14 deletions

View File

@ -11,11 +11,19 @@ use std::fs;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::collections::HashMap; use std::collections::HashMap;
use rocket::response::{NamedFile, Redirect}; use rocket::response::{NamedFile, Redirect};
use rocket::http::ContentType; use rocket::http::{Cookie, Cookies, ContentType, Status};
use rocket::request::{self, Request, Form, FromRequest};
use rocket_contrib::templates::Template; use rocket_contrib::templates::Template;
use rocket_upload::MultipartDatas; use rocket_upload::MultipartDatas;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
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: String = env::var("FASTCLOUD_ADMIN_KEY").unwrap_or_else(|_| String::from(""));
static ref USER_KEY: String = env::var("FASTCLOUD_USER_KEY").unwrap_or_else(|_| String::from(""));
static ref PUBLIC_READ: bool = env::var("FASTCLOUD_PUBLIC").unwrap_or_else(|_| String::from("")) != *"";
}
#[derive(Serialize)] #[derive(Serialize)]
struct DirPath { struct DirPath {
is_file: bool, is_file: bool,
@ -23,41 +31,91 @@ struct DirPath {
name: String, name: String,
} }
#[derive(FromForm, Deserialize)] #[derive(Debug, FromForm, Deserialize)]
struct LoginInfo { struct GenericUser {
key: String, key: String,
} }
struct AdminUser;
impl<'a, 'r> FromRequest<'a, 'r> for GenericUser {
type Error = ();
lazy_static! { fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
static ref DIR: PathBuf = Path::new(env::var("FASTCLOUD_DIR").unwrap_or_else(|_| String::from("")).as_str()).to_path_buf(); match request.cookies().get("key") {
static ref ADMIN_KEY: PathBuf = Path::new(env::var("FASTCLOUD_ADMIN_KEY").unwrap_or_else(|_| String::from("")).as_str()).to_path_buf(); Some(key) => {
static ref USER_KEY: PathBuf = Path::new(env::var("FASTCLOUD_USER_KEY").unwrap_or_else(|_| String::from("")).as_str()).to_path_buf(); if key.value() == ADMIN_KEY.as_str() || key.value() == USER_KEY.as_str() {
request::Outcome::Success(GenericUser { key: String::from(key.value()) })
} else {
request::Outcome::Failure((Status::BadRequest, ()))
}
},
None => {
if *PUBLIC_READ {
request::Outcome::Success(GenericUser { key: String::from("") })
} else {
request::Outcome::Failure((Status::BadRequest, ()))
}
}
}
}
} }
impl<'a, 'r> FromRequest<'a, 'r> for AdminUser {
type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
match request.cookies().get("key") {
Some(key) => {
if key.value() == ADMIN_KEY.as_str() {
request::Outcome::Success(AdminUser)
} else {
request::Outcome::Failure((Status::BadRequest, ()))
}
},
None => request::Outcome::Failure((Status::BadRequest, ()))
}
}
}
#[get("/")]
fn root() -> Template {
let map: HashMap<String, String> = HashMap::new();
Template::render("home", map)
}
#[post("/login", data = "<form>")]
fn login(form: Form<GenericUser>, mut cookies: Cookies) -> Redirect {
println!("{:?}", form);
let key = form.into_inner().key;
let mut cook = Cookie::new("key", key);
cook.set_http_only(true);
cook.set_secure(true);
cookies.add(cook);
Redirect::to("/serve")
}
#[get("/serve")] #[get("/serve")]
fn get_root() -> Template { fn get_root(_guard: GenericUser) -> Template {
let path = DIR.as_path().to_str().unwrap_or(""); let path = DIR.as_path().to_str().unwrap_or("");
Template::render("dir", directory_structure(path.to_string())) Template::render("dir", directory_structure(path.to_string()))
} }
#[get("/serve/<path..>")] #[get("/serve/<path..>")]
fn get_dir_entry(path: PathBuf) -> Template { fn get_dir_entry(path: PathBuf, _guard: GenericUser) -> Template {
let dir = DIR.as_path().join(path); let dir = DIR.as_path().join(path);
let path = dir.to_str().unwrap_or(""); let path = dir.to_str().unwrap_or("");
Template::render("dir", directory_structure(path.to_string())) Template::render("dir", directory_structure(path.to_string()))
} }
#[post("/dir/<path..>")] #[post("/dir/<path..>")]
fn create_dir(path: PathBuf) { fn create_dir(path: PathBuf, _guard: AdminUser) {
let dir = DIR.as_path().join(path); let dir = DIR.as_path().join(path);
fs::create_dir_all(dir).unwrap(); fs::create_dir_all(dir).unwrap();
} }
#[post("/del/<path..>")] #[post("/del/<path..>")]
fn delete(path: PathBuf) -> Redirect { fn delete(path: PathBuf, _guard: AdminUser) -> Redirect {
let dir = DIR.as_path().join(path.clone()); let dir = DIR.as_path().join(path.clone());
if dir.is_file() { if dir.is_file() {
fs::remove_file(dir).unwrap(); fs::remove_file(dir).unwrap();
@ -103,13 +161,13 @@ fn directory_structure(path: String) -> HashMap<&'static str, HashMap<i32, DirPa
#[get("/file/<path..>")] #[get("/file/<path..>")]
fn file_get(path: PathBuf) -> Option<NamedFile> { fn file_get(path: PathBuf, _guard: GenericUser) -> Option<NamedFile> {
let dir = DIR.as_path().join(path); let dir = DIR.as_path().join(path);
rocket::response::NamedFile::open(dir.as_path()).ok() rocket::response::NamedFile::open(dir.as_path()).ok()
} }
#[post("/upload/<path..>", data = "<data>")] #[post("/upload/<path..>", data = "<data>")]
fn upload_file(path: PathBuf, _content_type: &ContentType, data:MultipartDatas) -> Redirect { fn upload_file(path: PathBuf, _content_type: &ContentType, data:MultipartDatas, _guard: AdminUser) -> Redirect {
let dir = DIR.as_path().join(path.clone()); let dir = DIR.as_path().join(path.clone());
for f in data.files { for f in data.files {
if !Path::new(&format!("{}/{}", dir.to_str().unwrap(), f.filename)).exists() { if !Path::new(&format!("{}/{}", dir.to_str().unwrap(), f.filename)).exists() {
@ -125,6 +183,22 @@ fn upload_file(path: PathBuf, _content_type: &ContentType, data:MultipartDatas)
Redirect::to(uri!(get_dir_entry: path)) Redirect::to(uri!(get_dir_entry: path))
} }
#[post("/upload", data = "<data>")]
fn upload_root(_content_type: &ContentType, data:MultipartDatas, _guard: AdminUser) -> Redirect {
let dir = DIR.as_path();
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_root))
}
@ -135,5 +209,5 @@ fn upload_file(path: PathBuf, _content_type: &ContentType, data:MultipartDatas)
fn main() { fn main() {
rocket::ignite() rocket::ignite()
.attach(Template::fairing()) .attach(Template::fairing())
.mount("/", routes![get_root, get_dir_entry, create_dir, file_get, upload_file, delete]).launch(); .mount("/", routes![root, login, get_root, get_dir_entry, create_dir, file_get, upload_root, upload_file, delete]).launch();
} }

17
templates/home.html.hbs Normal file
View File

@ -0,0 +1,17 @@
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css">
</head>
<body>
<form action="/login" method="post">
<div class="form-outline mb-4">
<input type="text", id="key", name="key" class="form-control form-control-lg" placeholder="Enter Key"/>
<input type="submit" value="Login"/>
</div>
</form>
</body>
</html>