2424from starlette .status import HTTP_201_CREATED
2525
2626from api .pagination import CustomPage
27- from core .dependencies import session_dependency
27+ from core .dependencies import session_dependency , viewer_function , admin_dependency , admin_function , editor_dependency
2828from db import Thing
2929from db .asset import Asset , AssetThingAssociation
3030from schemas .asset import AssetResponse , CreateAsset , UpdateAsset
31+ from services .audit_helper import audit_add
3132from services .crud_helper import model_patcher
33+ from services .gcs_helper import GCS_BUCKET_NAME , get_storage_bucket , gcs_upload , set_asset_url
3234
33- router = APIRouter (prefix = "/asset" , tags = ["asset" ])
34- GCS_BUCKET_NAME = os . environ . get ( "GCS_BUCKET_NAME" )
35+ router = APIRouter (prefix = "/asset" , tags = ["asset" ],
36+ dependencies = [ Depends ( viewer_function )] )
3537
3638
37- from google .cloud import storage
39+ # ======= Create =========
40+ @router .post ("/upload" , status_code = HTTP_201_CREATED ,
41+ dependencies = [Depends (admin_function )])
42+ async def upload_asset (
43+ bucket = Depends (get_storage_bucket ), file : UploadFile = File (...)
44+ ):
45+ signed_url , blob_name = gcs_upload (bucket , file )
46+ return {
47+ "url" : signed_url ,
48+ "storage_path" : blob_name ,
49+
50+ }
51+
52+
53+ @router .post ("" , status_code = HTTP_201_CREATED )
54+ async def add_asset (
55+ user : admin_dependency ,
56+ session : session_dependency , asset_data : CreateAsset
57+ ) -> AssetResponse :
58+
59+ data = asset_data .model_dump ()
60+ thing_id = data .pop ("thing_id" , None )
61+ url = data .pop ("url" , "" )
3862
63+ data ["storage_service" ] = "gcs"
64+ asset = Asset (** data )
65+ audit_add (user , asset )
3966
40- def get_storage_bucket () -> storage .Bucket :
41- client = storage .Client .from_service_account_json (
42- os .environ .get ("GOOGLE_APPLICATION_CREDENTIALS" )
43- )
44- bucket = client .bucket (GCS_BUCKET_NAME )
45- return bucket
67+ if thing_id :
68+ assoc = AssetThingAssociation ()
69+ audit_add (user , assoc )
70+ thing = session .get (Thing , thing_id )
71+ assoc .thing = thing
72+ assoc .asset = asset
73+ session .add (assoc )
74+
75+ session .add (asset )
76+ session .commit ()
77+ session .refresh (asset )
78+ asset .url = url
79+ return asset
4680
4781
82+ # ======= Read =========
4883@router .get ("" )
4984async def list_assets (
5085 session : session_dependency ,
51- # bucket=Depends(get_storage_bucket),
5286 thing_id : int = None ,
87+ bucket = Depends (get_storage_bucket ) # Assuming get_storage_bucket is defined elsewhere
5388) -> CustomPage [AssetResponse ]:
5489 """
5590 List all assets or assets associated with a specific thing.
@@ -60,16 +95,10 @@ async def list_assets(
6095 AssetThingAssociation .thing_id == thing_id
6196 )
6297
63- # assets = session.scalars(sql).all()
64- # if not assets:
65- # return []
6698
6799 def transformer (assets : List [Asset ]) -> AssetResponse :
68- # blob = bucket.blob(asset.storage_path)
69- # asset.url = blob.generate_signed_url(expiration=timedelta(minutes=10), method="GET")
70- # return [AssetResponse.model_validate(asset) for asset in assets]
71100 for a in assets :
72- a . url = f"https://storage.googleapis.com/ { GCS_BUCKET_NAME } / { a . storage_path } "
101+ set_asset_url ( a , bucket )
73102 return assets
74103
75104 return paginate (query = sql , conn = session , transformer = transformer )
@@ -79,9 +108,7 @@ def transformer(assets: List[Asset]) -> AssetResponse:
79108async def get_asset (
80109 asset_id : int ,
81110 session : session_dependency ,
82- bucket = Depends (
83- get_storage_bucket
84- ), # Assuming get_storage_bucket is defined elsewhere
111+ bucket = Depends (get_storage_bucket ), # Assuming get_storage_bucket is defined elsewhere
85112 thing_id : int = None ,
86113) -> AssetResponse :
87114 """
@@ -99,59 +126,21 @@ async def get_asset(
99126 if not asset :
100127 raise HTTPException (status_code = 404 , detail = "Asset not found" )
101128
102- blob = bucket .blob (asset .storage_path )
103- asset .url = blob .generate_signed_url (expiration = timedelta (minutes = 10 ), method = "GET" )
104- return asset
105-
106-
107- @router .post ("/upload" , status_code = HTTP_201_CREATED )
108- async def upload_asset (
109- bucket = Depends (get_storage_bucket ), file : UploadFile = File (...)
110- ):
111- file_id = str (uuid4 ())
112- blob_name = f"uploads/{ file_id } _{ file .filename } "
113- blob = bucket .blob (blob_name )
114- blob .upload_from_file (file .file , content_type = file .content_type )
115- return {
116- "url" : blob .generate_signed_url (expiration = timedelta (minutes = 10 ), method = "GET" ),
117- "storage_path" : blob_name ,
118- }
119-
120-
121- @router .post ("" , status_code = HTTP_201_CREATED )
122- async def add_asset (
123- session : session_dependency , asset_data : CreateAsset
124- ) -> AssetResponse :
125-
126- data = asset_data .model_dump ()
127- thing_id = data .pop ("thing_id" , None )
128- url = data .pop ("url" , "" )
129-
130- data ["storage_service" ] = "gcs"
131- asset = Asset (** data )
129+ set_asset_url (asset , bucket )
132130
133- if thing_id :
134- assoc = AssetThingAssociation ()
135- thing = session .get (Thing , thing_id )
136- assoc .thing = thing
137- assoc .asset = asset
138- session .add (assoc )
139131
140- session .add (asset )
141- session .commit ()
142- session .refresh (asset )
143- asset .url = url
144132 return asset
145133
146-
134+ # ======= Update =========
147135@router .patch ("/{asset_id}" )
148136async def update_asset (
149- asset_id : int , session : session_dependency , asset_data : UpdateAsset
137+ asset_id : int , session : session_dependency , asset_data : UpdateAsset ,
138+ user : editor_dependency
150139):
151140 """
152141 Update an existing asset.
153142 """
154- return model_patcher (session , Asset , asset_id , asset_data )
143+ return model_patcher (session , Asset , asset_id , asset_data , user = user )
155144
156145
157146# ============= EOF =============================================
0 commit comments