import datetime, os, pathlib from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, Response, status from fastapi.responses import FileResponse from pydantic import BaseModel, EmailStr, Field from typing import Dict, List, Optional, Set, Union from app.lib_general import log, logging, common_route_params, Common_Route_Params from app.config import settings from app.db_sql import sql_insert, sql_update, sql_insert_or_update, sql_select, sql_delete, redis_lookup_id_random from app.routers.api_crud import delete_obj_template, get_obj_template, get_obj_li_template, patch_obj_template, post_obj_template from app.methods.event_file_methods import create_event_file_obj, load_event_file_obj # , update_event_file_obj from app.models.event_file_models import Event_File_Base from app.models.response_models import Resp_Body_Base, mk_resp router = APIRouter() @router.post('', response_model=Resp_Body_Base) async def post_event_file_obj( event_file_obj: Event_File_Base, x_account_id: str = Header(...), return_obj: Optional[bool] = True, by_alias: Optional[bool] = True, exclude_unset: Optional[bool] = True, response: Response = Response, ): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) obj_type = 'event_file' event_file_obj_data_dict = event_file_obj.dict(by_alias=False, exclude_unset=True) result = post_obj_template( obj_type = obj_type, data = event_file_obj_data_dict, return_obj = True, by_alias = True, exclude_unset = True, ) return result @router.patch('/{obj_id}', response_model=Resp_Body_Base) async def patch_event_file_obj( obj_id: str = Query(..., min_length=11, max_length=22), obj: Event_File_Base = None, x_account_id: Optional[str] = Header(..., ), return_obj: Optional[bool] = True, by_alias: Optional[bool] = True, exclude_unset: Optional[bool] = True, response: Response = Response, ): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) obj_type = 'event_file' obj_data_dict = obj.dict(by_alias=False, exclude_unset=True) obj_data_dict['id'] = redis_lookup_id_random(record_id_random=obj_id, table_name=obj_type) obj_data_dict['id_random'] = obj_id result = patch_obj_template( obj_type=obj_type, data=obj_data_dict, obj_id=obj_id, return_obj=True, by_alias=True, exclude_unset=True, ) return result # ### BEGIN ### API Event File ### get_event_file_lookup() ### # Updated 2021-10-06 @router.get('/lookup', response_model=Resp_Body_Base) async def event_file_lookup( hosted_file_id: str = Query(..., min_length=11, max_length=22), for_type: str = Query(..., min_length=5, max_length=15), for_id: str = Query(..., min_length=11, max_length=22), inc_hosted_file: bool = False, x_account_id: str = Header(...), by_alias: bool = True, exclude_unset: bool = True, response: Response = Response, ): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) if hosted_file_id := redis_lookup_id_random(record_id_random=hosted_file_id, table_name='hosted_file'): pass else: return mk_resp(data=False, status_code=404, status_message=f'Hosted File ID was not found. Hosted File ID: {hosted_file_id}', response=response) # Not Found if for_id := redis_lookup_id_random(record_id_random=for_id, table_name=for_type): pass else: return mk_resp(data=False, status_code=404, status_message=f'For ID was not found. For Type: {for_type}, For ID: {for_id}', response=response) # Not Found data = {} data['hosted_file_id'] = hosted_file_id data['for_type'] = for_type data['for_id'] = for_id log.debug(data) sql = f""" SELECT id AS 'event_file_id', id_random AS 'event_file_id_random' FROM `event_file` AS `event_file` WHERE `event_file`.hosted_file_id = :hosted_file_id AND `event_file`.for_type = :for_type AND `event_file`.for_id = :for_id """ log.debug(sql) if event_file_obj_result := sql_select(data=data, sql=sql): log.debug(event_file_obj_result) event_file_id = event_file_obj_result.get('event_file_id', None) if event_file_obj := load_event_file_obj( event_file_id = event_file_id, inc_hosted_file = inc_hosted_file, enabled = 'all', # NOTE: This should not be hardcoded model_as_dict = False, ): event_file_dict = event_file_obj.dict(by_alias = by_alias, exclude_unset=exclude_unset) else: return mk_resp(data=False, status_code=400, response=response) # Bad Request else: log.debug(event_file_obj_result) return mk_resp(data=None, status_code=404, status_message=f'An Event File was not found. Hosted File ID: {hosted_file_id}, For Type: {for_type}, For ID: {for_id}', response=response) # Not Found return mk_resp(data=event_file_dict, response=response) # ### END ### API Event File ### get_event_file_lookup() ### # ### BEGIN ### API Event File ### download_event_file() ### # Updated 2021-11-23 @router.get('/{event_file_id}/download', response_model=Resp_Body_Base) async def download_event_file( event_file_id: str = Query(..., min_length=11, max_length=22), filename: str = Query(None, min_length=4, max_length=100), commons: Common_Route_Params = Depends(common_route_params), ): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) # ### SECTION ### Secondary data validation if event_file_id := redis_lookup_id_random(record_id_random=event_file_id, table_name='event_file'): pass else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The event_file ID was invalid or not found.') hosted_files_path = settings.PATH_HOSTED_FILES_ROOT log.info(f'Hosted Files Path: {hosted_files_path}') if event_file_obj := load_event_file_obj( event_file_id = event_file_id, inc_hosted_file = True, ): pass else: return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request if not filename: filename = event_file_obj.filename log.info(f'Filename: {filename}') dir_path = event_file_obj.hosted_file.directory_path subdir_path = event_file_obj.hosted_file.subdirectory_path hash_sha256 = event_file_obj.hosted_file.hash_sha256 hash_filename = hash_sha256+'.file' full_subdirectory_path = os.path.join(hosted_files_path, subdir_path) log.debug(full_subdirectory_path) pathlib.Path(full_subdirectory_path).mkdir(parents=True, exist_ok=True) file_path_w_subdir = os.path.join(full_subdirectory_path, hash_filename) log.info(f'Full file path with subdirectory: {file_path_w_subdir}') return FileResponse(file_path_w_subdir, filename=filename) # ### END ### API Hosted File ### download_tmp() ### # ### BEGIN ### API Event File ### get_event_file_obj() ### # Updated 2021-10-21 @router.get('/{event_file_id}', response_model=Resp_Body_Base) async def get_event_file_obj( event_file_id: str = Query(..., min_length=11, max_length=22), inc_hosted_file: bool = False, enabled: str = 'enabled', # enabled, disabled, all; For now this covers any included objects or object lists hidden: str = 'not_hidden', # hidden, not_hidden, all x_account_id: str = Header(...), by_alias: bool = True, exclude_unset: bool = True, response: Response = Response, ): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) if event_file_id := redis_lookup_id_random(record_id_random=event_file_id, table_name='event_file'): pass else: return mk_resp(data=None, status_code=404, response=response) if event_file_obj := load_event_file_obj( event_file_id = event_file_id, enabled = enabled, # hidden = hidden, inc_hosted_file = inc_hosted_file, model_as_dict = False, ): event_file_dict = event_file_obj.dict(by_alias=by_alias, exclude_unset=exclude_unset) pass else: return mk_resp(data=False, status_code=400, response=response) # Bad Request return mk_resp(data=event_file_dict, response=response) #return mk_resp(data=event_file_obj) # ### END ### API Event File ### get_event_file_obj() ### # ### BEGIN ### API Event File ### delete_event_file_obj() ### # Updated 2021-11-02 @router.delete('/{event_file_id}', response_model=Resp_Body_Base) async def delete_event_file_obj( event_file_id: str = Query(..., min_length=11, max_length=22), hosted_file_id: str = Query(..., min_length=11, max_length=22), for_type: str = Query(..., min_length=1, max_length=25), for_id: str = Query(..., min_length=11, max_length=22), delete_hosted_file: bool = False, x_account_id: str = Header(...), response: Response = Response, ): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) if event_file_id := redis_lookup_id_random(record_id_random=event_file_id, table_name='event_file'): pass else: return mk_resp(data=None, status_code=404, response=response) if hosted_file_id := redis_lookup_id_random(record_id_random=hosted_file_id, table_name='hosted_file'): pass else: return mk_resp(data=None, status_code=404, response=response) if for_id := redis_lookup_id_random(record_id_random=for_id, table_name=for_type): pass else: return mk_resp(data=None, status_code=404, response=response) if event_file_delete_result := sql_delete(table_name='event_file', record_id=event_file_id): log.info(f'Deleted Event File ID: {event_file_id}') else: return mk_resp(data=False, status_code=500, response=response) # Internal Server Error sql = f""" DELETE FROM hosted_file_link WHERE hosted_file_id = :hosted_file_id AND link_to_type = :for_type AND link_to_id = :for_id """ hosted_file_link_data = {} hosted_file_link_data['hosted_file_id'] = hosted_file_id hosted_file_link_data['for_type'] = for_type hosted_file_link_data['for_id'] = for_id log.debug(hosted_file_link_data) if event_file_delete_result := sql_delete(sql=sql, data=hosted_file_link_data): log.info(f'Deleted Hosted File Link. Hosted File ID: {hosted_file_id}, Link To Type: {for_type}, Link To ID: {for_id}') else: return mk_resp(data=False, status_code=500, response=response) # Internal Server Error return mk_resp(data=True, response=response) # ### END ### API Event File ### delete_event_file_obj() ###