Refactor utils::files and move upload helpers to mastodon_api::uploads module
This commit is contained in:
parent
c546840787
commit
3b56b29785
7 changed files with 62 additions and 57 deletions
|
@ -9,7 +9,7 @@ use crate::activitypub::actors::types::{Actor, ActorAddress};
|
|||
use crate::activitypub::constants::ACTIVITY_CONTENT_TYPE;
|
||||
use crate::config::Instance;
|
||||
use crate::http_signatures::create::{create_http_signature, SignatureError};
|
||||
use crate::utils::files::{save_file, FileError};
|
||||
use crate::utils::files::save_file;
|
||||
use crate::webfinger::types::JsonResourceDescriptor;
|
||||
|
||||
const FETCHER_CONNECTION_TIMEOUT: u64 = 30;
|
||||
|
@ -26,7 +26,7 @@ pub enum FetchError {
|
|||
JsonParseError(#[from] serde_json::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
FileError(#[from] FileError),
|
||||
FileError(#[from] std::io::Error),
|
||||
|
||||
#[error("{0}")]
|
||||
OtherError(&'static str),
|
||||
|
@ -86,7 +86,7 @@ pub async fn fetch_file(
|
|||
let client = build_client()?;
|
||||
let response = client.get(url).send().await?;
|
||||
let file_data = response.bytes().await?;
|
||||
let (file_name, media_type) = save_file(file_data.to_vec(), output_dir)?;
|
||||
let (file_name, media_type) = save_file(file_data.to_vec(), output_dir, None)?;
|
||||
Ok((file_name, media_type))
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use uuid::Uuid;
|
|||
|
||||
use crate::errors::ValidationError;
|
||||
use crate::frontend::get_subscription_page_url;
|
||||
use crate::mastodon_api::uploads::{UploadError, save_validated_b64_file};
|
||||
use crate::models::profiles::types::{
|
||||
DbActorProfile,
|
||||
ExtraField,
|
||||
|
@ -20,7 +21,7 @@ use crate::models::users::types::{
|
|||
validate_local_username,
|
||||
User,
|
||||
};
|
||||
use crate::utils::files::{FileError, save_validated_b64_file, get_file_url};
|
||||
use crate::utils::files::get_file_url;
|
||||
|
||||
/// https://docs.joinmastodon.org/entities/field/
|
||||
#[derive(Serialize)]
|
||||
|
@ -182,7 +183,7 @@ fn process_b64_image_field_value(
|
|||
form_value: Option<String>,
|
||||
db_value: Option<String>,
|
||||
output_dir: &Path,
|
||||
) -> Result<Option<String>, FileError> {
|
||||
) -> Result<Option<String>, UploadError> {
|
||||
let maybe_file_name = match form_value {
|
||||
Some(b64_data) => {
|
||||
if b64_data.is_empty() {
|
||||
|
@ -210,7 +211,7 @@ impl AccountUpdateData {
|
|||
current_identity_proofs: &[IdentityProof],
|
||||
current_payment_options: &[PaymentOption],
|
||||
media_dir: &Path,
|
||||
) -> Result<ProfileUpdateData, FileError> {
|
||||
) -> Result<ProfileUpdateData, UploadError> {
|
||||
let avatar = process_b64_image_field_value(
|
||||
self.avatar, current_avatar.clone(), media_dir,
|
||||
)?;
|
||||
|
|
|
@ -30,6 +30,7 @@ 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,
|
||||
|
@ -64,7 +65,6 @@ use crate::utils::crypto::{
|
|||
generate_private_key,
|
||||
serialize_private_key,
|
||||
};
|
||||
use crate::utils::files::FileError;
|
||||
use super::helpers::get_relationship;
|
||||
use super::types::{
|
||||
Account,
|
||||
|
@ -197,10 +197,10 @@ async fn update_credentials(
|
|||
)
|
||||
.map_err(|err| {
|
||||
match err {
|
||||
FileError::Base64DecodingError(_) => {
|
||||
UploadError::Base64DecodingError(_) => {
|
||||
HttpError::ValidationError("base64 decoding error".into())
|
||||
},
|
||||
FileError::InvalidMediaType => {
|
||||
UploadError::InvalidMediaType => {
|
||||
HttpError::ValidationError("invalid media type".into())
|
||||
},
|
||||
_ => HttpError::InternalError,
|
||||
|
|
|
@ -5,8 +5,8 @@ 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::models::attachments::queries::create_attachment;
|
||||
use crate::utils::files::{FileError, save_b64_file};
|
||||
use super::types::{AttachmentCreateData, Attachment};
|
||||
|
||||
#[post("")]
|
||||
|
@ -22,7 +22,9 @@ async fn create_attachment_view(
|
|||
&attachment_data.file,
|
||||
&config.media_dir(),
|
||||
).map_err(|err| match err {
|
||||
FileError::Base64DecodingError(err) => HttpError::ValidationError(err.to_string()),
|
||||
UploadError::Base64DecodingError(err) => {
|
||||
HttpError::ValidationError(err.to_string())
|
||||
},
|
||||
_ => HttpError::InternalError,
|
||||
})?;
|
||||
let db_attachment = create_attachment(
|
||||
|
|
|
@ -9,5 +9,6 @@ mod pagination;
|
|||
pub mod search;
|
||||
pub mod statuses;
|
||||
pub mod timelines;
|
||||
mod uploads;
|
||||
|
||||
const MASTODON_API_VERSION: &str = "3.0.0";
|
||||
|
|
39
src/mastodon_api/uploads.rs
Normal file
39
src/mastodon_api/uploads.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
use std::path::Path;
|
||||
|
||||
use crate::utils::files::{save_file, sniff_media_type};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum UploadError {
|
||||
#[error(transparent)]
|
||||
WriteError(#[from] std::io::Error),
|
||||
|
||||
#[error("base64 decoding error")]
|
||||
Base64DecodingError(#[from] base64::DecodeError),
|
||||
|
||||
#[error("invalid media type")]
|
||||
InvalidMediaType,
|
||||
}
|
||||
|
||||
pub fn save_b64_file(
|
||||
b64data: &str,
|
||||
output_dir: &Path,
|
||||
) -> Result<(String, Option<String>), UploadError> {
|
||||
let data = base64::decode(b64data)?;
|
||||
Ok(save_file(data, output_dir, None)?)
|
||||
}
|
||||
|
||||
pub fn save_validated_b64_file(
|
||||
b64data: &str,
|
||||
output_dir: &Path,
|
||||
media_type_prefix: &str,
|
||||
) -> Result<(String, String), UploadError> {
|
||||
let data = base64::decode(b64data)?;
|
||||
let media_type = sniff_media_type(&data)
|
||||
.ok_or(UploadError::InvalidMediaType)?;
|
||||
if !media_type.starts_with(media_type_prefix) {
|
||||
return Err(UploadError::InvalidMediaType);
|
||||
};
|
||||
let (file_name, _) =
|
||||
save_file(data, output_dir, Some(media_type.clone()))?;
|
||||
Ok((file_name, media_type))
|
||||
}
|
|
@ -4,6 +4,7 @@ use std::fs::{
|
|||
File,
|
||||
Permissions,
|
||||
};
|
||||
use std::io::Error;
|
||||
use std::io::prelude::*;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::path::Path;
|
||||
|
@ -12,19 +13,7 @@ use mime_guess::get_mime_extensions_str;
|
|||
use mime_sniffer::MimeTypeSniffer;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum FileError {
|
||||
#[error(transparent)]
|
||||
WriteError(#[from] std::io::Error),
|
||||
|
||||
#[error("base64 decoding error")]
|
||||
Base64DecodingError(#[from] base64::DecodeError),
|
||||
|
||||
#[error("invalid media type")]
|
||||
InvalidMediaType,
|
||||
}
|
||||
|
||||
fn sniff_media_type(data: &[u8]) -> Option<String> {
|
||||
pub fn sniff_media_type(data: &[u8]) -> Option<String> {
|
||||
data.sniff_mime_type().map(|val| val.to_string())
|
||||
}
|
||||
|
||||
|
@ -42,13 +31,13 @@ fn get_file_name(data: &[u8], media_type: Option<&str>) -> String {
|
|||
file_name
|
||||
}
|
||||
|
||||
pub fn write_file(data: &[u8], file_path: &Path) -> Result<(), FileError> {
|
||||
pub fn write_file(data: &[u8], file_path: &Path) -> Result<(), Error> {
|
||||
let mut file = File::create(file_path)?;
|
||||
file.write_all(data)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_file_permissions(file_path: &Path, mode: u32) -> Result<(), FileError> {
|
||||
pub fn set_file_permissions(file_path: &Path, mode: u32) -> Result<(), Error> {
|
||||
let permissions = Permissions::from_mode(mode);
|
||||
set_permissions(file_path, permissions)?;
|
||||
Ok(())
|
||||
|
@ -57,43 +46,16 @@ pub fn set_file_permissions(file_path: &Path, mode: u32) -> Result<(), FileError
|
|||
pub fn save_file(
|
||||
data: Vec<u8>,
|
||||
output_dir: &Path,
|
||||
) -> Result<(String, Option<String>), FileError> {
|
||||
let media_type = sniff_media_type(&data);
|
||||
media_type: Option<String>,
|
||||
) -> Result<(String, Option<String>), Error> {
|
||||
// Sniff media type if not provided
|
||||
let media_type = media_type.or(sniff_media_type(&data));
|
||||
let file_name = get_file_name(&data, media_type.as_deref());
|
||||
let file_path = output_dir.join(&file_name);
|
||||
write_file(&data, &file_path)?;
|
||||
Ok((file_name, media_type))
|
||||
}
|
||||
|
||||
pub fn save_b64_file(
|
||||
b64data: &str,
|
||||
output_dir: &Path,
|
||||
) -> Result<(String, Option<String>), FileError> {
|
||||
let data = base64::decode(b64data)?;
|
||||
let media_type = sniff_media_type(&data);
|
||||
let file_name = get_file_name(&data, media_type.as_deref());
|
||||
let file_path = output_dir.join(&file_name);
|
||||
write_file(&data, &file_path)?;
|
||||
Ok((file_name, media_type))
|
||||
}
|
||||
|
||||
pub fn save_validated_b64_file(
|
||||
b64data: &str,
|
||||
output_dir: &Path,
|
||||
media_type_prefix: &str,
|
||||
) -> Result<(String, String), FileError> {
|
||||
let data = base64::decode(b64data)?;
|
||||
let media_type = sniff_media_type(&data)
|
||||
.ok_or(FileError::InvalidMediaType)?;
|
||||
if !media_type.starts_with(media_type_prefix) {
|
||||
return Err(FileError::InvalidMediaType);
|
||||
}
|
||||
let file_name = get_file_name(&data, Some(&media_type));
|
||||
let file_path = output_dir.join(&file_name);
|
||||
write_file(&data, &file_path)?;
|
||||
Ok((file_name, media_type))
|
||||
}
|
||||
|
||||
pub fn get_file_url(instance_url: &str, file_name: &str) -> String {
|
||||
format!("{}/media/{}", instance_url, file_name)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue