11import uuid
22from typing import Any
33
4+ import boto3
45from fastapi import APIRouter , HTTPException
6+ from fastapi .responses import RedirectResponse
57from sqlmodel import func , select
68
7- from app .api .deps import CurrentUser , SessionDep
9+ from app .api .deps import AwsDep , CurrentUser , SessionDep
10+ from app .core .config import Settings
811from app .models .attachments import (
912 Attachment ,
1013 AttachmentCreate ,
14+ AttachmentCreatePublic ,
1115 AttachmentPublic ,
1216 AttachmentsPublic ,
1317 AttachmentUpdate ,
@@ -22,7 +26,7 @@ def read_attachments(
2226 session : SessionDep , current_user : CurrentUser , skip : int = 0 , limit : int = 100
2327) -> Any :
2428 """
25- Retrieve attachments.
29+ Retrieve list of all attachments.
2630 """
2731 count_statement = select (func .count ()).select_from (Attachment )
2832 count = session .exec (count_statement ).one ()
@@ -31,64 +35,68 @@ def read_attachments(
3135
3236 return AttachmentsPublic (data = attachments , count = count )
3337
38+ @router .get ("/{id}/content" )
39+ def read_attachment_content (session : SessionDep , aws_client : AwsDep , current_user : CurrentUser , id : uuid .UUID ) -> Any :
40+ """
41+ Get attachment content by ID.
42+ """
43+ attachment = session .get (Attachment , id )
44+ if not attachment :
45+ raise HTTPException (status_code = 404 , detail = "Attachment not found" )
46+
47+ try :
48+ presigned_url = aws_client .generate_presigned_url (
49+ "get_object" ,
50+ Params = {
51+ "Bucket" : Settings .AWS_S3_ATTACHMENTS_BUCKET ,
52+ "Key" : attachment .storage_path ,
53+ "ContentDisposition" : f"attachment; filename={ attachment .file_name } " ,
54+ },
55+ ExpiresIn = 3600 ,
56+ )
57+ except Exception as e :
58+ raise HTTPException (status_code = 500 , detail = "Could not generate presigned URL" )
59+
60+ return RedirectResponse (status_code = 302 , url = presigned_url )
61+
3462
3563@router .get ("/{id}" , response_model = AttachmentPublic )
3664def read_attachment (session : SessionDep , current_user : CurrentUser , id : uuid .UUID ) -> Any :
3765 """
38- Get attachment by ID.
66+ Get attachment details by ID.
3967 """
4068 attachment = session .get (Attachment , id )
4169 if not attachment :
4270 raise HTTPException (status_code = 404 , detail = "Attachment not found" )
4371 return attachment
4472
4573
46- @router .post ("/" , response_model = AttachmentPublic )
74+ @router .post ("/" , response_model = AttachmentCreatePublic )
4775def create_attachment (
48- * , session : SessionDep , current_user : CurrentUser , attachment_in : AttachmentCreate
76+ * , session : SessionDep , aws_client : AwsDep , current_user : CurrentUser , attachment_in : AttachmentCreate
4977) -> Any :
5078 """
51- Create new attachment.
79+ Create a new attachment.
5280 """
5381 attachment = Attachment .model_validate (attachment_in )
5482 session .add (attachment )
5583 session .commit ()
5684 session .refresh (attachment )
57- return attachment
58-
5985
60- @router .put ("/{id}" , response_model = AttachmentPublic )
61- def update_attachment (
62- * ,
63- session : SessionDep ,
64- current_user : CurrentUser ,
65- id : uuid .UUID ,
66- attachment_in : AttachmentUpdate ,
67- ) -> Any :
68- """
69- Update an attachment.
70- """
71- attachment = session .get (Attachment , id )
72- if not attachment :
73- raise HTTPException (status_code = 404 , detail = "Attachment not found" )
74- update_dict = attachment_in .model_dump (exclude_unset = True )
75- attachment .sqlmodel_update (update_dict )
76- session .add (attachment )
77- session .commit ()
78- session .refresh (attachment )
79- return attachment
86+ try :
87+ presigned_upload_url = aws_client .generate_presigned_url (
88+ "put_object" ,
89+ Params = {
90+ "Bucket" : Settings .AWS_S3_ATTACHMENTS_BUCKET ,
91+ "Key" : attachment .storage_path ,
92+ "ContentDisposition" : f"attachment; filename={ attachment .file_name } " ,
93+ },
94+ ExpiresIn = 3600 ,
95+ )
96+ except Exception as e :
97+ raise HTTPException (status_code = 500 , detail = "Could not generate presigned URL" )
8098
99+ resmodel = AttachmentCreatePublic .model_validate (attachment )
100+ resmodel .upload_url = presigned_upload_url
81101
82- @router .delete ("/{id}" )
83- def delete_attachment (
84- session : SessionDep , current_user : CurrentUser , id : uuid .UUID
85- ) -> Message :
86- """
87- Delete an attachment.
88- """
89- attachment = session .get (Attachment , id )
90- if not attachment :
91- raise HTTPException (status_code = 404 , detail = "Attachment not found" )
92- session .delete (attachment )
93- session .commit ()
94- return Message (message = "Attachment deleted successfully" )
102+ return resmodel
0 commit comments