mirror of
https://git.collinwebdesigns.de/oscar.krause/fastapi-dls.git
synced 2024-11-23 15:31:00 +03:00
Merge branch 'main' into ui
# Conflicts: # .PKGBUILD/PKGBUILD
This commit is contained in:
commit
f95ba1347f
@ -1,10 +0,0 @@
|
||||
# https://packages.ubuntu.com
|
||||
fastapi==0.91.0
|
||||
uvicorn[standard]==0.15.0
|
||||
python-jose[pycryptodome]==3.3.0
|
||||
pycryptodome==3.11.0
|
||||
python-dateutil==2.8.2
|
||||
sqlalchemy==1.4.46
|
||||
markdown==3.4.3
|
||||
python-dotenv==0.21.0
|
||||
jinja2==3.1.2
|
@ -1,10 +0,0 @@
|
||||
# https://packages.ubuntu.com
|
||||
fastapi==0.101.0
|
||||
uvicorn[standard]==0.23.2
|
||||
python-jose[pycryptodome]==3.3.0
|
||||
pycryptodome==3.11.0
|
||||
python-dateutil==2.8.2
|
||||
sqlalchemy==1.4.47
|
||||
markdown==3.4.4
|
||||
python-dotenv==1.0.0
|
||||
jinja2==3.1.2
|
@ -52,6 +52,7 @@ package() {
|
||||
install -Dm755 "$srcdir/$pkgname/app/main.py" "$pkgdir/opt/$pkgname/main.py"
|
||||
install -Dm755 "$srcdir/$pkgname/app/orm.py" "$pkgdir/opt/$pkgname/orm.py"
|
||||
install -Dm755 "$srcdir/$pkgname/app/util.py" "$pkgdir/opt/$pkgname/util.py"
|
||||
install -Dm755 "$srcdir/$pkgname/app/middleware.py" "$pkgdir/opt/$pkgname/middleware.py"
|
||||
|
||||
# copy static asset files
|
||||
install -Dm755 "$srcdir/$pkgname/app/static/assets/css/bootstrap.min.css" "$pkgdir/opt/$pkgname/static/assets/css/bootstrap.min.css"
|
||||
|
@ -144,11 +144,9 @@ test:
|
||||
matrix:
|
||||
- IMAGE: [ 'python:3.12-slim-bookworm' ]
|
||||
REQUIREMENTS: [ 'requirements.txt' ]
|
||||
- IMAGE: [ 'debian:bookworm' ]
|
||||
- IMAGE: [ 'debian:bookworm' ] # EOL: June 06, 2026
|
||||
REQUIREMENTS: [ '.DEBIAN/requirements-bookworm-12.txt' ]
|
||||
- IMAGE: [ 'ubuntu:23.10' ]
|
||||
REQUIREMENTS: [ '.DEBIAN/requirements-ubuntu-23.10.txt' ]
|
||||
- IMAGE: [ 'ubuntu:24.04' ]
|
||||
- IMAGE: [ 'ubuntu:24.04' ] # EOL: April 2036
|
||||
REQUIREMENTS: [ '.DEBIAN/requirements-ubuntu-24.04.txt' ]
|
||||
- IMAGE: [ 'ubuntu:24.10' ]
|
||||
REQUIREMENTS: [ '.DEBIAN/requirements-ubuntu-24.10.txt' ]
|
||||
|
42
README.md
42
README.md
@ -330,11 +330,12 @@ Packages are available here:
|
||||
|
||||
Successful tested with:
|
||||
|
||||
- Debian 12 (Bookworm) (EOL: tba.)
|
||||
- Ubuntu 22.10 (Kinetic Kudu) (EOL: July 20, 2023)
|
||||
- Ubuntu 23.04 (Lunar Lobster) (EOL: January 2024)
|
||||
- Ubuntu 23.10 (Mantic Minotaur) (EOL: July 2024)
|
||||
- Ubuntu 24.04 (Noble Numbat) (EOL: April 2036)
|
||||
- **Debian 12 (Bookworm)** (EOL: June 06, 2026)
|
||||
- *Ubuntu 22.10 (Kinetic Kudu)* (EOL: July 20, 2023)
|
||||
- *Ubuntu 23.04 (Lunar Lobster)* (EOL: January 2024)
|
||||
- *Ubuntu 23.10 (Mantic Minotaur)* (EOL: July 2024)
|
||||
- **Ubuntu 24.04 (Noble Numbat)** (EOL: April 2036)
|
||||
- *Ubuntu 24.10 (Oracular Oriole)* (EOL: tba.)
|
||||
|
||||
Not working with:
|
||||
|
||||
@ -410,21 +411,22 @@ After first success you have to replace `--issue` with `--renew`.
|
||||
|
||||
# Configuration
|
||||
|
||||
| Variable | Default | Usage |
|
||||
|------------------------|----------------------------------------|------------------------------------------------------------------------------------------------------|
|
||||
| `DEBUG` | `false` | Toggles `fastapi` debug mode |
|
||||
| `DLS_URL` | `localhost` | Used in client-token to tell guest driver where dls instance is reachable |
|
||||
| `DLS_PORT` | `443` | Used in client-token to tell guest driver where dls instance is reachable |
|
||||
| `TOKEN_EXPIRE_DAYS` | `1` | Client auth-token validity (used for authenticate client against api, **not `.tok` file!**) |
|
||||
| `LEASE_EXPIRE_DAYS` | `90` | Lease time in days |
|
||||
| `LEASE_RENEWAL_PERIOD` | `0.15` | The percentage of the lease period that must elapse before a licensed client can renew a license \*1 |
|
||||
| `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) |
|
||||
| `CORS_ORIGINS` | `https://{DLS_URL}` | Sets `Access-Control-Allow-Origin` header (comma separated string) \*2 |
|
||||
| `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid |
|
||||
| `INSTANCE_REF` | `10000000-0000-0000-0000-000000000001` | Instance identification uuid |
|
||||
| `ALLOTMENT_REF` | `20000000-0000-0000-0000-000000000001` | Allotment identification uuid |
|
||||
| `INSTANCE_KEY_RSA` | `<app-dir>/cert/instance.private.pem` | Site-wide private RSA key for singing JWTs \*3 |
|
||||
| `INSTANCE_KEY_PUB` | `<app-dir>/cert/instance.public.pem` | Site-wide public key \*3 |
|
||||
| Variable | Default | Usage |
|
||||
|--------------------------|----------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `DEBUG` | `false` | Toggles `fastapi` debug mode |
|
||||
| `DLS_URL` | `localhost` | Used in client-token to tell guest driver where dls instance is reachable |
|
||||
| `DLS_PORT` | `443` | Used in client-token to tell guest driver where dls instance is reachable |
|
||||
| `TOKEN_EXPIRE_DAYS` | `1` | Client auth-token validity (used for authenticate client against api, **not `.tok` file!**) |
|
||||
| `LEASE_EXPIRE_DAYS` | `90` | Lease time in days |
|
||||
| `LEASE_RENEWAL_PERIOD` | `0.15` | The percentage of the lease period that must elapse before a licensed client can renew a license \*1 |
|
||||
| `DATABASE` | `sqlite:///db.sqlite` | See [official SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/engines.html) |
|
||||
| `CORS_ORIGINS` | `https://{DLS_URL}` | Sets `Access-Control-Allow-Origin` header (comma separated string) \*2 |
|
||||
| `SITE_KEY_XID` | `00000000-0000-0000-0000-000000000000` | Site identification uuid |
|
||||
| `INSTANCE_REF` | `10000000-0000-0000-0000-000000000001` | Instance identification uuid |
|
||||
| `ALLOTMENT_REF` | `20000000-0000-0000-0000-000000000001` | Allotment identification uuid |
|
||||
| `INSTANCE_KEY_RSA` | `<app-dir>/cert/instance.private.pem` | Site-wide private RSA key for singing JWTs \*3 |
|
||||
| `INSTANCE_KEY_PUB` | `<app-dir>/cert/instance.public.pem` | Site-wide public key \*3 |
|
||||
| `SUPPORT_MALFORMED_JSON` | `false` | Support parsing for mal formatted "mac_address_list" ([Issue](https://git.collinwebdesigns.de/oscar.krause/fastapi-dls/-/issues/1)) |
|
||||
|
||||
\*1 For example, if the lease period is one day and the renewal period is 20%, the client attempts to renew its license
|
||||
every 4.8 hours. If network connectivity is lost, the loss of connectivity is detected during license renewal and the
|
||||
|
@ -100,6 +100,11 @@ app.add_middleware(
|
||||
allow_methods=['*'],
|
||||
allow_headers=['*'],
|
||||
)
|
||||
if bool(env('SUPPORT_MALFORMED_JSON', False)):
|
||||
from middleware import PatchMalformedJsonMiddleware
|
||||
|
||||
logger.info(f'Enabled "PatchMalformedJsonMiddleware"!')
|
||||
app.add_middleware(PatchMalformedJsonMiddleware, enabled=True)
|
||||
|
||||
|
||||
# Helper
|
||||
|
43
app/middleware.py
Normal file
43
app/middleware.py
Normal file
@ -0,0 +1,43 @@
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.requests import Request
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PatchMalformedJsonMiddleware(BaseHTTPMiddleware):
|
||||
# see oscar.krause/fastapi-dls#1
|
||||
|
||||
REGEX = '(\"mac_address_list\"\:\s?\[)([\w\d])'
|
||||
|
||||
def __init__(self, app, enabled: bool):
|
||||
super().__init__(app)
|
||||
self.enabled = enabled
|
||||
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
body = await request.body()
|
||||
content_type = request.headers.get('Content-Type')
|
||||
|
||||
if self.enabled and content_type == 'application/json':
|
||||
body = body.decode()
|
||||
try:
|
||||
json.loads(body)
|
||||
except json.decoder.JSONDecodeError:
|
||||
logger.warning(f'Malformed json received! Try to fix it, "PatchMalformedJsonMiddleware" is enabled.')
|
||||
s = PatchMalformedJsonMiddleware.fix_json(body)
|
||||
logger.debug(f'Fixed JSON: "{s}"')
|
||||
s = json.loads(s) # ensure json is now valid
|
||||
# set new body
|
||||
request._body = json.dumps(s).encode('utf-8')
|
||||
|
||||
response = await call_next(request)
|
||||
return response
|
||||
|
||||
@staticmethod
|
||||
def fix_json(s: str) -> str:
|
||||
s = s.replace('\t', '')
|
||||
s = s.replace('\n', '')
|
||||
return re.sub(PatchMalformedJsonMiddleware.REGEX, r'\1"\2', s)
|
14
test/main.py
14
test/main.py
@ -1,7 +1,8 @@
|
||||
import sys
|
||||
from base64 import b64encode as b64enc
|
||||
from hashlib import sha256
|
||||
from calendar import timegm
|
||||
from datetime import datetime
|
||||
from hashlib import sha256
|
||||
from os.path import dirname, join
|
||||
from uuid import uuid4, UUID
|
||||
|
||||
@ -9,7 +10,6 @@ from dateutil.relativedelta import relativedelta
|
||||
from jose import jwt, jwk
|
||||
from jose.constants import ALGORITHMS
|
||||
from starlette.testclient import TestClient
|
||||
import sys
|
||||
|
||||
# add relative path to use packages as they were in the app/ dir
|
||||
sys.path.append('../')
|
||||
@ -18,6 +18,7 @@ sys.path.append('../app')
|
||||
from app import main
|
||||
from app.util import load_key
|
||||
|
||||
# main.app.add_middleware(PatchMalformedJsonMiddleware, enabled=True)
|
||||
client = TestClient(main.app)
|
||||
|
||||
ORIGIN_REF, ALLOTMENT_REF, SECRET = str(uuid4()), '20000000-0000-0000-0000-000000000001', 'HelloWorld'
|
||||
@ -106,6 +107,15 @@ def test_auth_v1_origin():
|
||||
assert response.json().get('origin_ref') == ORIGIN_REF
|
||||
|
||||
|
||||
def test_auth_v1_origin_malformed_json(): # see oscar.krause/fastapi-dls#1
|
||||
from middleware import PatchMalformedJsonMiddleware
|
||||
|
||||
# test regex (temporary, until this section is merged into main.py
|
||||
s = '{"environment": {"fingerprint": {"mac_address_list": [ff:ff:ff:ff:ff:ff"]}}'
|
||||
replaced = PatchMalformedJsonMiddleware.fix_json(s)
|
||||
assert replaced == '{"environment": {"fingerprint": {"mac_address_list": ["ff:ff:ff:ff:ff:ff"]}}'
|
||||
|
||||
|
||||
def auth_v1_origin_update():
|
||||
payload = {
|
||||
"registration_pending": False,
|
||||
|
Loading…
Reference in New Issue
Block a user