fix(backend): match the authenticated user into get/download/delete operations

This commit is contained in:
2026-06-03 23:34:29 +03:00
parent 41ea8b598a
commit 0f6bfe2111
11 changed files with 449 additions and 14 deletions

View File

@@ -106,12 +106,13 @@ impl FileRepository {
pub async fn download_file(
&self,
file_id: i64,
user_id: i64,
) -> Result<impl Stream<Item = std::io::Result<Bytes>> + use<>, LoftError> {
info!(
"Fetching metadata of file \"{}\" from file_records",
file_id
);
let record = self.get_file(file_id).await?;
let record = self.get_file(file_id, user_id).await?;
info!("Downloading file \"{}\"", file_id);
let reader = self.op.reader(&record.storage_key).await.unwrap();
let stream = reader.into_bytes_stream(0..).await.unwrap();
@@ -119,7 +120,7 @@ impl FileRepository {
Ok(stream)
}
pub async fn get_file(&self, file_id: i64) -> Result<FileRecord, LoftError> {
pub async fn get_file(&self, file_id: i64, user_id: i64) -> Result<FileRecord, LoftError> {
info!(
"Fetching metadata of file \"{}\" from file_records",
file_id
@@ -130,8 +131,10 @@ impl FileRepository {
SELECT *
FROM file_records fr
WHERE fr.id = $1
AND fr.user_id = $2
"#,
file_id
file_id,
user_id
)
.fetch_optional(&self.pool)
.await
@@ -141,12 +144,12 @@ impl FileRepository {
Ok(record)
}
pub async fn delete_file(&self, file_id: i64) -> Result<FileRecord, LoftError> {
pub async fn delete_file(&self, file_id: i64, user_id: i64) -> Result<FileRecord, LoftError> {
info!(
"Fetching metadata of file \"{}\" from file_records",
file_id
);
let record = self.get_file(file_id).await?;
let record = self.get_file(file_id, user_id).await?;
info!("Deleting file bytes \"{}\"", file_id);
self.op.delete(&record.storage_key).await.unwrap();
@@ -156,9 +159,11 @@ impl FileRepository {
r#"
DELETE FROM file_records
WHERE id = $1
AND user_id = $2
RETURNING *
"#,
file_id
file_id,
user_id
)
.fetch_optional(&self.pool)
.await
@@ -407,7 +412,10 @@ mod tests {
.await
.unwrap();
let _downloaded = file_repository.download_file(file_record.id).await.unwrap();
let _downloaded = file_repository
.download_file(file_record.id, user.id)
.await
.unwrap();
//TODO: add assert
@@ -422,7 +430,7 @@ mod tests {
truncate_file_records(&file_repository.pool).await;
assert!(matches!(
file_repository.download_file(i64::MAX).await,
file_repository.download_file(i64::MAX, 1).await,
Err(LoftError::FileIdNotFound)
));
}
@@ -453,10 +461,13 @@ mod tests {
.await
.unwrap();
file_repository.delete_file(file_record.id).await.unwrap();
file_repository
.delete_file(file_record.id, user.id)
.await
.unwrap();
assert!(matches!(
file_repository.download_file(file_record.id).await,
file_repository.download_file(file_record.id, user.id).await,
Err(LoftError::FileIdNotFound)
));
truncate_file_records(&file_repository.pool).await;
@@ -469,7 +480,7 @@ mod tests {
let file_repository = file_repository().await.unwrap();
assert!(matches!(
file_repository.delete_file(99).await,
file_repository.delete_file(99, 1).await,
Err(LoftError::FileIdNotFound)
));
}

View File

@@ -57,28 +57,37 @@ async fn upload_file(
#[axum::debug_handler]
async fn get_file(
State(file_repository): State<FileRepository>,
ctx: Ctx,
Path(file_id): Path<u64>,
) -> Result<Json<FileRecord>, LoftError> {
let record = file_repository.get_file(file_id as i64).await?;
let record = file_repository
.get_file(file_id as i64, ctx.user_id())
.await?;
Ok(Json(record))
}
#[axum::debug_handler]
async fn download_file(
State(file_repository): State<FileRepository>,
ctx: Ctx,
Path(file_id): Path<u64>,
) -> Result<impl IntoResponse, LoftError> {
let stream = file_repository.download_file(file_id as i64).await?;
let stream = file_repository
.download_file(file_id as i64, ctx.user_id())
.await?;
Ok(Body::from_stream(stream))
}
async fn delete_file(
State(file_repository): State<FileRepository>,
ctx: Ctx,
Path(file_id): Path<u64>,
) -> Result<Json<FileRecord>, LoftError> {
info!("handler: delete_file");
let file = file_repository.delete_file(file_id as i64).await?;
let file = file_repository
.delete_file(file_id as i64, ctx.user_id())
.await?;
Ok(Json(file))
}