+ /admin/remove-video...

+ /admin/upload-video
Code still requires some tests to ensure correctness
This commit is contained in:
shockrah 2022-03-22 22:09:04 -07:00
parent 88a938d0c2
commit 367c798320
4 changed files with 46 additions and 15 deletions

1
.gitignore vendored
View File

@ -28,3 +28,4 @@ aws/playbooks/hosts
ts/dist/ ts/dist/
ts/node_modules/ ts/node_modules/
.vscode/settings.json .vscode/settings.json
api/.vscode/settings.json

View File

@ -5,7 +5,12 @@ use rocket::http::Status;
use crate::db::{self, DB_PATH}; use crate::db::{self, DB_PATH};
pub struct ApiKey { pub struct ApiKey {
// These are used by rocket's driver code/decl macros however cargo
// is not able to check those as the code is generated at compile time.
// The dead code thing is just to stifle pointless warnings
#[allow(dead_code)]
uid: String, uid: String,
#[allow(dead_code)]
key: String key: String
} }

View File

@ -2,15 +2,21 @@
mod apikey; mod apikey;
mod response; mod response;
mod util;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Result;
use std::fs;
use std::path::{Path, PathBuf};
use rocket::data::{Data, ToByteUnit};
use rocket::serde::json::Json;
use rocket_dyn_templates::Template;
use response::{bad_request, ok};
use apikey::ApiKey; use apikey::ApiKey;
use response::ActionResponse; use response::ActionResponse;
use rocket::serde::json::Json; use crate::common::get_clips_dir;
use rocket_dyn_templates::Template;
#[get("/dashboard")] #[get("/dashboard")]
pub async fn login_dashboard() -> Template { pub async fn login_dashboard() -> Template {
@ -22,18 +28,35 @@ pub async fn login_dashboard() -> Template {
#[post("/dashboard")] #[post("/dashboard")]
pub async fn dashboard(_key: ApiKey) -> Json<ActionResponse> { pub async fn dashboard(_key: ApiKey) -> Json<ActionResponse> {
// API Key auth'd for us so we don't need to bother checking, // Assuming the api key check doesn't fail we can reply with Ok
// this just serves to confirm the credentials are correct // at the application level
Json(ActionResponse("ok")) ok()
} }
#[post("/upload-video?<category>&<filename>")] #[post("/upload-video/<category>/<filename>", data = "<data>")]
async fn updload_video(_key: ApiKey, category: String, filename: String) -> &'static str { pub async fn updload_video(_key: ApiKey, category: PathBuf, filename: PathBuf, data: Data<'_>)
todo!() -> Result<Json<ActionResponse>> {
// filenames must have a basename .len of at least 1 + '.' + extension
// Valid file extensions are mkv|mp4|webm
if util::valid_filename(&filename) == false {
return Ok(bad_request(Some("Invalid filename(s)")));
}
let clips = get_clips_dir();
fs::create_dir_all(Path::new(&clips).join(&category))?;
let filepath = Path::new(&clips).join(category).join(filename);
data.open(200.megabytes()).into_file(filepath).await?;
Ok(ok())
} }
#[delete("/remove-video?<category>&<filename>")] #[delete("/remove-video/<category>/<filename>")]
async fn remove_video(_key: ApiKey, category: String, filename: String) -> &'static str { pub async fn remove_video(_key: ApiKey, category: PathBuf, filename: PathBuf)
todo!() -> Result<Json<ActionResponse>> {
let clips = get_clips_dir();
let path = Path::new(&clips).join(&category).join(&filename);
fs::remove_file(path)?;
Ok(ok())
} }

View File

@ -35,7 +35,9 @@ async fn main() {
.mount("/video", routes![video::get_video]) // videos .mount("/video", routes![video::get_video]) // videos
.mount("/admin", routes![ .mount("/admin", routes![
admin::login_dashboard, admin::login_dashboard,
admin::dashboard admin::dashboard,
admin::updload_video,
admin::remove_video
]) ])
.attach(Template::fairing()) .attach(Template::fairing())
.launch().await; .launch().await;