From 2780044ef850b0151bb0352ab8bab96a537bcd69 Mon Sep 17 00:00:00 2001 From: n4mlz Date: Tue, 29 Sep 2026 17:14:41 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=94=A7=20=E3=82=B8=E3=83=A3=E3=82=B1?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=81=AE=E3=82=B5=E3=82=A4=E3=82=BA=E4=B8=8A?= =?UTF-8?q?=E9=99=90=E3=82=92=E6=9B=B4=E6=96=B0=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/presentation/src/route/admin/asset.rs | 2 +- crates/usecase/src/asset.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/presentation/src/route/admin/asset.rs b/crates/presentation/src/route/admin/asset.rs index 60af07c..cf15267 100644 --- a/crates/presentation/src/route/admin/asset.rs +++ b/crates/presentation/src/route/admin/asset.rs @@ -183,7 +183,7 @@ fn map_jacket_error(error: AssetUploadError) -> AppError { AssetUploadError::UnsupportedContentType => { AppError::bad_request("jacket must be JPEG, PNG, or WebP") } - AssetUploadError::TooLarge => AppError::bad_request("jacket exceeds 5 MiB"), + AssetUploadError::TooLarge => AppError::bad_request("jacket exceeds 20 MiB"), AssetUploadError::InvalidData => AppError::bad_request("jacket image is invalid"), AssetUploadError::InvalidFileName => AppError::bad_request("jacket file name is invalid"), } diff --git a/crates/usecase/src/asset.rs b/crates/usecase/src/asset.rs index 484a3c0..c33eebe 100644 --- a/crates/usecase/src/asset.rs +++ b/crates/usecase/src/asset.rs @@ -4,7 +4,7 @@ use image::{ImageFormat, ImageReader, Limits}; use thiserror::Error; use tokio::io::AsyncRead; -pub const MAX_JACKET_SIZE: usize = 5 * 1024 * 1024; +pub const MAX_JACKET_SIZE: usize = 20 * 1024 * 1024; pub const MAX_AUDIO_SIZE: usize = 30 * 1024 * 1024; pub const MAX_CHART_SIZE: usize = 5 * 1024 * 1024; @@ -276,6 +276,16 @@ mod tests { assert_eq!(&upload.bytes[..8], b"\x89PNG\r\n\x1a\n"); } + #[test] + fn rejects_jacket_over_size_limit() { + let bytes = vec![0; MAX_JACKET_SIZE + 1]; + + assert!(matches!( + AssetUpload::jacket("image/png", bytes), + Err(AssetUploadError::TooLarge) + )); + } + #[test] fn accepts_wav_header() { let mut bytes = b"RIFF".to_vec(); From 705eb440e0155eab2475947c89af65f05772dad4 Mon Sep 17 00:00:00 2001 From: n4mlz Date: Tue, 29 Sep 2026 17:18:01 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=94=A7=20=E9=9F=B3=E6=BA=90=E3=81=AE?= =?UTF-8?q?=E3=82=B5=E3=82=A4=E3=82=BA=E4=B8=8A=E9=99=90=E3=82=92=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/presentation/src/route/admin/asset.rs | 2 +- crates/presentation/src/route/mod.rs | 3 ++- crates/usecase/src/asset.rs | 14 +++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/presentation/src/route/admin/asset.rs b/crates/presentation/src/route/admin/asset.rs index cf15267..884b931 100644 --- a/crates/presentation/src/route/admin/asset.rs +++ b/crates/presentation/src/route/admin/asset.rs @@ -192,7 +192,7 @@ fn map_jacket_error(error: AssetUploadError) -> AppError { fn map_audio_error(error: AssetUploadError) -> AppError { match error { AssetUploadError::UnsupportedContentType => AppError::bad_request("audio must be WAV"), - AssetUploadError::TooLarge => AppError::bad_request("audio exceeds 30 MiB"), + AssetUploadError::TooLarge => AppError::bad_request("audio exceeds 60 MiB"), AssetUploadError::InvalidData => AppError::bad_request("audio is invalid"), AssetUploadError::InvalidFileName => AppError::bad_request("audio file name is invalid"), } diff --git a/crates/presentation/src/route/mod.rs b/crates/presentation/src/route/mod.rs index 6aa9d28..fe76b36 100644 --- a/crates/presentation/src/route/mod.rs +++ b/crates/presentation/src/route/mod.rs @@ -6,6 +6,7 @@ use axum::{ routing::{get, patch, post}, }; use tower_http::{cors::CorsLayer, trace::TraceLayer}; +use usecase::asset::MAX_AUDIO_SIZE; use crate::{ auth::{Authenticator, AuthorizationPolicy, PrincipalKind}, @@ -77,7 +78,7 @@ pub fn create_app(state: State, authenticator: Option) -> Router get(admin::asset::get_chart), ) .route("/db/synchronize", post(admin::handle_db_synchronization)); - let admin_routes = admin_routes.layer(DefaultBodyLimit::max(31 * 1024 * 1024)); + let admin_routes = admin_routes.layer(DefaultBodyLimit::max(MAX_AUDIO_SIZE)); let private_routes = Router::new() .nest("/users", users) diff --git a/crates/usecase/src/asset.rs b/crates/usecase/src/asset.rs index c33eebe..3ed3890 100644 --- a/crates/usecase/src/asset.rs +++ b/crates/usecase/src/asset.rs @@ -5,7 +5,7 @@ use thiserror::Error; use tokio::io::AsyncRead; pub const MAX_JACKET_SIZE: usize = 20 * 1024 * 1024; -pub const MAX_AUDIO_SIZE: usize = 30 * 1024 * 1024; +pub const MAX_AUDIO_SIZE: usize = 60 * 1024 * 1024; pub const MAX_CHART_SIZE: usize = 5 * 1024 * 1024; #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -298,6 +298,18 @@ mod tests { ); } + #[test] + fn rejects_audio_over_size_limit() { + let mut bytes = vec![0; MAX_AUDIO_SIZE + 1]; + bytes[..4].copy_from_slice(b"RIFF"); + bytes[8..12].copy_from_slice(b"WAVE"); + + assert!(matches!( + AssetUpload::audio("audio/wav", bytes), + Err(AssetUploadError::TooLarge) + )); + } + #[test] fn rejects_invalid_wav_header() { assert!(matches!(