diff --git a/admin/requirements.txt b/admin/requirements.txt index a0e595b..47038e9 100644 --- a/admin/requirements.txt +++ b/admin/requirements.txt @@ -1,6 +1,7 @@ gunicorn uvicorn fastapi[all] +pydantic SQLAlchemy mysqlclient redis diff --git a/app/main.py b/app/main.py index 0f2e268..7152169 100644 --- a/app/main.py +++ b/app/main.py @@ -1,4 +1,4 @@ -import logging, os, random # , uvicorn +import datetime, json, logging, os, pytz, random, secrets # , uvicorn from enum import Enum #from datetime import datetime, time, timedelta @@ -14,7 +14,7 @@ from sqlalchemy import create_engine, text from sqlalchemy.exc import IntegrityError, OperationalError from . import config -from app.lib_general import * +from app.lib_general import log, logging from app.log import log # Import the routers here first: @@ -57,162 +57,102 @@ app.include_router( api.router, prefix='/api', tags=['API'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( flask_cfg.router, prefix='/flask_cfg', tags=['Flask CFG'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) # app.include_router( # flask_cfg.router, # prefix='/redis', # tags=['Redis'], -# #dependencies=[Depends(get_token_header)], -# #dependencies=[Depends(get_account_header)], -# #responses={404: {'description': 'Not found'}}, # ) app.include_router( account.router, prefix='/account', tags=['Account'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( address.router, prefix='/address', tags=['Address'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( archive.router, prefix='/archive', tags=['Archive'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( archive_content.router, prefix='/archive/content', tags=['Archive Content'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( contact.router, prefix='/contact', tags=['Contact'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event.router, prefix='/event', tags=['Event'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_exhibit.router, prefix='/event/exhibit', tags=['Event Exhibit'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_file.router, prefix='/event/file', tags=['Event File'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_person.router, prefix='/event/person', tags=['Event Person'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_person.router, prefix='/event/person/detail', tags=['Event Person Detail'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_presentation.router, prefix='/event/presentation', tags=['Event Presenter'], - #dependencies=[DependPresenter(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_presenter.router, prefix='/event/presenter', tags=['Event Presenter'], - #dependencies=[DependPresenter(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_registration.router, prefix='/event/registration', tags=['Event Registration'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( event_session.router, prefix='/event/session', tags=['Event Session'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( hosted_file.router, prefix='/hosted_file', tags=['Hosted File'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( journal.router, prefix='/journal', tags=['Journal'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( journal_entry.router, prefix='/journal/entry', tags=['Journal Entry'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( lookup.router, @@ -238,89 +178,56 @@ app.include_router( order.router, prefix='/order', tags=['Order'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( order_cart.router, prefix='/order/cart', tags=['Order Cart'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( organization.router, prefix='/organization', tags=['Organization'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( page.router, prefix='/page', tags=['Page'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( person.router, prefix='/person', tags=['Person'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( post.router, prefix='/post', tags=['Post'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( post_comment.router, prefix='/post/comment', tags=['Post Comment'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( product.router, prefix='/product', tags=['Product'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( site.router, prefix='/site', tags=['Site'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( site_domain.router, prefix='/site/domain', tags=['Site Domain'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( user.router, prefix='/user', tags=['User'], - #dependencies=[Depends(get_token_header)], - #dependencies=[Depends(get_account_header)], - #responses={404: {'description': 'Not found'}}, ) app.include_router( user_person.router, @@ -396,38 +303,74 @@ async def add_process_time_header(request: Request, call_next): return response -@app.get('/', tags=['Default']) -async def get_root(): - log.setLevel(logging.INFO) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL +# ### BEGIN ### API Main ### fastapi_root() ### +@app.get('/', tags=['Root'], response_class=PlainTextResponse) +async def fastapi_root(): + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) log.info(config.settings.APP_NAME) - log.setLevel(logging.DEBUG) - - print('***') + log.info('***') log.debug('This is debug') # 10 DEBUG log.info('This is info') # 20 INFO - log.warn('This is warn') # 30 WARNING - log.warning('This is a warning') # 30 WARNING + log.warning('This is a warning') # 30 WARNING (and WARN) log.error('This is an error') # 40 ERROR log.exception('This is an exception') # 40 ERROR log.critical('This is critical') # 50 CRITICAL - #print('----') - #logging.debug('This is debug') # 10 DEBUG - #logging.info('This is info') # 20 INFO - #logging.warn('This is warn') # 30 WARNING - #logging.warning('This is a warning') # 30 WARNING - #logging.error('This is an error') # 40 ERROR - #logging.exception('This is an exception') # 40 ERROR - #logging.critical('This is critical') # 50 CRITICAL - print('^^^') + log.info('^^^') - return {'hello': 'This is the Aether API using FastAPI.'} + response_data = {} + response_data['message'] = 'This is the Aether API using FastAPI.' + current_datetime = datetime.datetime.now() + current_datetime_string = current_datetime.isoformat() + + timezone = pytz.timezone("America/New_York") + current_datetime_tz = timezone.localize(current_datetime) + current_datetime_tz_string = current_datetime_tz.isoformat() + + current_datetime_utc = datetime.datetime.utcnow() + current_datetime_utc_string = current_datetime_utc.isoformat() + + current_datetime_utc_localize = pytz.utc.localize(current_datetime_utc) + current_datetime_utc_localize_string = current_datetime_utc_localize.isoformat() + + current_datetime_utc_localize_pst = current_datetime_utc_localize.astimezone(pytz.timezone("America/Los_Angeles")) + current_datetime_utc_localize_pst_string = current_datetime_utc_localize_pst.isoformat() + + response_data['datetime'] = current_datetime_string + response_data['datetime_tz'] = current_datetime_tz_string + response_data['datetime_utc'] = current_datetime_utc_string + response_data['datetime_utc_localize'] = current_datetime_utc_localize_string + response_data['datetime_utc_localize_pst'] = current_datetime_utc_localize_pst_string + + response_data['url_safe_string_4_bytes_1'] = secrets.token_urlsafe(4) + response_data['url_safe_string_8_bytes_1'] = secrets.token_urlsafe(8) + response_data['url_safe_string_8_bytes_2'] = secrets.token_urlsafe(8) + response_data['url_safe_string_8_bytes_3'] = secrets.token_urlsafe(8) + response_data['url_safe_string_8_bytes_4'] = secrets.token_urlsafe(8) + response_data['url_safe_string_8_bytes_5'] = secrets.token_urlsafe(8) + response_data['url_safe_string_16_bytes_1'] = secrets.token_urlsafe(16) + response_data['url_safe_string_16_bytes_2'] = secrets.token_urlsafe(16) + response_data['url_safe_string_16_bytes_3'] = secrets.token_urlsafe(16) + response_data['url_safe_string_16_bytes_4'] = secrets.token_urlsafe(16) + response_data['url_safe_string_16_bytes_5'] = secrets.token_urlsafe(16) + + response_data['hex_string_4_bytes_1'] = secrets.token_hex(4) + response_data['hex_string_8_bytes_1'] = secrets.token_hex(8) + response_data['hex_string_16_bytes_1'] = secrets.token_hex(16) + response_data['hex_string_32_bytes_1'] = secrets.token_hex(32) + + log.debug(json.dumps(response_data, indent=4)) + return json.dumps(response_data, indent=4) # , sort_keys=True +# ### END ### API Main ### fastapi_root() ### + + +# ### BEGIN ### API Main ### quick_test() ### # ### TEST TEST TEST ### # -@app.get('/quick_test', tags=['Default']) +@app.get('/quick_test', tags=['Testing'], response_class=PlainTextResponse) async def quick_test(): log.setLevel(logging.DEBUG) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) @@ -435,11 +378,11 @@ async def quick_test(): log.info('Getting all accounts...') sql = text( - """ - SELECT * - FROM `account` - """ - ) + """ + SELECT id, id_random, name, enable + FROM `account` + """ + ) try: result = db.execute(sql) except Exception as e: @@ -450,16 +393,16 @@ async def quick_test(): log.error('^^^ exception ^^^') else: if result.rowcount: - records = result.fetchall() - log.debug(records) + record_li = [dict(record) for record in result.fetchall()] + log.debug(record_li) else: - log.warning('Something went wrong.') + log.error('No records found. Something went wrong.') log.info('Got the account list') - response = {} - response['hello'] = 'This is the Aether API using FastAPI.' - response['data'] = records + response_data = {} + response_data['message'] = 'This is the Aether API using FastAPI.' + response_data['data'] = record_li - return response -# ### TEST TEST TEST ### # + return json.dumps(response_data, indent=4) # , sort_keys=True +# ### END ### API Main ### quick_test() ### diff --git a/app/methods/membership_group_member_methods.py b/app/methods/membership_group_member_methods.py index 8d5f36c..480d804 100644 --- a/app/methods/membership_group_member_methods.py +++ b/app/methods/membership_group_member_methods.py @@ -121,8 +121,9 @@ def get_membership_group_member_rec_list( ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC {sql_limit}; """ - log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + # log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(sql) + if membership_group_member_rec_li_result := sql_select(data=data, sql=sql, as_list=True): membership_group_member_rec_li = membership_group_member_rec_li_result else: diff --git a/app/methods/membership_member_methods.py b/app/methods/membership_member_methods.py index 35e8b9d..5774a96 100644 --- a/app/methods/membership_member_methods.py +++ b/app/methods/membership_member_methods.py @@ -33,6 +33,7 @@ def load_membership_member_obj( # inc_membership_member_profile_cust: bool = False, inc_organization: bool = False, inc_person: bool = False, + inc_product: bool = False, # The product the person actually purchased for a member_type or member_group inc_user: bool = False, ) -> Membership_Member_Base: log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL @@ -183,34 +184,98 @@ def get_membership_member_rec_list( else: return False data = {} data[f'{for_obj_type}_id'] = for_obj_id - # data['for_obj_type'] = for_obj_type - sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' - if enabled in ['enabled', 'disabled', 'all']: - if enabled == 'enabled': - data['enable'] = True - sql_enabled = f'AND `tbl`.enable = :enable' - elif enabled == 'disabled': - data['enable'] = False - sql_enabled = f'AND `tbl`.enable = :enable' - elif enabled == 'all': - sql_enabled = '' + allowed_forign_key_li = ['account', 'membership_type', 'person', 'user'] + if for_obj_type in allowed_forign_key_li: + log.info(f'Query using forign key: {for_obj_type} {for_obj_id}') + sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' - if limit: - data['limit'] = limit - sql_limit = f'LIMIT :limit' - else: - sql_limit = '' + if enabled in ['enabled', 'disabled', 'all']: + if enabled == 'enabled': + data['enable'] = True + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'disabled': + data['enable'] = False + sql_enabled = f'AND `tbl`.enable = :enable' + elif enabled == 'all': + sql_enabled = '' - sql = f""" - SELECT `tbl`.id AS 'membership_member_id', `tbl`.id_random AS 'membership_member_id_random' - FROM `membership_member` AS `tbl` - WHERE - {sql_obj_type_id} - {sql_enabled} - ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC - {sql_limit}; - """ + if limit: + data['limit'] = limit + sql_limit = f'LIMIT :limit' + else: + sql_limit = '' + + sql = f""" + SELECT `tbl`.id AS 'membership_member_id', `tbl`.id_random AS 'membership_member_id_random' + FROM `membership_member` AS `tbl` + WHERE + {sql_obj_type_id} + {sql_enabled} + ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + {sql_limit}; + """ + elif for_obj_type == 'unknown': + log.info(f'Query using joined table: {for_obj_type} {for_obj_id}') + # sql_obj_type_id = f'`membership_member`.{for_obj_type}_id = :{for_obj_type}_id' + + # if enabled in ['enabled', 'disabled', 'all']: + # if enabled == 'enabled': + # data['enable'] = True + # sql_enabled = f'AND `membership_member`.enable = :enable' + # elif enabled == 'disabled': + # data['enable'] = False + # sql_enabled = f'AND `membership_member`.enable = :enable' + # elif enabled == 'all': + # sql_enabled = '' + + # if limit: + # data['limit'] = limit + # sql_limit = f'LIMIT :limit' + # else: + # sql_limit = '' + + # sql = f""" + # SELECT `membership_member`.id AS 'membership_type_id', `membership_member`.id_random AS 'membership_type_id_random' + # FROM `membership_member` + # INNER JOIN membership_type ON membership_member.membership_type_id = membership_type.id + # WHERE + # {sql_obj_type_id} + # {sql_enabled} + + # ORDER BY `membership_member`.created_on DESC, `membership_member`.updated_on DESC + # {sql_limit}; + # """ + log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + log.debug(sql) + + # sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' + + # if enabled in ['enabled', 'disabled', 'all']: + # if enabled == 'enabled': + # data['enable'] = True + # sql_enabled = f'AND `tbl`.enable = :enable' + # elif enabled == 'disabled': + # data['enable'] = False + # sql_enabled = f'AND `tbl`.enable = :enable' + # elif enabled == 'all': + # sql_enabled = '' + + # if limit: + # data['limit'] = limit + # sql_limit = f'LIMIT :limit' + # else: + # sql_limit = '' + + # sql = f""" + # SELECT `tbl`.id AS 'membership_member_id', `tbl`.id_random AS 'membership_member_id_random' + # FROM `membership_member` AS `tbl` + # WHERE + # {sql_obj_type_id} + # {sql_enabled} + # ORDER BY `tbl`.created_on DESC, `tbl`.updated_on DESC + # {sql_limit}; + # """ if membership_member_rec_li_result := sql_select(data=data, sql=sql, as_list=True): membership_member_rec_li = membership_member_rec_li_result diff --git a/app/methods/membership_type_methods.py b/app/methods/membership_type_methods.py index bc028fe..24061eb 100644 --- a/app/methods/membership_type_methods.py +++ b/app/methods/membership_type_methods.py @@ -144,9 +144,10 @@ def get_membership_type_rec_list( else: return False data = {} data[f'{for_obj_type}_id'] = for_obj_id - # data['for_obj_type'] = for_obj_type + + allowed_forign_key_li = ['account'] # 'lu_membership_type_id'? 'level'? if for_obj_type == 'account': - print('********************************* account **************************') + log.info(f'Query using forign key: {for_obj_type} {for_obj_id}') sql_obj_type_id = f'`tbl`.{for_obj_type}_id = :{for_obj_type}_id' if enabled in ['enabled', 'disabled', 'all']: @@ -175,7 +176,7 @@ def get_membership_type_rec_list( {sql_limit}; """ elif for_obj_type == 'membership_member': - print('********************************* membership_member **************************') + log.info(f'Query using joined table: {for_obj_type} {for_obj_id}') sql_obj_type_id = f'`membership_member`.{for_obj_type}_id = :{for_obj_type}_id' if enabled in ['enabled', 'disabled', 'all']: @@ -207,6 +208,7 @@ def get_membership_type_rec_list( """ log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(sql) + if membership_type_rec_li_result := sql_select(data=data, sql=sql, as_list=True): membership_type_rec_li = membership_type_rec_li_result else: diff --git a/app/models/response_models.py b/app/models/response_models.py index 1f7232f..d58b18f 100644 --- a/app/models/response_models.py +++ b/app/models/response_models.py @@ -5,7 +5,7 @@ from typing import Dict, List, Optional, Set, Union from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator from app.db_sql import redis_lookup_id_random -from app.lib_general import log, logging +from app.lib_general import log, logging, status from app.config import settings @@ -90,11 +90,11 @@ def mk_resp( elif status_code == 503: response.status_code = status.HTTP_503_SERVICE_UNAVAILABLE elif status_code == 504: response.status_code = status.HTTP_504_GATEWAY_TIMEOUT - log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL + # log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(type(resp_body['data'])) resp_body_obj = Resp_Body_Base(**resp_body) - resp_body_obj.test_prop = 'my value' + # resp_body_obj.test_prop = 'my value' log.debug(resp_body_obj) resp_body_dict = resp_body_obj.dict(by_alias=by_alias, exclude_unset=exclude_unset) log.debug(resp_body_dict) diff --git a/app/routers/account.py b/app/routers/account.py index 7ed7584..9aeee35 100644 --- a/app/routers/account.py +++ b/app/routers/account.py @@ -276,7 +276,7 @@ async def get_account_obj_new( # ### BEGIN ### API Account ### get_account_obj_membership_member_list() ### -# Working well as of 2021-06-23. Using as a template for other routes. +# Working well as of 2021-06-24. Using as a template for other routes. @router.get('/{account_id}/membership_member_list', response_model=Resp_Body_Base) async def get_account_obj_membership_member_list( account_id: str = Query(..., min_length=1, max_length=22), @@ -342,7 +342,7 @@ async def get_account_obj_membership_member_list( inc_organization = inc_organization, inc_person = inc_person, inc_product = inc_product, - inc_product_list = inc_product_list, + # inc_product_list = inc_product_list, inc_user = inc_user, ): membership_member_result_list.append(load_membership_member_result)