import datetime, pytz, time from fastapi import APIRouter, Body, Depends, Header, HTTPException, Path, Query, Response, status 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, get_id_random, 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.data_store_methods import create_update_data_store_obj, get_data_store_rec_list, load_data_store_obj, load_data_store_obj_w_code from app.models.common_field_schema import default_num_bytes from app.models.data_store_models import Data_Store_Base from app.models.response_models import Resp_Body_Base, mk_resp router = APIRouter() # ### BEGIN ### API Data Store Routers ### post_data_store_obj() ### # Updated 2022-03-11 @router.post('/data_store', response_model=Resp_Body_Base) async def post_data_store_obj( data_store_obj: Data_Store_Base, return_obj: bool = True, commons: Common_Route_Params = Depends(common_route_params), ): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) # ### SECTION ### Secondary data validation # None # ### SECTION ### Process data if data_store_id := create_update_data_store_obj( data_store_dict_obj = data_store_obj, ): pass else: log.warning('Likely bad request') return mk_resp(data=False, status_code=400, response=commons.response, status_message='Not created. Something failed while processing the data. Check the field names and data types.') # Bad Request # ### SECTION ### Return successful results if return_obj: data_store_obj = load_data_store_obj( data_store_id = data_store_id, inc_event_cfg = inc_event_cfg, inc_event_location = inc_event_location, ) data = data_store_obj else: data_store_id_random = get_id_random(record_id=data_store_id, table_name='data_store') data = {} data['data_store_id'] = data_store_id data['data_store_id_random'] = data_store_id_random return mk_resp(data=data, response=commons.response) # ### END ### API Data Store Routers ### post_data_store_obj() ### # ### BEGIN ### API Data Store Routers ### patch_data_store_obj() ### # Updated 2022-03-11 @router.patch('/data_store/{data_store_id}', response_model=Resp_Body_Base) async def patch_data_store_obj( data_store_obj: Data_Store_Base, data_store_id: str = Path(min_length=11, max_length=22), return_obj: Optional[bool] = True, commons: Common_Route_Params = Depends(common_route_params), ): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) # ### SECTION ### Secondary data validation data_store_id_random = data_store_id # This is used later for the response data if data_store_id := redis_lookup_id_random(record_id_random=data_store_id, table_name='data_store'): pass else: return mk_resp(data=None, status_code=404, response=commons.response, status_message='The Data Store ID was invalid or not found.') # ### SECTION ### Process data if data_store_up_result := create_update_data_store_obj( data_store_dict_obj = data_store_obj, data_store_id = data_store_id, ): pass else: log.warning('Likely bad request') return mk_resp(data=False, status_code=400, response=commons.response, status_message='Not updated. Something failed while processing the data. Check the field names and data types.') # Bad Request # ### SECTION ### Return successful results if return_obj: data_store_obj = load_data_store_obj( data_store_id = data_store_id, ) data = data_store_obj else: data = {} data['data_store_id'] = data_store_id data['data_store_id_random'] = data_store_id_random return mk_resp(data=data, response=commons.response) # ### END ### API Data Store Routers ### patch_data_store_obj() ### # ### BEGIN ### API Data Store ### get_data_store_obj() ### # Updated 2022-03-11 @router.get('/data_store/{data_store_id}', response_model=Resp_Body_Base) async def get_data_store_obj( data_store_id: str = Path(min_length=11, max_length=22), commons: Common_Route_Params = Depends(common_route_params), ): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) # ### SECTION ### Secondary data validation if data_store_id := redis_lookup_id_random(record_id_random=data_store_id, table_name='data_store'): pass else: return mk_resp(data=None, status_code=404, response=commons.response) if data_store_rec_result := load_data_store_obj( data_store_id = data_store_id, limit = commons.limit, enabled = commons.enabled, inc_event_cfg = inc_event_cfg, inc_event_location = inc_event_location, ): log.info('Loading successful. Returning result') return mk_resp(data=data_store_rec_result, response=commons.response) elif isinstance(data_store_rec_result, list) or data_store_rec_result is None: # Empty list or None log.info('No results') return mk_resp(data=None, status_code=404, response=commons.response) # Not Found else: log.warning('Likely bad request') return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request # ### END ### API Data Store ### get_data_store_obj() ### # ### BEGIN ### API Data Store ### get_data_store_obj_w_code() ### # NOTE: Adding some explanation because this is not quickly obvious how it fully works. # The look up order starts with a required data_store_code. Then the first result that matches the most specific method. The for_type and for_id fields are not required. I think it makes the most sense to be a part of the URL path, not the GET params. Either should work with no problem though. # Lookup using: for_type and for_id > account_id > data_store_code # This is a nice way to have global default data along with account and object specific data. # Updated 2023-05-22 @router.get('/data_store/code/{data_store_code}/{for_type}/{for_id}', response_model=Resp_Body_Base) async def get_data_store_obj_w_code_path( data_store_code: str = Path(min_length=3, max_length=50), for_type: Optional[str] = Path(min_length=1, max_length=25), for_id: Optional[str] = Path(min_length=11, max_length=22), commons: Common_Route_Params = Depends(common_route_params), ): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) log.debug('Using path parameters') # ### SECTION ### Call generic function to get the data_store object return handle_get_data_store_obj_w_code( data_store_code = data_store_code, for_type = for_type, for_id = for_id, commons = commons, ) @router.get('/data_store/code/{data_store_code}', response_model=Resp_Body_Base) async def get_data_store_obj_w_code_query( data_store_code: str = Path(min_length=3, max_length=50), for_type: Optional[str] = Query(None, min_length=1, max_length=25), for_id: Optional[str] = Query(None, min_length=11, max_length=22), commons: Common_Route_Params = Depends(common_route_params), ): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) log.debug('Using query parameters') # ### SECTION ### Call generic function to get the data_store object return handle_get_data_store_obj_w_code( data_store_code = data_store_code, for_type = for_type, for_id = for_id, commons = commons, ) def handle_get_data_store_obj_w_code( data_store_code: str, for_type: Optional[str], for_id: Optional[str], commons: Common_Route_Params, ): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) log.debug(commons.x_account_id_random) log.debug(commons.x_account_id) # NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING # time.sleep(2.5) # NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING # NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING NOTE: WARNING # ### SECTION ### Secondary data validation if for_type and for_id: 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=commons.response, status_message='The for type and ID was invalid or not found.') # NOTE: Currently this returns a list: load_data_store_obj_w_code() # NOTE: Only the first sorted record is needed if data_store_obj_result := load_data_store_obj_w_code( account_id = commons.x_account_id, code = data_store_code, for_type = for_type, for_id = for_id, limit = 1, # commons.limit, enabled = commons.enabled, ): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.info('Loading successful. Returning result') data_store_obj = data_store_obj_result[0] # Get first record only log.debug(data_store_obj) return mk_resp(data=data_store_obj, response=commons.response) elif isinstance(data_store_obj_result, list) or data_store_obj_result is None: # Empty list or None log.info('No results') return mk_resp(data=None, status_code=404, response=commons.response) # Not Found else: log.warning('Likely bad request') return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request # ### END ### API Data Store ### get_data_store_obj_w_code() ### # ### BEGIN ### API Data Store ### get_account_obj_data_store_list() ### # Updated 2022-03-11 @router.get('/account/{account_id}/data_store/list', response_model=Resp_Body_Base) async def get_account_obj_data_store_list( account_id: str = Path(min_length=11, max_length=22), commons: Common_Route_Params = Depends(common_route_params), ): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) if account_id := redis_lookup_id_random(record_id_random=account_id, table_name='account'): pass else: return mk_resp(data=None, status_code=404, response=commons.response) # Updated 2022-03-11 if data_store_rec_list_result := get_data_store_rec_list( account_id = account_id, for_type = 'account', for_id = account_id, enabled = commons.enabled, limit = commons.limit, offset = commons.offset, ): data_store_result_list = [] for data_store_rec in data_store_rec_list_result: if load_data_store_result := load_data_store_obj( data_store_id = data_store_rec.get('data_store_id', None), enabled = commons.enabled, ): data_store_result_list.append(load_data_store_result) else: data_store_result_list.append(None) response_data = data_store_result_list return mk_resp(data=response_data, response=commons.response) elif isinstance(data_store_rec_list_result, list) or data_store_rec_list_result is None: # Empty list or None log.info('No results') return mk_resp(data=None, status_code=404, response=commons.response) # Not Found else: log.warning('Likely bad request') return mk_resp(data=False, status_code=400, response=commons.response) # Bad Request # ### END ### API Data Store ### get_account_obj_data_store_list() ###