[wip][routing] update routes scanner functions in lib.routes

This commit is contained in:
Maxime Alves LIRMM 2020-09-22 14:04:19 +02:00
parent c54101c3e6
commit ba44a01a45

View File

@ -2,7 +2,7 @@
from functools import wraps from functools import wraps
import importlib import importlib
import sys import sys
from typing import Callable, List, Tuple from typing import Callable, List, Tuple, Dict
from halfapi.conf import (PROJECT_NAME, DB_NAME, HOST, PORT, from halfapi.conf import (PROJECT_NAME, DB_NAME, HOST, PORT,
PRODUCTION, DOMAINS) PRODUCTION, DOMAINS)
@ -14,6 +14,7 @@ from halfapi.db import (
AclFunction, AclFunction,
Acl) Acl)
from halfapi.lib.responses import * from halfapi.lib.responses import *
from halfapi.lib.domain import domain_scanner
from starlette.exceptions import HTTPException from starlette.exceptions import HTTPException
from starlette.routing import Mount, Route from starlette.routing import Mount, Route
from starlette.requests import Request from starlette.requests import Request
@ -21,24 +22,11 @@ from starlette.requests import Request
class DomainNotFoundError(Exception): class DomainNotFoundError(Exception):
pass pass
def get_routes(domains=None): def route_decorator(fct: Callable, acls_mod, params: List[Dict]):
""" Procedure to mount the registered domains on their prefixes
Parameters:
- app (ASGIApp): The Starlette instance
- domains (list): The domains to mount, retrieved from the database
with their attributes "name"
Returns: Nothing
"""
def route_decorator(fct: Callable, acls_mod, acls: List[Tuple]):
@wraps(fct) @wraps(fct)
async def caller(req: Request, *args, **kwargs): async def caller(req: Request, *args, **kwargs):
for acl_fct_name, keys in acls: for param in params:
acl_fct = getattr(acls_mod, acl_fct_name) acl_fct = getattr(acls_mod, param['acl'])
if acl_fct(req, *args, **kwargs): if acl_fct(req, *args, **kwargs):
""" """
We the 'acl' and 'keys' kwargs values to let the We the 'acl' and 'keys' kwargs values to let the
@ -49,48 +37,34 @@ def get_routes(domains=None):
req, *args, req, *args,
**{ **{
**kwargs, **kwargs,
'acl': f'{acls_mod.__name__}.{acl_fct_name}', **params
'keys': keys
}) })
raise HTTPException(401) raise HTTPException(401)
return caller return caller
app_routes = [] def gen_starlette_routes():
for domain_name in DOMAINS: for domain in DOMAINS:
try: domain_acl_mod = importlib.import_module(
domain = next(Domain(name=domain_name).select()) f'{domain}.acl')
except StopIteration:
raise DomainNotFoundError(
f"Domain '{domain_name}' not found in '{DB_NAME}' database!")
domain_acl_mod = importlib.import_module(f'{domain["name"]}.acl')
domain_routes = []
for router in APIRouter(domain=domain['name']).select():
router_routes = []
router_mod = importlib.import_module( ( Route(route['path'],
'{domain}.routers.{name}'.format(**router))
with APIRoute(domain=domain['name'],
router=router['name']) as routes:
for route in routes.select():
fct_name = route.pop('fct_name')
acls = [ (elt['acl_fct_name'], elt['keys'])
for elt in Acl(**route).select('acl_fct_name', 'keys') ]
router_routes.append(
Route(route['path'],
route_decorator( route_decorator(
getattr(router_mod, fct_name), route['fct'],
domain_acl_mod, domain_acl_mod,
acls route['params'],
), methods=[route['http_verb']]) ), methods=[route['verb']])
for route in domain_scanner(domain)
) )
domain_routes.append( for route in gen_routes(domain):
Mount('/{name}'.format(**router), routes=router_routes))
app_routes.append(Mount('/{name}'.format(**domain), yield (
routes=domain_routes)) Route(route['path'],
return app_routes route_decorator(
route['fct'],
domain_acl_mod,
route['params'],
), methods=[route['verb']])
)