+ Rust docs where needed
There may be more changes that could be added to improve documentation however this is meant to be a good start. !+ There is also a new redirect endpoint for /admin/dashboard This just a convenience thing so that people don't have to remember the '/dashboard' part of the admin route.
This commit is contained in:
parent
6c6d5f8f30
commit
86b9081354
@ -12,12 +12,18 @@ use std::path::{Path, PathBuf};
|
|||||||
use rocket::data::{Data, ToByteUnit};
|
use rocket::data::{Data, ToByteUnit};
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
|
use rocket::response::Redirect;
|
||||||
use response::{bad_request, ok};
|
use response::{bad_request, ok};
|
||||||
|
|
||||||
use apikey::ApiKey;
|
use apikey::ApiKey;
|
||||||
use response::ActionResponse;
|
use response::ActionResponse;
|
||||||
use crate::common::get_clips_dir;
|
use crate::common::get_clips_dir;
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
pub async fn login_dashboard_redirect() -> Redirect {
|
||||||
|
Redirect::to("/admin/dashboard")
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/dashboard")]
|
#[get("/dashboard")]
|
||||||
pub async fn login_dashboard() -> Template {
|
pub async fn login_dashboard() -> Template {
|
||||||
// This page is basically just a login form
|
// This page is basically just a login form
|
||||||
@ -37,9 +43,11 @@ pub async fn dashboard(_key: ApiKey) -> Json<ActionResponse> {
|
|||||||
#[post("/upload-video/<category>/<filename>", data = "<data>")]
|
#[post("/upload-video/<category>/<filename>", data = "<data>")]
|
||||||
pub async fn updload_video(_key: ApiKey, category: PathBuf, filename: PathBuf, data: Data<'_>)
|
pub async fn updload_video(_key: ApiKey, category: PathBuf, filename: PathBuf, data: Data<'_>)
|
||||||
-> Result<Json<ActionResponse>> {
|
-> Result<Json<ActionResponse>> {
|
||||||
// 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 {
|
if util::valid_filename(&filename) == false {
|
||||||
return Ok(bad_request(Some("Invalid filename(s)")));
|
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();
|
let clips = get_clips_dir();
|
||||||
fs::create_dir_all(Path::new(&clips).join(&category))?;
|
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);
|
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())
|
Ok(ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,20 +5,19 @@ use std::io;
|
|||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
use crate::common::{get_clips_dir, thumbs_dir};
|
use crate::common::{get_clips_dir, thumbs_dir};
|
||||||
|
|
||||||
|
/// Describes a category of videos as
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Category {
|
pub struct Category {
|
||||||
name: String,
|
name: String,
|
||||||
// NOTE: this is simply a URI pathname
|
/// NOTE: this is simply a URI pathname
|
||||||
// EXAMPLE: /thumbnail/<category>/.thumbnail.png
|
/// EXAMPLE: /thumbnail/<category>/.thumbnail.png
|
||||||
thumbnail: String
|
thumbnail: String
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
/// Returns a vector of category directories
|
||||||
struct List {
|
|
||||||
categories: Vec<Category>
|
|
||||||
}
|
|
||||||
pub fn get_category_dirs(path: &str) -> std::io::Result<Vec<DirEntry>> {
|
pub fn get_category_dirs(path: &str) -> std::io::Result<Vec<DirEntry>> {
|
||||||
let path = std::path::Path::new(path);
|
let path = std::path::Path::new(path);
|
||||||
|
// Trying to ignore non-directory entries
|
||||||
if !path.is_dir() {
|
if !path.is_dir() {
|
||||||
let e = io::Error::new(io::ErrorKind::NotFound, "Unable to open");
|
let e = io::Error::new(io::ErrorKind::NotFound, "Unable to open");
|
||||||
return Err(e);
|
return Err(e);
|
||||||
@ -33,10 +32,12 @@ pub fn get_category_dirs(path: &str) -> std::io::Result<Vec<DirEntry>> {
|
|||||||
Ok(ret)
|
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<String> {
|
pub fn get_category_thumbnail(category: &str) -> std::io::Result<String> {
|
||||||
let pathname = format!("{}/{}", thumbs_dir(), &category);
|
let pathname = format!("{}/{}", thumbs_dir(), &category);
|
||||||
let path = Path::new(&pathname);
|
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| {
|
let item = path.read_dir()?.find(|file| {
|
||||||
if let Ok(file) = file {
|
if let Ok(file) = file {
|
||||||
let name = file.file_name().into_string().unwrap();
|
let name = file.file_name().into_string().unwrap();
|
||||||
@ -55,10 +56,10 @@ pub fn get_category_thumbnail(category: &str) -> std::io::Result<String> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// WARN: misconfigured servers are just going to get shafted and serve up
|
||||||
|
/// a tonne of 500's
|
||||||
#[get("/categories")]
|
#[get("/categories")]
|
||||||
pub fn list() -> Json<Vec<Category>> {
|
pub fn list() -> Json<Vec<Category>> {
|
||||||
// WARN: misconfigured servers are just going to get shafted and serve up
|
|
||||||
// a tonne of 500's
|
|
||||||
let dir = get_clips_dir();
|
let dir = get_clips_dir();
|
||||||
|
|
||||||
let mut cats: Vec<Category> = Vec::new();
|
let mut cats: Vec<Category> = Vec::new();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
/// Returns the absolute path to the videos directory
|
||||||
pub fn get_clips_dir() -> String {
|
pub fn get_clips_dir() -> String {
|
||||||
match env::var("CLIPS_DIR") {
|
match env::var("CLIPS_DIR") {
|
||||||
Ok(val) => val,
|
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 {
|
pub fn thumbs_dir() -> String {
|
||||||
match env::var("THUMBS_DIR") {
|
match env::var("THUMBS_DIR") {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
|
@ -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_dyn_templates::Template;
|
||||||
use rocket::fs::NamedFile;
|
use rocket::fs::NamedFile;
|
||||||
use std::path::{Path, PathBuf};
|
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> {
|
pub fn default_map() -> HashMap<&'static str, String> {
|
||||||
let mut h: HashMap<&'static str, String> = HashMap::new();
|
let mut h: HashMap<&'static str, String> = HashMap::new();
|
||||||
h.insert("sitetitle", SITENAME.clone());
|
h.insert("sitetitle", SITENAME.clone());
|
||||||
@ -108,8 +113,9 @@ pub fn video(cat: PathBuf, file_base: PathBuf) -> Template {
|
|||||||
Template::render("video", &h)
|
Template::render("video", &h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This route handler returns static files that are comprised
|
||||||
|
/// of JS, CSS, the favicon and other static items
|
||||||
#[get("/<file..>")]
|
#[get("/<file..>")]
|
||||||
pub async fn files(file: PathBuf) -> Option<NamedFile> {
|
pub async fn files(file: PathBuf) -> Option<NamedFile> {
|
||||||
// Used for things like javascript, css, and favicons
|
|
||||||
NamedFile::open(Path::new("static/").join(file)).await.ok()
|
NamedFile::open(Path::new("static/").join(file)).await.ok()
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use rocket::fs::NamedFile;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use crate::common::thumbs_dir;
|
use crate::common::thumbs_dir;
|
||||||
|
|
||||||
|
/// Returns a thumbnail whose formatted name is <video-name>.<ext>.jpg
|
||||||
#[get("/<file..>")]
|
#[get("/<file..>")]
|
||||||
pub async fn get(file: PathBuf) -> Option<NamedFile> {
|
pub async fn get(file: PathBuf) -> Option<NamedFile> {
|
||||||
let clips_dir = thumbs_dir();
|
let clips_dir = thumbs_dir();
|
||||||
|
@ -8,7 +8,9 @@ use crate::common::get_clips_dir;
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct VideoPreview {
|
pub struct VideoPreview {
|
||||||
|
/// Real filename on disk
|
||||||
name: String,
|
name: String,
|
||||||
|
/// URI path to what the browser can reasonably expect
|
||||||
thumbnail: Option<String>
|
thumbnail: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +62,7 @@ pub fn list(cat: PathBuf) -> Option<Json<Vec<VideoPreview>>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Endpoint returns the video file itself that is saved on the server
|
||||||
#[get("/<cat>/<file>")]
|
#[get("/<cat>/<file>")]
|
||||||
pub async fn get_video(cat: PathBuf, file: PathBuf) -> Option<NamedFile> {
|
pub async fn get_video(cat: PathBuf, file: PathBuf) -> Option<NamedFile> {
|
||||||
let clips_dir = get_clips_dir();
|
let clips_dir = get_clips_dir();
|
||||||
|
Loading…
Reference in New Issue
Block a user