show image preview + single file downloads

This commit is contained in:
2025-08-10 23:16:18 +02:00
parent bfe73eefb9
commit c8b52a5b3b
13 changed files with 174 additions and 26 deletions

12
backend/Cargo.lock generated
View File

@@ -144,6 +144,7 @@ dependencies = [
"axum",
"axum-core",
"bytes",
"cookie",
"fastrand",
"futures-util",
"http",
@@ -292,6 +293,17 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cookie"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
dependencies = [
"percent-encoding",
"time",
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.4"

View File

@@ -15,7 +15,7 @@ path = "src/bin/backend/main.rs"
anyhow = "1.0.98"
argon2 = "0.5.3"
axum = { version = "0.8.4", features = ["multipart", "query"] }
axum-extra = { version = "0.10.1", features = ["multipart"] }
axum-extra = { version = "0.10.1", features = ["cookie", "multipart"] }
base64 = "0.22.1"
bytes = "1.10.1"
chrono = "0.4.41"

View File

@@ -2,6 +2,7 @@ use axum::{
extract::FromRequestParts,
http::{header::AUTHORIZATION, request::Parts},
};
use axum_extra::extract::CookieJar;
use crate::{
domain::warren::models::auth_session::AuthSessionIdWithType, inbound::http::responses::ApiError,
@@ -15,21 +16,38 @@ where
{
type Rejection = ApiError;
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
let Some(header) = parts.headers.get(AUTHORIZATION) else {
return Err(ApiError::Unauthorized(
"Missing authorization header".to_string(),
));
};
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
// Release build
if !cfg!(debug_assertions) {
let jar = CookieJar::from_request_parts(parts, state).await.unwrap();
let header_str = header.to_str().map_err(|_| {
ApiError::InternalServerError(
"Failed to get authorization header as string".to_string(),
)
})?;
let Some(cookie) = jar.get(AUTHORIZATION.as_str()) else {
return Err(ApiError::Unauthorized(
"Missing authorization cookie".to_string(),
));
};
AuthSessionIdWithType::from_str(header_str)
.map(|session_id| SessionIdHeader(session_id))
.map_err(|_| ApiError::BadRequest("Invalid session id".to_string()))
AuthSessionIdWithType::from_str(cookie.value())
.map(|session_id| SessionIdHeader(session_id))
.map_err(|_| ApiError::BadRequest("Invalid session id".to_string()))
}
// Debug build
else {
let Some(header) = parts.headers.get(AUTHORIZATION) else {
return Err(ApiError::Unauthorized(
"Missing authorization header".to_string(),
));
};
let header_str = header.to_str().map_err(|_| {
ApiError::InternalServerError(
"Failed to get authorization header as string".to_string(),
)
})?;
AuthSessionIdWithType::from_str(header_str)
.map(|session_id| SessionIdHeader(session_id))
.map_err(|_| ApiError::BadRequest("Invalid session id".to_string()))
}
}
}