diff options
| author | WriterV2 <primary-v2@protonmail.com> | 2026-03-21 11:56:19 +0100 |
|---|---|---|
| committer | WriterV2 <primary-v2@protonmail.com> | 2026-03-21 11:56:19 +0100 |
| commit | f491ed95a3bc82c31c70b0f38ed841408576ec0c (patch) | |
| tree | 1cfc9a957e150ded75c93fad54028a18640ba7c2 /src/handlers/admin.rs | |
| parent | 74db93c431ebc02b1dc43ec12714007d005a9704 (diff) | |
Purge + prepare for local website builder
Diffstat (limited to 'src/handlers/admin.rs')
| -rw-r--r-- | src/handlers/admin.rs | 143 |
1 files changed, 0 insertions, 143 deletions
diff --git a/src/handlers/admin.rs b/src/handlers/admin.rs deleted file mode 100644 index b0863af..0000000 --- a/src/handlers/admin.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::collections::HashMap; -use std::io::{BufWriter, Write}; - -use anyhow::Context; -use axum::body::Bytes; -use axum::extract::{Multipart, Path, Request, State}; -use axum::http::{HeaderMap, StatusCode}; -use axum::middleware::Next; -use axum::response::{IntoResponse, Response}; -use axum::{Extension, Json}; -use rand::Rng; -use subtle::ConstantTimeEq; - -use crate::db::product::get_all_products; -use crate::db::story::{format_filepath, Story}; -use crate::db::ProductDatabaseHandler; -use crate::error::AppError; - -use super::{ApiContext, AppState}; - -pub fn generate_token() -> String { - const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\ - abcdefghijklmnopqrstuvwxyz\ - 0123456789)(*&^%$#@!~"; - let mut rng = rand::thread_rng(); - let token: String = (0..32) - .map(|_| { - let idx = rng.gen_range(0..CHARSET.len()); - CHARSET[idx] as char - }) - .collect(); - println!("New Token generated: {}", token); - token -} - -pub async fn admin_middleware( - State(state): State<AppState>, - headers: HeaderMap, - request: Request, - next: Next, -) -> Result<Response, StatusCode> { - let mut expected_token = state.admin_token.lock().await; - - let token = headers - .get("X-Admin-Token") - .and_then(|header| header.to_str().ok()) - .ok_or(StatusCode::UNAUTHORIZED)?; - - if expected_token - .as_bytes() - .ct_ne(token.as_bytes()) - .unwrap_u8() - == 1 - { - eprintln!("Warning: Unauthorized access attempt with invalid token"); - *expected_token = generate_token(); - return Err(StatusCode::UNAUTHORIZED); - } - *expected_token = generate_token(); - - Ok(next.run(request).await) -} - -pub async fn admin_healthcheck() -> impl IntoResponse { - StatusCode::OK -} - -pub async fn upload_story( - ctx: Extension<ApiContext>, - mut multipart: Multipart, -) -> Result<impl IntoResponse, AppError> { - let mut form: HashMap<String, Bytes> = HashMap::new(); - while let Some(field) = multipart.next_field().await? { - if let Some(label) = field.name() { - form.insert(label.to_string(), field.bytes().await?); - } - } - - let name = if let Some(name_value) = form.get("name") { - std::str::from_utf8(name_value).with_context(|| "Failed to parse name")? - } else { - return Ok(StatusCode::BAD_REQUEST.into_response()); - }; - - let description = if let Some(description_value) = form.get("description") { - std::str::from_utf8(description_value).with_context(|| "Failed to parse description")? - } else { - return Ok(StatusCode::BAD_REQUEST.into_response()); - }; - - let language = if let Some(language_value) = form.get("language") { - String::from_utf8(language_value.to_vec()).with_context(|| "Failed to parse language")? - } else { - return Ok(StatusCode::BAD_REQUEST.into_response()); - }; - - let pdf = if let Some(pdf_value) = form.get("pdf") { - let filename = format_filepath(name, "pdf"); - let file = std::fs::File::create_new(filename)?; - BufWriter::new(file).write_all(pdf_value)?; - pdf_value.to_vec() - } else { - return Ok(StatusCode::BAD_REQUEST.into_response()); - }; - - let mut tags: Vec<&str> = Vec::new(); - if let Some(tags_value) = form.get("tag") { - let tagstring = std::str::from_utf8(tags_value)?; - for tag in tagstring.split(",") { - tags.push(tag.trim()); - } - } - - let story_template = Story { - id: 0, - pid: 0, - language, - pdf, - }; - - let story = story_template - .post(&ctx.pool, name, description, tags) - .await?; - Ok((StatusCode::CREATED, Json(story)).into_response()) -} - -pub async fn delete_story( - ctx: Extension<ApiContext>, - Path(story_id): Path<i64>, -) -> Result<impl IntoResponse, AppError> { - Story::delete(&ctx.pool, story_id).await?; - Ok((StatusCode::NO_CONTENT).into_response()) -} - -pub async fn get_stories(ctx: Extension<ApiContext>) -> Result<impl IntoResponse, AppError> { - let stories = Story::get_all(&ctx.pool).await?; - Ok((StatusCode::OK, Json(stories)).into_response()) -} - -pub async fn get_products(ctx: Extension<ApiContext>) -> Result<impl IntoResponse, AppError> { - let products = get_all_products(&ctx.pool).await?; - Ok((StatusCode::OK, Json(products)).into_response()) -} |
