diff --git a/api/src/admin/mod.rs b/api/src/admin/mod.rs index 29d2863..1d82851 100644 --- a/api/src/admin/mod.rs +++ b/api/src/admin/mod.rs @@ -12,12 +12,18 @@ use std::path::{Path, PathBuf}; use rocket::data::{Data, ToByteUnit}; use rocket::serde::json::Json; use rocket_dyn_templates::Template; +use rocket::response::Redirect; use response::{bad_request, ok}; use apikey::ApiKey; use response::ActionResponse; use crate::common::get_clips_dir; +#[get("/")] +pub async fn login_dashboard_redirect() -> Redirect { + Redirect::to("/admin/dashboard") +} + #[get("/dashboard")] pub async fn login_dashboard() -> Template { // This page is basically just a login form @@ -37,9 +43,11 @@ pub async fn dashboard(_key: ApiKey) -> Json { #[post("/upload-video//", data = "")] pub async fn updload_video(_key: ApiKey, category: PathBuf, filename: PathBuf, data: Data<'_>) -> Result> { - // filenames must have a basename .len of at least 1 + '.' + extension - // Valid file extensions are mkv|mp4|webm - + /* + * Uploads must have BOTH a valid filename and a category + * Without the category the server will simply not find + * the correct endpoint to reach and thus will 404 + */ if util::valid_filename(&filename) == false { return Ok(bad_request(Some("Invalid filename(s)"))); } @@ -47,8 +55,14 @@ pub async fn updload_video(_key: ApiKey, category: PathBuf, filename: PathBuf, d let clips = get_clips_dir(); fs::create_dir_all(Path::new(&clips).join(&category))?; + /* + * We allow up to 200 Megaytes per upload as most short + * clips are not going to be very large anyway and this + * should be a reasonably high limit for those that want + * to upload "large" clips + * */ let filepath = Path::new(&clips).join(category).join(filename); - data.open(200.megabytes()).into_file(filepath).await?; + data.open(250.megabytes()).into_file(filepath).await?; Ok(ok()) } diff --git a/api/src/category.rs b/api/src/category.rs index 5bcf46d..fa9b170 100644 --- a/api/src/category.rs +++ b/api/src/category.rs @@ -5,20 +5,19 @@ use std::io; use rocket::serde::json::Json; use crate::common::{get_clips_dir, thumbs_dir}; +/// Describes a category of videos as #[derive(Serialize)] pub struct Category { name: String, - // NOTE: this is simply a URI pathname - // EXAMPLE: /thumbnail//.thumbnail.png + /// NOTE: this is simply a URI pathname + /// EXAMPLE: /thumbnail//.thumbnail.png thumbnail: String } -#[derive(Serialize)] -struct List { - categories: Vec -} +/// Returns a vector of category directories pub fn get_category_dirs(path: &str) -> std::io::Result> { let path = std::path::Path::new(path); + // Trying to ignore non-directory entries if !path.is_dir() { let e = io::Error::new(io::ErrorKind::NotFound, "Unable to open"); return Err(e); @@ -33,10 +32,12 @@ pub fn get_category_dirs(path: &str) -> std::io::Result> { Ok(ret) } +/// Will return the path to a category's thumb nail assuming it exists. +/// If nothing is found then it gives back the URI path to a not-found image pub fn get_category_thumbnail(category: &str) -> std::io::Result { let pathname = format!("{}/{}", thumbs_dir(), &category); let path = Path::new(&pathname); - // Assume its a directory + // Assume directory as we're only called from "safe" places let item = path.read_dir()?.find(|file| { if let Ok(file) = file { let name = file.file_name().into_string().unwrap(); @@ -55,10 +56,10 @@ pub fn get_category_thumbnail(category: &str) -> std::io::Result { }) } +/// WARN: misconfigured servers are just going to get shafted and serve up +/// a tonne of 500's #[get("/categories")] pub fn list() -> Json> { - // WARN: misconfigured servers are just going to get shafted and serve up - // a tonne of 500's let dir = get_clips_dir(); let mut cats: Vec = Vec::new(); diff --git a/api/src/common.rs b/api/src/common.rs index 56a8173..880323f 100644 --- a/api/src/common.rs +++ b/api/src/common.rs @@ -1,5 +1,6 @@ use std::env; +/// Returns the absolute path to the videos directory pub fn get_clips_dir() -> String { match env::var("CLIPS_DIR") { Ok(val) => val, @@ -7,6 +8,7 @@ pub fn get_clips_dir() -> String { } } +/// Returns the absolute path to the thumbnails directory pub fn thumbs_dir() -> String { match env::var("THUMBS_DIR") { Ok(val) => val, diff --git a/api/src/page.rs b/api/src/page.rs index f92450d..1550a7f 100644 --- a/api/src/page.rs +++ b/api/src/page.rs @@ -1,3 +1,7 @@ +/// This module takes care of returning bare webpage templates +/// Most of the work done here is simply to fill the templates +/// with the appropriate meta data that is required + use rocket_dyn_templates::Template; use rocket::fs::NamedFile; use std::path::{Path, PathBuf}; @@ -19,6 +23,7 @@ lazy_static! { }; } +/// Default metadata that all web pages must be filled with pub fn default_map() -> HashMap<&'static str, String> { let mut h: HashMap<&'static str, String> = HashMap::new(); h.insert("sitetitle", SITENAME.clone()); @@ -108,8 +113,9 @@ pub fn video(cat: PathBuf, file_base: PathBuf) -> Template { Template::render("video", &h) } +/// This route handler returns static files that are comprised +/// of JS, CSS, the favicon and other static items #[get("/")] pub async fn files(file: PathBuf) -> Option { - // Used for things like javascript, css, and favicons NamedFile::open(Path::new("static/").join(file)).await.ok() } diff --git a/api/src/thumbnail.rs b/api/src/thumbnail.rs index 7176fe9..286623c 100644 --- a/api/src/thumbnail.rs +++ b/api/src/thumbnail.rs @@ -2,6 +2,7 @@ use rocket::fs::NamedFile; use std::path::{Path, PathBuf}; use crate::common::thumbs_dir; +/// Returns a thumbnail whose formatted name is ..jpg #[get("/")] pub async fn get(file: PathBuf) -> Option { let clips_dir = thumbs_dir(); diff --git a/api/src/video.rs b/api/src/video.rs index f9088f0..66feb6a 100644 --- a/api/src/video.rs +++ b/api/src/video.rs @@ -8,7 +8,9 @@ use crate::common::get_clips_dir; #[derive(Serialize)] pub struct VideoPreview { + /// Real filename on disk name: String, + /// URI path to what the browser can reasonably expect thumbnail: Option } @@ -60,6 +62,7 @@ pub fn list(cat: PathBuf) -> Option>> { } +/// Endpoint returns the video file itself that is saved on the server #[get("//")] pub async fn get_video(cat: PathBuf, file: PathBuf) -> Option { let clips_dir = get_clips_dir();