import datetime, json, os, pytz, random, secrets # , uvicorn from enum import Enum #from datetime import datetime, time, timedelta from fastapi import Body, Cookie, Depends, FastAPI, File, Form, Header, HTTPException, Path, Query, Request, Response, status, UploadFile from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse, HTMLResponse, JSONResponse, PlainTextResponse from fastapi.staticfiles import StaticFiles from functools import lru_cache from pydantic import BaseModel, EmailStr, Field from typing import Dict, List, Optional, Set, Union # from sqlalchemy import create_engine, text # from sqlalchemy.exc import IntegrityError, OperationalError # from . import config # from app.lib_general import common_route_params, Common_Route_Params from app.log import log, logging # Import the routers here first: # from app.routers import aether_cfg, api_crud, api, importing, sql, account, activity_log, address, archive, archive_content, contact, cont_edu_cert, cont_edu_cert_person, data_store, event, event_abstract, event_badge, event_badge_importing, event_badge_template, event_device, event_exhibit, event_exhibit_tracking, event_file, event_importing, event_location, event_person, event_person_detail, event_person_tracking, event_presentation, event_presenter, event_registration, event_session, flask_cfg, fundraising, hosted_file, journal, journal_entry, log_client_viewing, lookup, membership_cfg, membership_group, membership_person_group, membership_person, membership_person_profile, membership_type, membership_person_type, order, order_v3, order_line, order_cart, organization, page, person, person_user, post, post_comment, product, qr, site, site_domain, user, websockets_redis, e_confex, e_cvent, c_idaa, e_impexium, e_stripe from app.db_sql import sql_select # , sql_connect print('### **** *** ** * The Aether API v5 using FastAPI is loading... * ** *** **** ###') #log = logging.getLogger('root') # log.setLevel(logging.DEBUG) # DEBUG > INFO > WARNING > ERROR > CRITICAL #logging.basicConfig( #format='[%(asctime)s] %(levelname)s @ %(module)s.%(funcName)s()#%(lineno)d: %(message)s' #) app = FastAPI( # debug = True, title = 'Aether API', description = 'One Sky IT\'s Aether API v5 using FastAPI.', version = '4.9.0', operationsSorter = 'method', ) print('HERE') # log.setLevel(logging.INFO) # log.debug(config.settings) # log.debug('DEBUG TEST!') # if aether_cfg_sql_result := sql_select( # table_name = 'cfg', # record_id = config.settings.AETHER_CFG['id'], # as_list = False, # max_count = 1, # ): # aether_cfg_sql = aether_cfg_sql_result # config.settings.DB['server'] = aether_cfg_sql.get('db_server') # config.settings.DB['port'] = aether_cfg_sql.get('db_port') # config.settings.DB['name'] = aether_cfg_sql.get('db_name') # config.settings.DB['username'] = aether_cfg_sql.get('db_username') # config.settings.DB['password'] = aether_cfg_sql.get('db_password') # DB = config.settings.DB # config.settings.SQLALCHEMY_DB_URI = 'mysql://'+DB['username']+':'+DB['password']+'@'+DB['server']+'/'+DB['name'] # # db_result = sql_connect(config.settings.SQLALCHEMY_DB_URI) # log.debug(config.settings.DB) # config.settings.SMTP['server'] = aether_cfg_sql.get('smtp_server') # config.settings.SMTP['port'] = aether_cfg_sql.get('smtp_port') # config.settings.SMTP['username'] = aether_cfg_sql.get('smtp_username') # config.settings.SMTP['password'] = aether_cfg_sql.get('smtp_password') # # config.settings.FILES_PATH['hosted_files_root'] = aether_cfg_sql.get('PATH_HOSTED_FILES_ROOT') # # config.settings.FILES_PATH['hosted_tmp_root'] = aether_cfg_sql.get('PATH_HOSTED_TMP_ROOT') # config.settings.FILES_PATH['hosted_files_root'] = aether_cfg_sql.get('path_hosted_files_root') # config.settings.FILES_PATH['hosted_tmp_root'] = aether_cfg_sql.get('path_hosted_tmp_root') # else: # # aether_cfg_sql_result # pass # # log.debug(aether_cfg_sql_result) # # log.debug(config.settings) # # @lru_cache() # # def get_settings(): # # return config.Settings() # app.mount('/static', StaticFiles(directory='static'), name='static') # # Set up each route once the router has been imported # app.include_router( # aether_cfg.router, # tags=['Aether Config'], # ) # app.include_router( # api_crud.router, # prefix='/crud', # tags=['CRUD'], # #dependencies=[Depends(get_token_header)], # #dependencies=[Depends(get_account_header)], # #responses={404: {'description': 'Not found'}}, # ) # app.include_router( # api.router, # prefix='/api', # tags=['API'], # ) # app.include_router( # flask_cfg.router, # prefix='/flask_cfg', # tags=['Flask CFG'], # ) # app.include_router( # importing.router, # prefix='/importing', # tags=['Importing'], # ) # app.include_router( # sql.router, # # prefix='/sql', # tags=['SQL'], # ) # # app.include_router( # # flask_cfg.router, # # prefix='/redis', # # tags=['Redis'], # # ) # app.include_router( # account.router, # # prefix='/account', # tags=['Account'], # ) # app.include_router( # activity_log.router, # prefix='/activity_log', # tags=['Activity Log'], # ) # app.include_router( # address.router, # prefix='/address', # tags=['Address'], # ) # app.include_router( # archive.router, # # prefix='/archive', # tags=['Archive'], # ) # app.include_router( # archive_content.router, # prefix='/archive/content', # tags=['Archive Content'], # ) # app.include_router( # contact.router, # prefix='/contact', # tags=['Contact'], # ) # app.include_router( # cont_edu_cert.router, # tags=['Cont Edu Cert'], # ) # app.include_router( # cont_edu_cert_person.router, # tags=['Cont Edu Cert Person'], # ) # app.include_router( # data_store.router, # # prefix='/data_store', # tags=['Data Store'], # ) # app.include_router( # event.router, # # prefix='/event', # tags=['Event'], # ) # app.include_router( # event_abstract.router, # tags=['Event Abstract'], # ) # app.include_router( # event_badge.router, # tags=['Event Badge'], # ) # app.include_router( # event_badge_importing.router, # tags=['Event Badge Importing'], # ) # app.include_router( # event_badge_template.router, # # prefix='/event/badge/template', # tags=['Event Badge Template'], # ) # app.include_router( # event_device.router, # # prefix='/event/device', # tags=['Event Device'], # ) # app.include_router( # event_exhibit.router, # # prefix='/event/exhibit', # tags=['Event Exhibit'], # ) # app.include_router( # event_exhibit_tracking.router, # # prefix='/event/exhibit/tracking', # tags=['Event Exhibit Tracking'], # ) # app.include_router( # event_file.router, # # prefix='/event/file', # tags=['Event File'], # ) # app.include_router( # event_importing.router, # # prefix='/event/importing', # tags=['Event Importing'], # ) # app.include_router( # event_location.router, # # prefix='/event/location', # tags=['Event Location'], # ) # app.include_router( # event_person.router, # # prefix='/event/person', # tags=['Event Person'], # ) # app.include_router( # event_person.router, # prefix='/event/person/detail', # tags=['Event Person Detail'], # ) # app.include_router( # event_person_tracking.router, # tags=['Event Person Tracking'], # ) # app.include_router( # event_presentation.router, # # prefix='/event/presentation', # tags=['Event Presentation'], # ) # app.include_router( # event_presenter.router, # prefix='/event/presenter', # tags=['Event Presenter'], # ) # app.include_router( # event_registration.router, # prefix='/event/registration', # tags=['Event Registration'], # ) # app.include_router( # event_session.router, # # prefix='/event/session', # tags=['Event Session'], # ) # app.include_router( # fundraising.router, # tags=['Fundraising'], # ) # app.include_router( # hosted_file.router, # prefix='/hosted_file', # tags=['Hosted File'], # ) # app.include_router( # journal.router, # prefix='/journal', # tags=['Journal'], # ) # app.include_router( # journal_entry.router, # # prefix='/journal/entry', # tags=['Journal Entry'], # ) # app.include_router( # log_client_viewing.router, # # prefix='/log/client_viewing', # tags=['Log Client Viewing'], # ) # app.include_router( # lookup.router, # prefix='/lu', # tags=['Lookup'], # ) # app.include_router( # membership_cfg.router, # tags=['Membership Config'], # ) # app.include_router( # membership_group.router, # tags=['Membership Group'], # ) # app.include_router( # membership_person_group.router, # tags=['Membership Group Person'], # ) # app.include_router( # membership_person_profile.router, # tags=['Membership Person Profile'], # ) # app.include_router( # membership_person.router, # tags=['Membership Person'], # ) # app.include_router( # membership_type.router, # tags=['Membership Type'], # ) # app.include_router( # membership_person_type.router, # tags=['Membership Type Person'], # ) # app.include_router( # order.router, # # prefix='/order', # tags=['Order'], # ) # app.include_router( # order_v3.router, # # prefix='/order', # tags=['Order v3'], # ) # app.include_router( # order_line.router, # # prefix='/order', # tags=['Order Line'], # ) # app.include_router( # order_cart.router, # prefix='/order/cart', # tags=['Order Cart'], # ) # app.include_router( # organization.router, # prefix='/organization', # tags=['Organization'], # ) # app.include_router( # page.router, # prefix='/page', # tags=['Page'], # ) # app.include_router( # person.router, # tags=['Person'], # ) # app.include_router( # person_user.router, # prefix='/person_user', # tags=['Person User'], # ) # app.include_router( # post.router, # # prefix='/post', # tags=['Post'], # ) # app.include_router( # post_comment.router, # prefix='/post/comment', # tags=['Post Comment'], # ) # app.include_router( # product.router, # # prefix='/product', # tags=['Product'], # ) # app.include_router( # qr.router, # tags=['QR'], # ) # app.include_router( # site.router, # # prefix='/site', # tags=['Site'], # ) # app.include_router( # site_domain.router, # # prefix='/site/domain', # tags=['Site Domain'], # ) # app.include_router( # user.router, # tags=['User'], # ) # # app.include_router( # # websockets.router, # # # prefix='/websocket', # # tags=['Websockets'], # # # dependencies=[Depends(get_token_header)], # # # responses={404: {'description': 'Not found'}}, # # ) # app.include_router( # websockets_redis.router, # tags=['Websockets (Redis)'], # ) # app.include_router( # e_confex.router, # prefix='/e/confex', # tags=['External Service: Confex'], # ) # app.include_router( # e_cvent.router, # prefix='/e/cvent', # tags=['External Service: Cvent'], # ) # app.include_router( # e_impexium.router, # prefix='/e/impexium', # tags=['External Service: Impexium'], # ) # app.include_router( # e_stripe.router, # prefix='/e/stripe', # tags=['External Service: Stripe'], # ) # app.include_router( # c_idaa.router, # prefix='/c/idaa', # tags=['Client: IDAA'], # ) # # BEGIN: CORS # # NOTE: Eventually this should query the DB for the specific list based on the cfg table and or site_domain table. That way it is dynamic and only allowing those defined in the DB. No wildcards or regex. # # NOTE: Need to include .localhost for less browser restrictions! Mainly for audio and video. # app.add_middleware( # CORSMiddleware, # # allow_origins = origins, # allow_origins = config.settings.ORIGINS, # allow_origin_regex = config.settings.ORIGINS_REGEX, # # allow_origin_regex = 'https://.*\.oneskyit\.com', # allow_credentials = True, # allow_methods = ['*'], # allow_headers = ['*'], # #expose_headers = [], # #max_age = 600, # ) # # END: CORS # @app.on_event('startup') # async def startup(): # log.setLevel(logging.INFO) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL # log.debug(locals()) # log.info('The Aether FastAPI API is starting up...') # #await database.connect() # @app.on_event('shutdown') # async def shutdown(): # log.setLevel(logging.INFO) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL # log.debug(locals()) # log.info('The Aether FastAPI API is shutting down...') # #await database.disconnect() # #Add the processing time to the response header. # @app.middleware('http') # async def add_process_time_header(request: Request, call_next): # import time # start_time = time.time() # response = await call_next(request) # process_time = time.time() - start_time # response.headers['X-Process-Time'] = str(process_time) # return response # # ### BEGIN ### API Main ### fastapi_root() ### # @app.get('/', tags=['Root'], response_class=PlainTextResponse) # async def fastapi_root(response: Response = Response): # log.setLevel(logging.DEBUG) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL # log.debug(locals()) # # log.info(config.settings.APP_NAME) # log.info('One Sky IT\'s Aether API root (FastAPI)') # log.info('***') # log.debug('This is debug') # 10 DEBUG # log.info('This is info') # 20 INFO # 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 # log.info('^^^') # response_data = {} # response_data['message'] = 'This is One Sky IT\'s Aether API root (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 ### generate_id_random() ### # # NOTE: This is just a quick utility function to generate a bunch of random IDs. # # Updated 2022-03-30 # @app.get('/generate_id_random', tags=['Root'], response_class=PlainTextResponse) # async def generate_id_random(response: Response = Response): # log.setLevel(logging.INFO) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL # log.debug(locals()) # response_data = {} # html_list = '' # return HTMLResponse(content=html_list, status_code=200) # # ### END ### API Main ### generate_id_random() ### # # ### BEGIN ### API Main ### sql_test() ### # # ### TEST TEST TEST ### # # @app.get('/sql_test', tags=['Testing'], response_class=PlainTextResponse) # async def sql_test(response: Response = Response): # log.setLevel(logging.DEBUG) # DEBUG, INFO, WARN, WARNING, ERROR, EXCEPTION, CRITICAL # log.debug(locals()) # return mk_resp(data=False, status_code=501, response=response) # log.info('Getting all accounts from DB...') # sql = text( # """ # SELECT id, id_random, name, enable # FROM `account` # """ # ) # try: # result = db.execute(sql) # except Exception as e: # log.error('*** An exception happened. ***') # log.error(repr(e)) # log.error('***') # log.error(str(e)) # log.error('^^^ exception ^^^') # else: # if result.rowcount: # record_li = [dict(record) for record in result.fetchall()] # log.debug(record_li) # else: # log.error('No records found. Something went wrong.') # log.info('Got the account list') # response_data = {} # response_data['message'] = 'This is the Aether API using FastAPI.' # response_data['data'] = record_li # return json.dumps(response_data, indent=4) # , sort_keys=True # # ### END ### API Main ### sql_test() ###