diff --git a/netmito/src/api/user.rs b/netmito/src/api/user.rs index 7c43b3d..d19beac 100644 --- a/netmito/src/api/user.rs +++ b/netmito/src/api/user.rs @@ -18,8 +18,8 @@ use crate::{ auth::{user_auth_middleware, user_login, AuthUser}, group::query_user_groups, s3::{ - get_artifact, query_attachment_list, user_get_attachment, user_upload_artifact, - user_upload_attachment, + get_artifact, query_attachment_list, user_get_attachment, user_get_attachment_db, + user_upload_artifact, user_upload_attachment, }, task::{ get_task, query_task_list, user_cancel_task, user_change_task, user_change_task_labels, @@ -44,6 +44,10 @@ pub fn user_router(st: InfraPool) -> Router { .route("/artifacts/:uuid/:content_type", get(download_artifact)) .route("/artifacts", post(upload_artifact)) .route("/attachments/:group_name/*key", get(download_attachment)) + .route( + "/attachments/meta/:group_name/*key", + get(get_attachment_metadata), + ) .route("/attachments", post(upload_attachment)) .route("/workers/:uuid/", get(query_worker).delete(shutdown_worker)) .route("/workers/:uuid/tags", put(replace_worker_tags)) @@ -265,6 +269,24 @@ pub async fn download_attachment( Ok(Json(attachment)) } +pub async fn get_attachment_metadata( + Extension(u): Extension, + State(pool): State, + Path((group_name, key)): Path<(String, String)>, +) -> Result, ApiError> { + let attachment = user_get_attachment_db(&pool, u.id, group_name, key) + .await + .map_err(|e| match e { + crate::error::Error::AuthError(err) => ApiError::AuthError(err), + crate::error::Error::ApiError(e) => e, + _ => { + tracing::error!("{}", e); + ApiError::InternalServerError + } + })?; + Ok(Json(attachment)) +} + pub async fn query_attachments( Extension(u): Extension, State(pool): State, diff --git a/netmito/src/schema.rs b/netmito/src/schema.rs index ade81e1..50c1724 100644 --- a/netmito/src/schema.rs +++ b/netmito/src/schema.rs @@ -261,6 +261,14 @@ pub struct TaskQueryResp { pub artifacts: Vec, } +#[derive(Debug, Serialize, Deserialize)] +pub struct AttachmentMetadata { + pub content_type: AttachmentContentType, + pub size: i64, + pub created_at: OffsetDateTime, + pub updated_at: OffsetDateTime, +} + #[derive(Debug, Serialize, Deserialize)] pub struct AttachmentsQueryReq { pub group_name: Option, diff --git a/netmito/src/service/s3.rs b/netmito/src/service/s3.rs index d5a5a33..25d0c79 100644 --- a/netmito/src/service/s3.rs +++ b/netmito/src/service/s3.rs @@ -11,7 +11,7 @@ use sea_orm::{ use tokio::io::AsyncWriteExt; use uuid::Uuid; -use crate::schema::RemoteResourceDownloadResp; +use crate::schema::{AttachmentMetadata, RemoteResourceDownloadResp}; use crate::{config::InfraPool, error::S3Error}; use crate::{ entity::StoredTaskModel, @@ -346,6 +346,44 @@ pub async fn get_attachment( }) } +pub async fn user_get_attachment_db( + pool: &InfraPool, + user_id: i64, + group_name: String, + key: String, +) -> Result { + let group_id = Group::Entity::find() + .filter(Group::Column::GroupName.eq(group_name.clone())) + .one(&pool.db) + .await? + .ok_or(crate::error::ApiError::NotFound(format!( + "Attachment of group {} and key {}", + group_name, key + )))? + .id; + UserGroup::Entity::find() + .filter(UserGroup::Column::UserId.eq(user_id)) + .filter(UserGroup::Column::GroupId.eq(group_id)) + .one(&pool.db) + .await? + .ok_or(AuthError::PermissionDenied)?; + let attachment = Attachment::Entity::find() + .filter(Attachment::Column::GroupId.eq(group_id)) + .filter(Attachment::Column::Key.eq(key.clone())) + .one(&pool.db) + .await? + .ok_or(crate::error::ApiError::NotFound(format!( + "Attachment of group {} and key {}", + group_name, key + )))?; + Ok(AttachmentMetadata { + content_type: attachment.content_type, + size: attachment.size, + created_at: attachment.created_at, + updated_at: attachment.updated_at, + }) +} + pub async fn user_get_attachment( pool: &InfraPool, user_id: i64,