208 lines
4.8 KiB
Python
Executable File
208 lines
4.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# builtins
|
|
import click
|
|
import uvicorn
|
|
import os
|
|
import sys
|
|
import importlib
|
|
|
|
# database
|
|
import psycopg2
|
|
|
|
# hop-generated classes
|
|
from .models.api.version import Version
|
|
from .models.api.domain import Domain
|
|
from .models.api.route import Route
|
|
from .models.api.acl_function import AclFunction
|
|
from .models.api.acl import Acl
|
|
|
|
|
|
HALFORM_DSN=''
|
|
HALFORM_SECRET=''
|
|
CONTEXT_SETTINGS={
|
|
'default_map':{'run': {'port': 8000}}
|
|
}
|
|
|
|
@click.group(invoke_without_command=True, context_settings=CONTEXT_SETTINGS)
|
|
@click.pass_context
|
|
def cli(ctx):
|
|
if ctx.invoked_subcommand is None:
|
|
return run()
|
|
|
|
@click.option('--envfile', default=None)
|
|
@click.option('--host', default='127.0.0.1')
|
|
@click.option('--port', default='8000')
|
|
@cli.command()
|
|
def run(envfile, host, port):
|
|
local_env = {}
|
|
if envfile:
|
|
try:
|
|
with open(envfile) as f:
|
|
print('Will use the following env parameters :')
|
|
local_env = dict([ tuple(line.strip().split('=', 1))
|
|
for line in f.readlines() ])
|
|
print(local_env)
|
|
except FileNotFoundError:
|
|
print(f'No file named {envfile}')
|
|
envfile = None
|
|
|
|
if 'DEV' in local_env.keys():
|
|
debug = True
|
|
reload = True
|
|
log_level = 'debug'
|
|
else:
|
|
reload = False
|
|
log_level = 'info'
|
|
|
|
click.echo('Launching application')
|
|
|
|
sys.path.insert(0, os.getcwd())
|
|
click.echo(f'current python_path : {sys.path}')
|
|
|
|
uvicorn.run('halfapi.app:app',
|
|
env_file=envfile,
|
|
host=host,
|
|
port=int(port),
|
|
log_level=log_level,
|
|
reload=reload)
|
|
|
|
@click.option('--dbname', default='api')
|
|
@click.option('--host', default='127.0.0.1')
|
|
@click.option('--port', default=5432)
|
|
@click.option('--user', default='api')
|
|
@click.option('--password', default='')
|
|
@click.option('--domain', default='organigramme')
|
|
@click.option('--drop', is_flag=True, default=False)
|
|
@cli.command()
|
|
def dbupdate(dbname, host, port, user, password, domain, drop):
|
|
|
|
def dropdb():
|
|
if not click.confirm(f'will now drop database {dbname}', default=True):
|
|
return False
|
|
|
|
conn = psycopg2.connect({
|
|
'dbname': dbname,
|
|
'host': host,
|
|
'port': port,
|
|
'user': user,
|
|
'password': password
|
|
})
|
|
|
|
cur = conn.cursor()
|
|
|
|
cur.execute(f'drop database {dbname};')
|
|
conn.commit()
|
|
cur.close()
|
|
conn.close()
|
|
|
|
return True
|
|
|
|
def delete_domain():
|
|
d = Domain(name=domain)
|
|
if len(d) < 1:
|
|
return False
|
|
|
|
acl = Acl(domain=domain)
|
|
acl.delete()
|
|
|
|
fct = AclFunction(domain=domain)
|
|
fct.delete()
|
|
|
|
route = Route(domain=domain)
|
|
route.delete()
|
|
|
|
d.delete()
|
|
|
|
return True
|
|
|
|
def add_acl_fct(fct):
|
|
acl = AclFunction()
|
|
acl.version = version
|
|
acl.domain = domain
|
|
acl.name = fct.__name__
|
|
if len(acl) == 0:
|
|
acl.insert()
|
|
|
|
def add_acl(name, **kwargs):
|
|
acl = Acl()
|
|
acl.version = version
|
|
acl.domain = domain
|
|
acl.name = name
|
|
acl.path = kwargs['path']
|
|
acl.http_verb = kwargs['verb']
|
|
for fct in kwargs['acl']:
|
|
acl.function = fct.__name__
|
|
|
|
if len(acl) == 0:
|
|
if fct is not None:
|
|
add_acl_fct(fct)
|
|
|
|
acl.insert()
|
|
|
|
elif fct is None:
|
|
acl.delete()
|
|
|
|
|
|
def add_route(name, **kwargs):
|
|
print(f'Adding route {version}/{domain}/{name}')
|
|
route = Route()
|
|
route.version = version
|
|
route.domain = domain
|
|
route.path = kwargs['path']
|
|
if len(route) == 0:
|
|
route.insert()
|
|
|
|
def add_routes_and_acl(routes):
|
|
for name, route_params in routes.items():
|
|
add_route(name, **route_params)
|
|
add_acl(name, **route_params)
|
|
|
|
|
|
def add_domain():
|
|
new_domain = Domain(name=domain)
|
|
new_domain.version = version
|
|
if len(new_domain) == 0:
|
|
print(f'New domain {domain}')
|
|
new_domain.insert()
|
|
|
|
|
|
if drop:
|
|
dropdb()
|
|
|
|
delete_domain()
|
|
|
|
acl_set = set()
|
|
|
|
try:
|
|
|
|
# module retrieval
|
|
dom_mod = importlib.import_module(domain)
|
|
|
|
version = dom_mod.API_VERSION
|
|
add_domain()
|
|
|
|
# add main routes
|
|
ROUTES = dom_mod.ROUTES
|
|
add_routes_and_acl(dom_mod.ROUTES)
|
|
|
|
# add sub routers
|
|
ROUTERS = dom_mod.ROUTERS
|
|
|
|
for router_name in dom_mod.ROUTERS:
|
|
router_mod = importlib.import_module(f'.routers.{router_name}', domain)
|
|
add_routes_and_acl(router_mod.ROUTES)
|
|
|
|
except ImportError:
|
|
click.echo(f'The domain {domain} has no *ROUTES* variable', err=True)
|
|
except Exception as e:
|
|
click.echo(e, err=True)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
cli()
|
|
|