mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 00:47:53 +00:00
don't upload duplicates
This commit is contained in:
1 parent
ba9f716ff8
commit
da05885d7d
4 files changed
+144
-7
No files matched your search
@@ -0,0 +1,104 @@
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, Utc};
|
||||
use crate::helpers::boolean_converters::i8_to_bool;
|
||||
use enums::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use errors::AnyhowResult;
|
||||
use log::{warn, info, error};
|
||||
use sqlx::pool::PoolConnection;
|
||||
use sqlx::{MySql, MySqlPool};
|
||||
use enums::by_table::media_uploads::media_upload_type::MediaUploadType;
|
||||
use tokens::files::media_upload::MediaUploadToken;
|
||||
use tokens::users::user::UserToken;
|
||||
use tokens::voice_conversion::model::VoiceConversionModelToken;
|
||||
|
||||
pub struct MediaUploadRecord {
|
||||
pub token: MediaUploadToken,
|
||||
pub media_type: MediaUploadType,
|
||||
|
||||
pub maybe_original_filename: Option<String>,
|
||||
|
||||
pub original_file_size_bytes: u32,
|
||||
pub original_duration_millis: u32,
|
||||
|
||||
pub creator_set_visibility: Visibility,
|
||||
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
/// Query for a media upload to see if we already uploaded it.
|
||||
pub async fn get_media_upload_by_uuid(
|
||||
uuid_idempotency_token: &str,
|
||||
mysql_pool: &MySqlPool,
|
||||
) -> AnyhowResult<Option<MediaUploadRecord>> {
|
||||
let mut connection = mysql_pool.acquire().await?;
|
||||
get_media_upload_by_uuid_with_connection(
|
||||
uuid_idempotency_token,
|
||||
&mut connection
|
||||
).await
|
||||
}
|
||||
|
||||
/// Query for a media upload to see if we already uploaded it.
|
||||
pub async fn get_media_upload_by_uuid_with_connection(
|
||||
uuid_idempotency_token: &str,
|
||||
mysql_connection: &mut PoolConnection<MySql>,
|
||||
) -> AnyhowResult<Option<MediaUploadRecord>> {
|
||||
let maybe_result = sqlx::query_as!(
|
||||
RawMediaUploadRecord,
|
||||
r#"
|
||||
SELECT
|
||||
mu.token as `token: tokens::files::media_upload::MediaUploadToken`,
|
||||
mu.media_type as `media_type: enums::by_table::media_uploads::media_upload_type::MediaUploadType`,
|
||||
mu.maybe_original_filename,
|
||||
mu.original_file_size_bytes,
|
||||
mu.original_duration_millis,
|
||||
mu.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,
|
||||
mu.created_at,
|
||||
mu.updated_at
|
||||
FROM media_uploads as mu
|
||||
WHERE
|
||||
mu.uuid_idempotency_token = ?
|
||||
AND mu.user_deleted_at IS NULL
|
||||
AND mu.mod_deleted_at IS NULL
|
||||
"#,
|
||||
uuid_idempotency_token,
|
||||
)
|
||||
.fetch_one(mysql_connection)
|
||||
.await;
|
||||
|
||||
match maybe_result {
|
||||
Err(err) => match err {
|
||||
sqlx::Error::RowNotFound => Ok(None),
|
||||
_ => {
|
||||
error!("list media uploads db error: {:?}", err);
|
||||
Err(anyhow!("error with query: {:?}", err))
|
||||
}
|
||||
},
|
||||
Ok(upload) => Ok(Some(MediaUploadRecord {
|
||||
token: upload.token,
|
||||
media_type: upload.media_type,
|
||||
maybe_original_filename: upload.maybe_original_filename,
|
||||
original_file_size_bytes: upload.original_file_size_bytes as u32,
|
||||
original_duration_millis: upload.original_duration_millis as u32,
|
||||
creator_set_visibility: upload.creator_set_visibility,
|
||||
created_at: upload.created_at,
|
||||
updated_at: upload.updated_at,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
struct RawMediaUploadRecord {
|
||||
pub token: MediaUploadToken,
|
||||
pub media_type: MediaUploadType,
|
||||
|
||||
pub maybe_original_filename: Option<String>,
|
||||
|
||||
pub original_file_size_bytes: i32,
|
||||
pub original_duration_millis: i32,
|
||||
|
||||
pub creator_set_visibility: Visibility,
|
||||
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod get_media_upload_by_uuid;
|
||||
pub mod insert_media_upload;
|
||||
pub mod reverse_list_user_media_uploads_of_type;
|
||||
-1
@@ -12,7 +12,6 @@ use tokens::files::media_upload::MediaUploadToken;
|
||||
use tokens::users::user::UserToken;
|
||||
use tokens::voice_conversion::model::VoiceConversionModelToken;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct MediaUploadRecord {
|
||||
pub token: MediaUploadToken,
|
||||
pub media_type: MediaUploadType,
|
||||
|
||||
+39
-6
@@ -22,7 +22,7 @@ use files::hash::hash_bytes_sha2;
|
||||
use files::mimetype::{get_mimetype_for_bytes, get_mimetype_for_bytes_or_default};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
use log::{info, warn, log};
|
||||
use log::{info, warn, log, error};
|
||||
use media::decode_basic_audio_info::decode_basic_audio_info;
|
||||
use regex::Regex;
|
||||
use sqlx::error::DatabaseError;
|
||||
@@ -35,6 +35,7 @@ use symphonia::core::formats::FormatOptions;
|
||||
use symphonia::core::io::{MediaSourceStream, ReadOnlySource};
|
||||
use symphonia::core::meta::MetadataOptions;
|
||||
use symphonia::core::probe::Hint;
|
||||
use mysql_queries::queries::media_uploads::get_media_upload_by_uuid::{get_media_upload_by_uuid, get_media_upload_by_uuid_with_connection};
|
||||
use tokens::files::media_upload::MediaUploadToken;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -81,11 +82,19 @@ pub async fn upload_media_handler(
|
||||
mut multipart_payload: Multipart,
|
||||
) -> Result<HttpResponse, UploadMediaError> {
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
.acquire()
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
UploadMediaError::ServerError
|
||||
})?;
|
||||
|
||||
// ==================== READ SESSION ==================== //
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.maybe_get_user_session_from_connection(&http_request, &mut mysql_connection)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
@@ -125,6 +134,27 @@ pub async fn upload_media_handler(
|
||||
let uuid_idempotency_token = upload_media_request.uuid_idempotency_token
|
||||
.ok_or(UploadMediaError::BadInput("no uuid".to_string()))?;
|
||||
|
||||
let maybe_existing_upload =
|
||||
get_media_upload_by_uuid_with_connection(&uuid_idempotency_token, &mut mysql_connection)
|
||||
.await;
|
||||
|
||||
match maybe_existing_upload {
|
||||
Err(err) => {
|
||||
error!("Error checking for previous upload: {:?}", err);
|
||||
return Err(UploadMediaError::ServerError);
|
||||
}
|
||||
Ok(Some(upload)) => {
|
||||
// File already uploaded and frontend didn't protect us.
|
||||
return render_ok_response(UploadMediaSuccessResponse {
|
||||
success: true,
|
||||
upload_token: upload.token,
|
||||
});
|
||||
}
|
||||
Ok(None) => {
|
||||
// Proceed.
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(reason) = validate_idempotency_token_format(&uuid_idempotency_token) {
|
||||
return Err(UploadMediaError::BadInput(reason));
|
||||
}
|
||||
@@ -271,15 +301,18 @@ pub async fn upload_media_handler(
|
||||
UploadMediaError::ServerError
|
||||
})?;
|
||||
|
||||
let response = UploadMediaSuccessResponse {
|
||||
render_ok_response(UploadMediaSuccessResponse {
|
||||
success: true,
|
||||
upload_token: token,
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fn render_ok_response(response: UploadMediaSuccessResponse) -> Result<HttpResponse, UploadMediaError> {
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| UploadMediaError::ServerError)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
return Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
.body(body));
|
||||
}
|
||||
Reference in new issue
Block a user