[conf] add envfile supprt / fix the bugs related to acl_caller_middleware / fix the bugs related to responses classes

This commit is contained in:
Maxime Alves LIRMM@home 2020-07-09 08:02:44 +02:00
parent f0d5eb7d92
commit 644e5c5d3d
7 changed files with 129 additions and 28 deletions

View File

@ -1,2 +1,3 @@
export HALFORM_SECRET="halform_secret"
export HALFORM_DSN="dbname=api user=api password= host=127.0.0.1 port=5432"
HALFORM_SECRET="halform_secret"
HALFORM_DSN="dbname=api user=api password= host=127.0.0.1 port=5432"
DEBUG=1

View File

@ -100,16 +100,18 @@ def check_conf():
if not environ.get('HALFORM_DSN', False):
print('Missing HALFORM_DSN variable from configuration')
DEBUG = True
CONFIG={
'DEBUG' : 'DEBUG' in environ.keys()
}
debug_routes = [
Route('/', lambda request: PlainTextResponse('It Works!')),
Route('/user', lambda request: JSONResponse({'user':request.user})),
Route('/payload', lambda request: JSONResponse({'payload':request.payload}))
] if DEBUG is True else []
Route('/', lambda request, *args, **kwargs: PlainTextResponse('It Works!')),
Route('/user', lambda request, *args, **kwargs: JSONResponse({'user':str(request.user)})),
Route('/payload', lambda request, *args, **kwargs: JSONResponse({'payload':str(request.payload)}))
] if CONFIG['DEBUG'] is True else []
app = Starlette(
debug=DEBUG,
debug=CONFIG['DEBUG'],
routes=debug_routes,
middleware=[
Middleware(AuthenticationMiddleware, backend=JWTAuthenticationBackend(secret_key=environ.get('HALFORM_SECRET'))),

View File

@ -32,6 +32,7 @@ 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')
@click.option('--debug', default=False)
@ -42,7 +43,17 @@ def cli(ctx):
@click.option('--dbuser', default='api')
@click.option('--dbpassword', default='')
@cli.command()
def run(host, port, debug, dev, dbname, dbhost, dbport, dbuser, dbpassword):
def run(envfile, host, port, debug, dev, dbname, dbhost, dbport, dbuser, dbpassword):
if envfile:
try:
with open(envfile) as f:
print('Will use the following env parameters')
print(f.readlines())
pass
except FileNotFoundError:
print(f'No file named {envfile}')
envfile = None
if dev:
debug = True
reload = True
@ -87,6 +98,7 @@ def run(host, port, debug, dev, dbname, dbhost, dbport, dbuser, dbpassword):
sys.path.insert(0, os.getcwd())
click.echo(sys.path)
uvicorn.run('halfapi.app:app',
env_file=envfile,
host=host,
port=int(port),
log_level=log_level,

View File

@ -1,4 +1,6 @@
#!/usr/bin/env python3
from os import environ
from starlette.exceptions import HTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.routing import Match, Mount
@ -6,7 +8,11 @@ from starlette.types import ASGIApp, Receive, Scope, Send
from halfapi.models.api.view.acl import Acl as AclView
def match_route(scope: Scope):
class DebugRouteException(Exception):
def __init__(self, *args, **kwargs):
super().__init__(self)
def match_route(app: ASGIApp, scope: Scope):
""" Checks all routes from "app" and checks if it matches with the one from
scope
@ -30,7 +36,10 @@ def match_route(scope: Scope):
Refer to the database documentation for more details on the api.route
table.
"""
from halfapi.app import app
print('3')
from ..app import CONFIG
print(CONFIG)
result = {
'domain': None,
@ -39,6 +48,9 @@ def match_route(scope: Scope):
'version': None
}
if 'DEBUG' in CONFIG.keys() and len(scope['path'].split('/')) <= 3:
raise DebugRouteException()
try:
""" Identification of the parts of the path
@ -51,7 +63,6 @@ def match_route(scope: Scope):
except ValueError as e:
#404 Not found
raise HTTPException(404)
# Prefix the path with "/"
path = f'/{path}'
@ -111,13 +122,18 @@ class AclCallerMiddleware(BaseHTTPMiddleware):
await self.app(scope, receive, send)
return
app = self.app
while True:
if not hasattr(app, 'app'):
break
app = app.app
if scope['path'].split('/')[-1] not in ['docs','openapi.json','redoc']:
# routes in the the database, the others being
# docs/openapi.json/redoc
d_match, path_params = match_route(scope)
try:
d_match, path_params = match_route(app, scope)
scope['acls'] = []
for acl in AclView(**d_match).select():
# retrieve related ACLs
@ -132,5 +148,11 @@ class AclCallerMiddleware(BaseHTTPMiddleware):
# TODO : No ACL sur une route existante, prevenir l'admin?
print("No ACL")
pass
except DebugRouteException:
print("Debug route")
if 'DEBUG_ACL' in environ.keys():
scope['acls'] = environ['DEBUG_ACL'].split(':')
else:
scope['acls'] = []
return await self.app(scope, receive, send)

View File

@ -5,12 +5,13 @@ from datetime import date
from io import TextIOBase, StringIO
# asgi framework
from starlette.responses import Response
from starlette.responses import PlainTextResponse, Response
__all__ = ['CSVResponse',
'InternalServerErrorResponse',
'NotFoundResponse',
'NotImplementedResponse',
'PlainTextResponse',
'UnauthorizedResponse']
class CSVResponse(Response):
@ -32,27 +33,27 @@ class CSVResponse(Response):
class InternalServerErrorResponse(Response):
""" The 500 Internal Server Error default Response
"""
def __init__(self):
def __init__(self, *args, **kwargs):
super().__init__(status_code=500)
class NotFoundResponse(Response):
""" The 404 Not Found default Response
"""
def __init__(self):
def __init__(self, *args, **kwargs):
super().__init__(status_code=404)
class NotImplementedResponse(Response):
""" The 501 Not Implemented default Response
"""
def __init__(self):
def __init__(self, *args, **kwargs):
super().__init__(status_code=501)
class UnauthorizedResponse(Response):
""" The 401 Not Found default Response
"""
def __init__(self):
def __init__(self, *args, **kwargs):
super().__init__(status_code = 401)

79
poetry.lock generated
View File

@ -1,6 +1,7 @@
[[package]]
category = "dev"
description = "Atomic file writes."
marker = "sys_platform == \"win32\""
name = "atomicwrites"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
@ -53,6 +54,14 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "0.4.3"
[[package]]
category = "main"
description = "Handle .env files"
name = "dotenv"
optional = false
python-versions = "*"
version = "0.0.5"
[[package]]
category = "main"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
@ -95,6 +104,7 @@ psycopg2-binary = "*"
reference = "fe53195abb637d2192857e8b4878f4865b0fcce4"
type = "git"
url = "git@gite.lirmm.fr:newsi/halfORM.git"
[[package]]
category = "main"
description = "A collection of framework independent HTTP protocol utils."
@ -159,6 +169,19 @@ uvicorn = "*"
reference = "4f9cf92253b2ee526a528724877840c8ec158d3a"
type = "git"
url = "git@gite.lirmm.fr:newsi/api/organigramme.git"
[[package]]
category = "dev"
description = "Core utilities for Python packages"
name = "packaging"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "20.4"
[package.dependencies]
pyparsing = ">=2.0.2"
six = "*"
[[package]]
category = "dev"
description = "plugin and hook calling mechanisms for python"
@ -217,23 +240,39 @@ crypto = ["cryptography (>=1.4)"]
flake8 = ["flake8", "flake8-import-order", "pep8-naming"]
test = ["pytest (>=4.0.1,<5.0.0)", "pytest-cov (>=2.6.0,<3.0.0)", "pytest-runner (>=4.2,<5.0.0)"]
[[package]]
category = "dev"
description = "Python parsing module"
name = "pyparsing"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
version = "2.4.7"
[[package]]
category = "dev"
description = "pytest: simple powerful testing with Python"
name = "pytest"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "3.10.1"
python-versions = ">=3.5"
version = "5.4.3"
[package.dependencies]
atomicwrites = ">=1.0"
attrs = ">=17.4.0"
colorama = "*"
more-itertools = ">=4.0.0"
pluggy = ">=0.7"
packaging = "*"
pluggy = ">=0.12,<1.0"
py = ">=1.5.0"
setuptools = "*"
six = ">=1.10.0"
wcwidth = "*"
[package.dependencies.importlib-metadata]
python = "<3.8"
version = ">=0.12"
[package.extras]
checkqa-mypy = ["mypy (v0.761)"]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
[[package]]
category = "main"
@ -276,6 +315,7 @@ half_orm = "*"
reference = "d0f14a9631eecd29098d13a3f34e9cd533145f24"
type = "git"
url = "git@gite.lirmm.fr:newsi/sidb_halfORM.git"
[[package]]
category = "dev"
description = "Python 2 and 3 compatibility utilities"
@ -335,6 +375,14 @@ optional = false
python-versions = "*"
version = "0.14.0"
[[package]]
category = "dev"
description = "Measures the displayed width of unicode strings in a terminal"
name = "wcwidth"
optional = false
python-versions = "*"
version = "0.2.5"
[[package]]
category = "main"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
@ -360,7 +408,7 @@ testing = ["jaraco.itertools", "func-timeout"]
organigramme = ["fastapi", "organigramme"]
[metadata]
content-hash = "54154bcf65bf5540092d6493dd5810fb541bc4a75e9fc328ca66d25ef5ed0584"
content-hash = "56e1f269ca07039fa6898fa427261f61cab9ef871c5a82edb592cbfb197c2d03"
python-versions = "^3.7"
[metadata.files]
@ -388,6 +436,9 @@ colorama = [
{file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
{file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"},
]
dotenv = [
{file = "dotenv-0.0.5.tar.gz", hash = "sha256:b58d2ab3f83dbd4f8a362b21158a606bee87317a9444485566b3c8f0af847091"},
]
fastapi = [
{file = "fastapi-0.58.1-py3-none-any.whl", hash = "sha256:d7499761d5ca901cdf5b6b73018d14729593f8ab1ea22d241f82fa574fc406ad"},
{file = "fastapi-0.58.1.tar.gz", hash = "sha256:92e59b77eef7d6eaa80b16d275adda06b5f33b12d777e3fc5521b2f7f4718e13"},
@ -424,6 +475,10 @@ more-itertools = [
{file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"},
]
organigramme = []
packaging = [
{file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
{file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
]
pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
@ -487,9 +542,13 @@ pyjwt = [
{file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"},
{file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"},
]
pyparsing = [
{file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
{file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
]
pytest = [
{file = "pytest-3.10.1-py2.py3-none-any.whl", hash = "sha256:3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec"},
{file = "pytest-3.10.1.tar.gz", hash = "sha256:e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"},
{file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
{file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
]
pyyaml = [
{file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
@ -536,6 +595,10 @@ uvloop = [
{file = "uvloop-0.14.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09"},
{file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"},
]
wcwidth = [
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]
websockets = [
{file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"},
{file = "websockets-8.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170"},

View File

@ -22,9 +22,9 @@ requests = "^2"
[tool.poetry.extras]
organigramme = [ "fastapi", "organigramme" ]
[tool.poetry.scripts]
halfapi = 'halfapi.cli:cli'
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
[tool.poetry.scripts]
halfapi = 'halfapi.cli:cli'