Return validation error if upload size exceeds limit

This commit is contained in:
silverpill 2022-08-18 20:15:40 +00:00
parent 3b56b29785
commit 4dc94ed39b
5 changed files with 30 additions and 24 deletions

View file

@ -25,12 +25,11 @@ use mitra::mastodon_api::oauth::views::oauth_api_scope;
use mitra::mastodon_api::search::views::search_api_scope;
use mitra::mastodon_api::statuses::views::status_api_scope;
use mitra::mastodon_api::timelines::views::timeline_api_scope;
use mitra::mastodon_api::UPLOAD_MAX_SIZE;
use mitra::nodeinfo::views as nodeinfo;
use mitra::scheduler;
use mitra::webfinger::views as webfinger;
const MAX_UPLOAD_SIZE: usize = 1024 * 1024 * 10;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let config = parse_config();
@ -119,8 +118,8 @@ async fn main() -> std::io::Result<()> {
}
})
.wrap(create_auth_error_handler())
.app_data(web::PayloadConfig::default().limit(MAX_UPLOAD_SIZE))
.app_data(web::JsonConfig::default().limit(MAX_UPLOAD_SIZE))
.app_data(web::PayloadConfig::default().limit(UPLOAD_MAX_SIZE * 2))
.app_data(web::JsonConfig::default().limit(UPLOAD_MAX_SIZE * 2))
.app_data(web::Data::new(config.clone()))
.app_data(web::Data::new(db_pool.clone()))
.app_data(web::Data::new(maybe_contract_set.clone()))

View file

@ -30,7 +30,6 @@ use crate::mastodon_api::oauth::auth::get_current_user;
use crate::mastodon_api::pagination::get_paginated_response;
use crate::mastodon_api::statuses::helpers::build_status_list;
use crate::mastodon_api::statuses::types::Status;
use crate::mastodon_api::uploads::UploadError;
use crate::models::posts::queries::get_posts_by_author;
use crate::models::profiles::queries::{
get_profile_by_id,
@ -194,18 +193,7 @@ async fn update_credentials(
&current_user.profile.identity_proofs.into_inner(),
&current_user.profile.payment_options.into_inner(),
&config.media_dir(),
)
.map_err(|err| {
match err {
UploadError::Base64DecodingError(_) => {
HttpError::ValidationError("base64 decoding error".into())
},
UploadError::InvalidMediaType => {
HttpError::ValidationError("invalid media type".into())
},
_ => HttpError::InternalError,
}
})?;
)?;
profile_data.clean()?;
current_user.profile = update_profile(
db_client,

View file

@ -5,7 +5,7 @@ use crate::config::Config;
use crate::database::{Pool, get_database_client};
use crate::errors::HttpError;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::mastodon_api::uploads::{UploadError, save_b64_file};
use crate::mastodon_api::uploads::save_b64_file;
use crate::models::attachments::queries::create_attachment;
use super::types::{AttachmentCreateData, Attachment};
@ -21,12 +21,7 @@ async fn create_attachment_view(
let (file_name, media_type) = save_b64_file(
&attachment_data.file,
&config.media_dir(),
).map_err(|err| match err {
UploadError::Base64DecodingError(err) => {
HttpError::ValidationError(err.to_string())
},
_ => HttpError::InternalError,
})?;
)?;
let db_attachment = create_attachment(
db_client,
&current_user.id,

View file

@ -12,3 +12,4 @@ pub mod timelines;
mod uploads;
const MASTODON_API_VERSION: &str = "3.0.0";
pub use uploads::UPLOAD_MAX_SIZE;

View file

@ -1,7 +1,10 @@
use std::path::Path;
use crate::errors::HttpError;
use crate::utils::files::{save_file, sniff_media_type};
pub const UPLOAD_MAX_SIZE: usize = 1024 * 1024 * 5;
#[derive(thiserror::Error, Debug)]
pub enum UploadError {
#[error(transparent)]
@ -10,15 +13,32 @@ pub enum UploadError {
#[error("base64 decoding error")]
Base64DecodingError(#[from] base64::DecodeError),
#[error("file is too large")]
TooLarge,
#[error("invalid media type")]
InvalidMediaType,
}
impl From<UploadError> for HttpError {
fn from(error: UploadError) -> Self {
match error {
UploadError::WriteError(_) => HttpError::InternalError,
other_error => {
HttpError::ValidationError(other_error.to_string())
},
}
}
}
pub fn save_b64_file(
b64data: &str,
output_dir: &Path,
) -> Result<(String, Option<String>), UploadError> {
let data = base64::decode(b64data)?;
if data.len() > UPLOAD_MAX_SIZE {
return Err(UploadError::TooLarge);
};
Ok(save_file(data, output_dir, None)?)
}
@ -28,6 +48,9 @@ pub fn save_validated_b64_file(
media_type_prefix: &str,
) -> Result<(String, String), UploadError> {
let data = base64::decode(b64data)?;
if data.len() > UPLOAD_MAX_SIZE {
return Err(UploadError::TooLarge);
};
let media_type = sniff_media_type(&data)
.ok_or(UploadError::InvalidMediaType)?;
if !media_type.starts_with(media_type_prefix) {