fix(backend): match the authenticated user into get/download/delete operations
This commit is contained in:
14
backend/.sqlx/query-11e96cfd8c2736f13ce55975ea910dd68640f6f14e38a4b3342d514804e3de27.json
generated
Normal file
14
backend/.sqlx/query-11e96cfd8c2736f13ce55975ea910dd68640f6f14e38a4b3342d514804e3de27.json
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM sessions WHERE id = $1",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "11e96cfd8c2736f13ce55975ea910dd68640f6f14e38a4b3342d514804e3de27"
|
||||
}
|
||||
40
backend/.sqlx/query-24fd2306e40be21dc82660ec3f42f95928849706ecb75fe1cb8b606aa3cf2971.json
generated
Normal file
40
backend/.sqlx/query-24fd2306e40be21dc82660ec3f42f95928849706ecb75fe1cb8b606aa3cf2971.json
generated
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT *\n FROM users u\n WHERE u.username = $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "username",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "password_hash",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "24fd2306e40be21dc82660ec3f42f95928849706ecb75fe1cb8b606aa3cf2971"
|
||||
}
|
||||
58
backend/.sqlx/query-31e1333f84168ce0ba75c474f2a1d7a0d0c4d04857130da327b07821f20cf07c.json
generated
Normal file
58
backend/.sqlx/query-31e1333f84168ce0ba75c474f2a1d7a0d0c4d04857130da327b07821f20cf07c.json
generated
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT *\n FROM file_records fr\n WHERE user_id = $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "file_type",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "size",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "uploaded_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "storage_key",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "user_id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "31e1333f84168ce0ba75c474f2a1d7a0d0c4d04857130da327b07821f20cf07c"
|
||||
}
|
||||
62
backend/.sqlx/query-638f29a940b4514c1ebd047975e1e1fb8d9b647dbe6ef025dbb13b6417b6e91e.json
generated
Normal file
62
backend/.sqlx/query-638f29a940b4514c1ebd047975e1e1fb8d9b647dbe6ef025dbb13b6417b6e91e.json
generated
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO file_records (user_id, name, file_type, size, storage_key)\n VALUES ($1, $2, $3, $4, $5)\n RETURNING *\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "file_type",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "size",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "uploaded_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "storage_key",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "user_id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Text",
|
||||
"Text",
|
||||
"Int8",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "638f29a940b4514c1ebd047975e1e1fb8d9b647dbe6ef025dbb13b6417b6e91e"
|
||||
}
|
||||
41
backend/.sqlx/query-65d6e198b36dc758d3da0e29374e5fabc8633a63f6c213b61a7e1902baad157b.json
generated
Normal file
41
backend/.sqlx/query-65d6e198b36dc758d3da0e29374e5fabc8633a63f6c213b61a7e1902baad157b.json
generated
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO users (username, password_hash)\n VALUES ($1, $2)\n RETURNING *\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "username",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "password_hash",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "65d6e198b36dc758d3da0e29374e5fabc8633a63f6c213b61a7e1902baad157b"
|
||||
}
|
||||
40
backend/.sqlx/query-7d78918485f2c98b302a9d4c0801ba3a0f3af9273db03691317ab5e8676d61b7.json
generated
Normal file
40
backend/.sqlx/query-7d78918485f2c98b302a9d4c0801ba3a0f3af9273db03691317ab5e8676d61b7.json
generated
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT *\n FROM sessions s\n WHERE s.id = $1\n AND s.expires_at > NOW()\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "user_id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "expires_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "7d78918485f2c98b302a9d4c0801ba3a0f3af9273db03691317ab5e8676d61b7"
|
||||
}
|
||||
42
backend/.sqlx/query-89c32ebfbbdf3f7d6fe47becb7b074a737b1627bc9c4cabbf2abe145d842b8f9.json
generated
Normal file
42
backend/.sqlx/query-89c32ebfbbdf3f7d6fe47becb7b074a737b1627bc9c4cabbf2abe145d842b8f9.json
generated
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n INSERT INTO sessions (id, user_id, expires_at)\n VALUES ($1, $2, $3)\n RETURNING *\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "user_id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "expires_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int8",
|
||||
"Timestamptz"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "89c32ebfbbdf3f7d6fe47becb7b074a737b1627bc9c4cabbf2abe145d842b8f9"
|
||||
}
|
||||
59
backend/.sqlx/query-d059130365f7e4b3a6ae49bee073897a12e58a29b0b2e5c814ff8cb392e32fa0.json
generated
Normal file
59
backend/.sqlx/query-d059130365f7e4b3a6ae49bee073897a12e58a29b0b2e5c814ff8cb392e32fa0.json
generated
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT *\n FROM file_records fr\n WHERE fr.id = $1\n AND fr.user_id = $2\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "file_type",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "size",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "uploaded_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "storage_key",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "user_id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "d059130365f7e4b3a6ae49bee073897a12e58a29b0b2e5c814ff8cb392e32fa0"
|
||||
}
|
||||
59
backend/.sqlx/query-f703be0699214db15f5d65ea7ec3186407f6a72cc1596f652fcdcd7c7f49562d.json
generated
Normal file
59
backend/.sqlx/query-f703be0699214db15f5d65ea7ec3186407f6a72cc1596f652fcdcd7c7f49562d.json
generated
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n DELETE FROM file_records\n WHERE id = $1\n AND user_id = $2\n RETURNING *\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "file_type",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "size",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "uploaded_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "storage_key",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "user_id",
|
||||
"type_info": "Int8"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "f703be0699214db15f5d65ea7ec3186407f6a72cc1596f652fcdcd7c7f49562d"
|
||||
}
|
||||
@@ -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)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user