603 lines
18 KiB
Python
603 lines
18 KiB
Python
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 = '<ul>'
|
|
# for x in range(50):
|
|
# html_list += f'<li>{secrets.token_urlsafe(8)}</li>'
|
|
# html_list += '</ul>'
|
|
|
|
# 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() ###
|