[wip][routing] update routes scanner functions in lib.routes
This commit is contained in:
parent
c54101c3e6
commit
ba44a01a45
@ -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,76 +22,49 @@ 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
|
@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):
|
||||||
|
"""
|
||||||
|
We the 'acl' and 'keys' kwargs values to let the
|
||||||
|
decorated function know which ACL function answered
|
||||||
|
True, and which keys the request will return
|
||||||
|
"""
|
||||||
|
return await fct(
|
||||||
|
req, *args,
|
||||||
|
**{
|
||||||
|
**kwargs,
|
||||||
|
**params
|
||||||
|
})
|
||||||
|
|
||||||
Parameters:
|
raise HTTPException(401)
|
||||||
|
|
||||||
- app (ASGIApp): The Starlette instance
|
return caller
|
||||||
- domains (list): The domains to mount, retrieved from the database
|
|
||||||
with their attributes "name"
|
|
||||||
|
|
||||||
Returns: Nothing
|
def gen_starlette_routes():
|
||||||
"""
|
for domain in DOMAINS:
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
|
||||||
def route_decorator(fct: Callable, acls_mod, acls: List[Tuple]):
|
for route in gen_routes(domain):
|
||||||
@wraps(fct)
|
|
||||||
async def caller(req: Request, *args, **kwargs):
|
|
||||||
for acl_fct_name, keys in acls:
|
|
||||||
acl_fct = getattr(acls_mod, acl_fct_name)
|
|
||||||
if acl_fct(req, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
We the 'acl' and 'keys' kwargs values to let the
|
|
||||||
decorated function know which ACL function answered
|
|
||||||
True, and which keys the request will return
|
|
||||||
"""
|
|
||||||
return await fct(
|
|
||||||
req, *args,
|
|
||||||
**{
|
|
||||||
**kwargs,
|
|
||||||
'acl': f'{acls_mod.__name__}.{acl_fct_name}',
|
|
||||||
'keys': keys
|
|
||||||
})
|
|
||||||
|
|
||||||
raise HTTPException(401)
|
yield (
|
||||||
|
Route(route['path'],
|
||||||
return caller
|
route_decorator(
|
||||||
|
route['fct'],
|
||||||
app_routes = []
|
domain_acl_mod,
|
||||||
for domain_name in DOMAINS:
|
route['params'],
|
||||||
try:
|
), methods=[route['verb']])
|
||||||
domain = next(Domain(name=domain_name).select())
|
)
|
||||||
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(
|
|
||||||
'{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(
|
|
||||||
getattr(router_mod, fct_name),
|
|
||||||
domain_acl_mod,
|
|
||||||
acls
|
|
||||||
), methods=[route['http_verb']])
|
|
||||||
)
|
|
||||||
|
|
||||||
domain_routes.append(
|
|
||||||
Mount('/{name}'.format(**router), routes=router_routes))
|
|
||||||
|
|
||||||
app_routes.append(Mount('/{name}'.format(**domain),
|
|
||||||
routes=domain_routes))
|
|
||||||
return app_routes
|
|
||||||
|
Loading…
Reference in New Issue
Block a user