[wip][routing] updated lib.domain function names

This commit is contained in:
Maxime Alves LIRMM 2020-09-22 14:26:46 +02:00
parent 38798549f6
commit 5f7d66d4d6
4 changed files with 43 additions and 84 deletions

View File

@ -16,11 +16,10 @@ from halfapi.conf import HOST, PORT, DB_NAME, SECRET, PRODUCTION, DOMAINS
from halfapi.lib.jwt_middleware import JWTAuthenticationBackend
from halfapi.lib.responses import *
from halfapi.lib.routes import get_starlette_routes
from halfapi.lib.domain import domain_scanner
from halfapi.lib.routes import gen_starlette_routes
debug_routes = [
routes = [
Route('/', lambda request, *args, **kwargs: PlainTextResponse('It Works!')),
Route('/user', lambda request, *args, **kwargs:
JSONResponse({'user':request.user.json})
@ -30,10 +29,12 @@ debug_routes = [
JSONResponse({'payload':str(request.payload)}))
] if not PRODUCTION else []
for route in gen_starlette_routes():
routes.append(route)
application = Starlette(
debug=not PRODUCTION,
routes=debug_routes + [ route for route in
gen_starlette_routes(domain_scanner()) ],
routes=routes,
middleware=[
Middleware(AuthenticationMiddleware,
backend=JWTAuthenticationBackend(secret_key=SECRET))

View File

@ -103,57 +103,6 @@ def update_db(domain):
acl.insert()
def get_fct_name(http_verb, path):
"""
Returns the predictable name of the function for a route
Parameters:
- http_verb (str): The Route's HTTP method (GET, POST, ...)
- path (str): A path beginning by '/' for the route
Returns:
str: The *unique* function name for a route and it's verb
Examples:
>>> get_fct_name('foo', 'bar')
Traceback (most recent call last):
...
Exception: Malformed path
>>> get_fct_name('get', '/')
'get_'
>>> get_fct_name('GET', '/')
'get_'
>>> get_fct_name('POST', '/foo')
'post_foo'
>>> get_fct_name('POST', '/foo/bar')
'post_foo_bar'
>>> get_fct_name('DEL', '/foo/{boo}/{far}/bar')
'del_foo_BOO_FAR_bar'
>>> get_fct_name('DEL', '/foo/{boo:zoo}')
'del_foo_BOO'
"""
if path[0] != '/':
raise Exception('Malformed path')
elts = path[1:].split('/')
fct_name = [http_verb.lower()]
for elt in elts:
if elt and elt[0] == '{':
fct_name.append(elt[1:-1].split(':')[0].upper())
else:
fct_name.append(elt)
return '_'.join(fct_name)
def add_route(http_verb, path, router, acls):
@ -216,8 +165,11 @@ def update_db(domain):
for router_name in dom_mod.ROUTERS:
try:
router_mod = getattr(dom_mod.routers, router_name)
except AttributError:
router_mod = None
for router_subname in router_name.split('.'):
router_mod = getattr(router_mod or dom_mod.routers, router_subname)
except AttributeError:
# Missing router, continue
click.echo(f'The domain {domain} has no *{router_name}* router', err=True)
continue
@ -232,7 +184,23 @@ def update_db(domain):
continue
for route_path, route_params in router_mod.ROUTES.items():
d_routes = {}
if hasattr(router_mod, 'ROUTES'):
d_routes.update(router_mod.ROUTES)
else:
logger.warning(f'{router_name} is missing a ROUTES variable')
if hasattr(router_mod, 'ROUTERS'):
for router_router in router_mod.ROUTERS:
if hasattr(router_router, 'ROUTES'):
d_routes.update(router_routes.ROUTES)
else:
logger.warning(f'{router_name}.{router_router.__name__} is missing a ROUTES variable')
else:
logger.warning(f'{router_mod} is missing a ROUTERS variable')
for route_path, route_params in d_routes.items():
for http_verb, acls in route_params.items():
try:
# Insert a route and it's ACLS
@ -274,6 +242,7 @@ def domain(domains, delete, update, create, read): #, domains, read, create, up
update (boolean): If set, update the database for the selected domains
"""
raise NotImplementedError
if not domains:
if create:

View File

@ -50,7 +50,7 @@ def get_fct_name(http_verb, path: t.List):
return '_'.join(fct_name)
def route_generator(route_params, path, m_router):
def gen_routes(route_params, path, m_router):
for verb in VERBS:
params = route_params.get(verb)
if params is None:
@ -67,12 +67,12 @@ def route_generator(route_params, path, m_router):
yield {
'verb':verb,
'path':'/'.join([ elt for elt in path if elt ]),
'path':f"/{'/'.join([ elt for elt in path if elt ])}",
'params':params,
'fct': fct }
def router_scanner(m_router, path=[]):
def gen_router_routes(m_router, path=[]):
"""
[
('path', [acl], fct)
@ -80,7 +80,7 @@ def router_scanner(m_router, path=[]):
"""
if not hasattr(m_router, 'ROUTES'):
print(f'Missing *ROUTES* constant in *{domain}.routers*')
print(f'Missing *ROUTES* constant in *{m_router.__name__}*')
routes = m_router.ROUTES
@ -88,14 +88,14 @@ def router_scanner(m_router, path=[]):
for subpath, route_params in routes.items():
path.append(subpath)
for route in route_generator(route_params, path, m_router):
for route in gen_routes(route_params, path, m_router):
yield route
subroutes = route_params.get('SUBROUTES', [])
for subroute in subroutes:
path.append(subroute)
submod = importlib.import_module(f'.{subroute}', m_router.__name__)
for route_scan in router_scanner(submod, path):
for route_scan in gen_router_routes(submod, path):
yield route_scan
path.pop()
@ -106,7 +106,7 @@ def router_scanner(m_router, path=[]):
def domain_scanner(domain):
def gen_domain_routes(domain):
m_domain = importlib.import_module(domain)
if not hasattr(m_domain, 'routers'):
@ -114,4 +114,4 @@ def domain_scanner(domain):
m_router = importlib.import_module('.routers', domain)
return router_scanner(m_router)
return gen_router_routes(m_router, [domain])

View File

@ -14,7 +14,7 @@ from halfapi.db import (
AclFunction,
Acl)
from halfapi.lib.responses import *
from halfapi.lib.domain import domain_scanner
from halfapi.lib.domain import gen_domain_routes
from starlette.exceptions import HTTPException
from starlette.routing import Mount, Route
from starlette.requests import Request
@ -26,8 +26,7 @@ def route_decorator(fct: Callable, acls_mod, params: List[Dict]):
@wraps(fct)
async def caller(req: Request, *args, **kwargs):
for param in params:
acl_fct = getattr(acls_mod, param['acl'])
if acl_fct(req, *args, **kwargs):
if param['acl'](req, *args, **kwargs):
"""
We the 'acl' and 'keys' kwargs values to let the
decorated function know which ACL function answered
@ -37,7 +36,7 @@ def route_decorator(fct: Callable, acls_mod, params: List[Dict]):
req, *args,
**{
**kwargs,
**params
**param
})
raise HTTPException(401)
@ -49,17 +48,7 @@ def gen_starlette_routes():
domain_acl_mod = importlib.import_module(
f'{domain}.acl')
( Route(route['path'],
route_decorator(
route['fct'],
domain_acl_mod,
route['params'],
), methods=[route['verb']])
for route in domain_scanner(domain)
)
for route in gen_routes(domain):
for route in gen_domain_routes(domain):
yield (
Route(route['path'],
route_decorator(