Bladeren bron

Added logging for authenticated APIs and removed old files + bugfix

proxy2core
root 1 maand geleden
bovenliggende
commit
e08959d9f4
71 gewijzigde bestanden met toevoegingen van 1525 en 5396 verwijderingen
  1. +2
    -2
      .env
  2. +3
    -0
      .gitignore
  3. BIN
      __pycache__/app.cpython-310.pyc
  4. BIN
      __pycache__/audit.cpython-310.pyc
  5. BIN
      __pycache__/security.cpython-310.pyc
  6. +0
    -354
      app.old
  7. +9
    -4
      app.py
  8. +129
    -0
      audit.py
  9. BIN
      logica_reslevis/__pycache__/alarm.cpython-310.pyc
  10. BIN
      logica_reslevis/__pycache__/building.cpython-310.pyc
  11. BIN
      logica_reslevis/__pycache__/config.cpython-310.pyc
  12. BIN
      logica_reslevis/__pycache__/operator.cpython-310.pyc
  13. BIN
      logica_reslevis/__pycache__/plan.cpython-310.pyc
  14. BIN
      logica_reslevis/__pycache__/subject.cpython-310.pyc
  15. BIN
      logica_reslevis/__pycache__/track.cpython-310.pyc
  16. BIN
      logica_reslevis/__pycache__/tracker.cpython-310.pyc
  17. BIN
      logica_reslevis/__pycache__/zone.cpython-310.pyc
  18. +83
    -0
      logica_reslevis/alarm.py
  19. +73
    -0
      logica_reslevis/building.py
  20. +2
    -1
      logica_reslevis/config.py
  21. +73
    -0
      logica_reslevis/operator.py
  22. +73
    -0
      logica_reslevis/plan.py
  23. +73
    -0
      logica_reslevis/subject.py
  24. +82
    -0
      logica_reslevis/track.py
  25. +84
    -0
      logica_reslevis/tracker.py
  26. +73
    -0
      logica_reslevis/zone.py
  27. +0
    -23
      res-levis-api-client.old/.gitignore
  28. +0
    -124
      res-levis-api-client.old/README.md
  29. +0
    -26
      res-levis-api-client.old/pyproject.toml
  30. +0
    -8
      res-levis-api-client.old/res_levis_api_client/__init__.py
  31. +0
    -1
      res-levis-api-client.old/res_levis_api_client/api/__init__.py
  32. +0
    -1
      res-levis-api-client.old/res_levis_api_client/api/developers/__init__.py
  33. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_alarms.py
  34. +0
    -204
      res-levis-api-client.old/res_levis_api_client/api/developers/get_buildings.py
  35. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_gateways.py
  36. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_operators.py
  37. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_plans.py
  38. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_subjects.py
  39. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_trackers.py
  40. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_tracks.py
  41. +0
    -219
      res-levis-api-client.old/res_levis_api_client/api/developers/get_zones.py
  42. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_alarm.py
  43. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_building.py
  44. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_gateway.py
  45. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_operator.py
  46. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_plan.py
  47. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_subject.py
  48. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_track.py
  49. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_tracker.py
  50. +0
    -110
      res-levis-api-client.old/res_levis_api_client/api/developers/post_zone.py
  51. +0
    -268
      res-levis-api-client.old/res_levis_api_client/client.py
  52. +0
    -16
      res-levis-api-client.old/res_levis_api_client/errors.py
  53. +0
    -23
      res-levis-api-client.old/res_levis_api_client/models/__init__.py
  54. +0
    -231
      res-levis-api-client.old/res_levis_api_client/models/alarm_item.py
  55. +0
    -107
      res-levis-api-client.old/res_levis_api_client/models/building_item.py
  56. +0
    -175
      res-levis-api-client.old/res_levis_api_client/models/gateway_item.py
  57. +0
    -123
      res-levis-api-client.old/res_levis_api_client/models/operator_item.py
  58. +0
    -105
      res-levis-api-client.old/res_levis_api_client/models/plan_item.py
  59. +0
    -132
      res-levis-api-client.old/res_levis_api_client/models/subject_item.py
  60. +0
    -201
      res-levis-api-client.old/res_levis_api_client/models/track_item.py
  61. +0
    -166
      res-levis-api-client.old/res_levis_api_client/models/tracker_item.py
  62. +0
    -112
      res-levis-api-client.old/res_levis_api_client/models/zone_item.py
  63. +0
    -1
      res-levis-api-client.old/res_levis_api_client/py.typed
  64. +0
    -54
      res-levis-api-client.old/res_levis_api_client/types.py
  65. BIN
      routes/__pycache__/reslevis.cpython-310.pyc
  66. +523
    -52
      routes/reslevis.py
  67. +0
    -116
      routes/reslevis.py.ori
  68. BIN
      schemas/__pycache__/reslevis.cpython-310.pyc
  69. +138
    -24
      security.py
  70. +105
    -0
      security.py.ok
  71. BIN
      venv.tgz

+ 2
- 2
.env Bestand weergeven

@@ -8,8 +8,8 @@


#CLINET SETTINGS
KEYCLOAK_AUDIENCE=Fastapi
SECRET=568bd5bcbe553e2692fc0476e4e176b4c6df57771235fbb2
KEYCLOAK_AUDIENCE=account,reslevis-frontend,Fastapi
SECRET=wojuoB7Z5xhlPFrF2lIxJSSdVHCApEgC

#KEYCLOAK URLS
KEYCLOAK_SERVER=https://10.251.0.30:10002


+ 3
- 0
.gitignore Bestand weergeven

@@ -1 +1,4 @@
/code_to_inspect_and_delete/
venv/
venv.tgz
.ev

BIN
__pycache__/app.cpython-310.pyc Bestand weergeven


BIN
__pycache__/audit.cpython-310.pyc Bestand weergeven


BIN
__pycache__/security.cpython-310.pyc Bestand weergeven


+ 0
- 354
app.old Bestand weergeven

@@ -1,354 +0,0 @@
import json
import subprocess
import logging
import ipaddress
#import api_utils.carddav_util as carddav_util
#from .api_utils import carddav_util
from enum import Enum
from typing import Any, Dict, List, Optional
# import wave
import os
import shutil
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Callable
import base64
from datetime import datetime, timedelta

from .api_utils import api_utils as api_utils
from .api_utils import coerce_methods as coerce_methods
from collections import OrderedDict

from pydantic import BaseModel, Field

from fastapi import Depends, FastAPI, HTTPException, File, UploadFile
from fastapi.encoders import jsonable_encoder
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.openapi.utils import get_openapi

from starlette.status import HTTP_403_FORBIDDEN
from starlette.responses import RedirectResponse, Response, JSONResponse
from starlette.requests import Request
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import FileResponse
from starlette.types import ASGIApp, Message, Receive, Scope, Send


from .models.cellular_hardware import cellularHardware
from .models.cellular_hardwares import cellularHardwares
from .models.call import call, post_call
from .models.calls import calls
from .models.httpresponse import httpResponse400, httpResponse200, httpResponse500


from fastapi_login import LoginManager


#from .core.security import manager,NotAuthenticatedException

from .routes import auth as _auth
auth_router = _auth.router
from .routes import user as _user
user_router = _user.router
#from routes.posts import router as posts_router
from .routes import majornet as _majornet
majornet_router = _majornet.router
from .routes import presence as _presence
presence_router = _presence.router
from .routes import contacts as _contacts
contacts_router = _contacts.router
from .routes import reslevis as _reslevis
reslevis_router = _reslevis.router

#security
from fastapi import FastAPI, Security
from fastapi.security import OAuth2AuthorizationCodeBearer

#AUTH_URL = "https://192.168.1.3:10002/realms/API.Server.local/protocol/openid-connect/auth"
#TOKEN_URL = "https://192.168.1.3:10002/realms/API.Server.local/protocol/openid-connect/token"

oauth2 = OAuth2AuthorizationCodeBearer(
authorizationUrl=AUTH_URL,
tokenUrl=TOKEN_URL,
scopes={"items:read": "Read items", "items:write": "Write items"},
)

log = logging.getLogger(__name__) # pylint: disable=invalid-name

DEBUG = True

app = FastAPI(title="MajorNet API", redoc_url=None, docs_url=None, openapi_url=None)
####DEV
##app = FastAPI(title=PROJECT_NAME)
app.debug = True


logging.basicConfig(filename='/tmp/app.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')
logging.warning('This will /tmp/app.log')


ALLOWED_HOSTS = ["*"]

app.add_middleware(
CORSMiddleware,
allow_origins=ALLOWED_HOSTS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


@app.exception_handler(NotAuthenticatedException)
def auth_exception_handler(request: Request, exc: NotAuthenticatedException):
"""
Redirect the user to the login page if not logged in
"""
return RedirectResponse(url='/login')

app.include_router(auth_router)
app.include_router(user_router)
#app.include_router(posts_router)
app.include_router(presence_router)
app.include_router(majornet_router)
app.include_router(contacts_router)
app.include_router(reslevis_router, prefix="/reslevis", tags=["reslevis"])

@app.get("/")
async def root():
#return {"url": "/docs"}
return get_swagger_ui_html(openapi_url="/openapi.json", title="docs")


@app.get("/openapi.json/", tags=["Documentation"])
async def get_open_api_endpoint():
#async def get_open_api_endpoint(current_user: User = Depends(get_current_active_user)):
return JSONResponse(get_openapi(title="MajorNet APIs", version="1.0", routes=app.routes))


@app.get("/docs/", tags=["Documentation"])
#async def get_documentation(current_user: User = Depends(get_current_active_user)):
async def get_documentation():
if DEBUG: print("SONO IN /DOCS")
return get_swagger_ui_html(openapi_url="/openapi.json", title="docs")




@app.post("/majortel/call/", tags=["Majortel"])
async def route_call(active_user=Depends(manager),callerNumber=None, calledNumber=None):
try:
if DEBUG: print("Entro nel TRY")
# Check if the callerNumber sent is an ip address and retrieve the associated number
ipaddress.ip_address(callerNumber)
callerNumberRetrieved = os.popen('asterisk -rx "sip show peers" | grep ' + callerNumber).read()
callerNumberRetrieved = callerNumberRetrieved.split("/")
callerNumber = callerNumberRetrieved[0]
except:
if DEBUG: print("EXCEPT")
mode = "callFromTo"
from_ = callerNumber
to_ = calledNumber
if DEBUG: print("DATI ARRIVATI: ")
if DEBUG: print(callerNumber)
if DEBUG: print(calledNumber)
subprocess.Popen(['perl', '/usr/local/bin/ast/voice.pl', mode, from_, to_], stdout=subprocess.PIPE)
return


@app.post("/majortel/ring/", tags=["Majortel"])
async def route_ring(active_user=Depends(manager),calledNumber=None, calledId=None, ringTime=None):
try:
if DEBUG: print("Entro nel TRY")
# Check if the callerNumber sent is an ip address and retrieve the associated number
ipaddress.ip_address(calledNumber)
calledNumberRetrieved = os.popen('asterisk -rx "sip show peers" | grep ' + calledNumber).read()
calledNumberRetrieved = calledNumberRetrieved.split("/")
calledNumber = calledNumberRetrieved[0]
except:
if DEBUG: print("EXCEPT")
mode = "ringAlert"
to_ = calledNumber
calledId_ = calledId
ringTime_ = ringTime
if DEBUG: print("DATI ARRIVATI: ")
if DEBUG: print(calledNumber)
if DEBUG: print(calledId)
if DEBUG: print(ringTime)
subprocess.Popen(['perl', '/usr/local/bin/ast/voice.pl', mode, to_, calledId_, ringTime_], stdout=subprocess.PIPE)
return


@app.get("/majortel/hardware/", response_model=cellularHardwares, tags=["Majortel"])
#async def majortel_hardware_get(current_user: User = Depends(get_current_active_user)):
async def majortel_hardware_get():
gsm_temp_list = "GSM span1: Provisioned, Up, Active"

response = {"CellularHardwares": []}
hardware_dict = {}
myCmd = os.popen('asterisk -rx "gsm show spans"').read()
myCmd = myCmd.split("\n")
# cancello l'ultimo item della lista poichè, risultando vuoto dopo lo split,
# genera errore "index out of range" nei successivi accessi alla lista
if DEBUG: print("spans: ")
if DEBUG: print(myCmd)
myCmd = os.popen('asterisk -rx "dongle show devices"').read()
myCmd = myCmd.split("\n")
# cancello il primo item della lista poichè contiene la legenda
del myCmd[0]
del myCmd[-1]
# costruisco la response
for device in myCmd:
device = device.split()
hardware_id = device[0]
current_device = os.popen('asterisk -rx "dongle show device state ' + hardware_id + '"').read()
current_device = current_device.split("\n")
# cancello il primo e gli ultimi item della lista poichè, risultando vuoti dopo lo split,
# generano errore "index out of range" nei successivi accessi alla lista
del current_device[0]
del current_device[-1]
del current_device[-1]
# costruisco un dizionario a partire dall'output della system call
for row in current_device:
row = row.split(":")
row[0] = row[0].strip()
row[1] = row[1].strip()
hardware_dict[row[0]] = row[1]
hardware_id = hardware_dict["Device"]
status = hardware_dict["State"]
signal = hardware_dict["RSSI"]
signal = int(signal[0:2])
operator = hardware_dict["Provider Name"]
device_obj = {"id": hardware_id, "description": "description", "status": status, "signal_level": signal,
"registered_number": "To Do", "operator": operator}
response["CellularHardwares"].append(device_obj)

return response


@app.get("/majortel/hardware/{item_id}", response_model=cellularHardware, tags=["Majortel"], responses={400: {"model": httpResponse400}})
#async def majortel_hardware_id_get(item_id: str, current_user: User = Depends(get_current_active_user)):
async def majortel_hardware_id_get(item_id: str,active_user=Depends(manager)):
hardware_response = {}
hardware_dict = {}
current_device = os.popen('asterisk -rx "dongle show device state ' + item_id + '"').read()
current_device = current_device.split("\n")
# cancello il primo e gli ultimi item della lista poichè, risultando vuoti dopo lo split,
# generano errore "index out of range" nei successivi accessi alla lista
del current_device[0]
if (current_device[0]):
del current_device[-1]
del current_device[-1]
# costruisco un dizionario a partire dall'output della system call
for row in current_device:
row = row.split(":")
row[0] = row[0].strip()
row[1] = row[1].strip()
hardware_dict[row[0]] = row[1]
hardware_id = hardware_dict["Device"]
status = hardware_dict["State"]
signal = hardware_dict["RSSI"]
signal = int(signal[0:2])
operator = hardware_dict["Provider Name"]
hardware_response = {"id": hardware_id, "description": "description", "status": status, "signal_level": signal,
"registered_number": "To Do", "operator": operator}
return hardware_response
else:
return JSONResponse(status_code=404, content={"message": "Device not found"})


@app.get("/majortel/calls/", response_model=calls, tags=["Majortel"])
#async def majortel_calls_get(current_user: User = Depends(get_current_active_user)):
async def majortel_calls_get(active_user=Depends(manager)):
response = {"Calls": []}
p = subprocess.Popen(['perl', '/opt/api_project_python/addCallQueue.pl', "get_calls"], stdout=subprocess.PIPE)
calls = str(p.stdout.read())
calls = calls.split("'")
response1 = calls
calls = calls[1].split("||")
# cancello l'ultimo item della lista poichè, risultando vuoto dopo lo split,
# genera errore "index out of range" nei successivi accessi alla lista
del calls[-1]
for call in calls:
call = call.split("|")
call_id = call[0]
status = call[1]
history = call[2]
ntel = call[3]
ackid = call[4]
call_obj = {"id": call_id, "status": status, "history": history, "called_number": ntel, "ack_id": ackid}
response["Calls"].append(call_obj)
return response


@app.get("/majortel/calls/{call_id}/", response_model=call, tags=["Majortel"])
async def majortel_calls_id_get(call_id,active_user=Depends(manager)):
p = subprocess.Popen(['perl', '/var/opt/FastAPI/addCallQueue.pl', "call_id", call_id],
stdout=subprocess.PIPE)
call = str(p.stdout.read())
call = call.split("|")
call_id = call[0].split("'")[1]
status = call[1]
# history = call[2]
ntel = call[3]
ackid = call[4]
ackid = int(ackid.split("'")[0])
response = {"id": call_id, "status": status, "called_number": ntel, "ack_id": ackid}

return response


# response_model=post_call,
@app.post("/majortel/calls", response_model=post_call, tags=["Majortel"])
async def majortel_calls_post(hw_id, ack_id, called_number, text_message="codice di riscontro ", timeout=30,
retry=1, file: UploadFile = File(None),active_user=Depends(manager)):
# controllo se l'hw_id corrisponde ai devices connessi
current_device = os.popen('asterisk -rx "dongle show device state ' + hw_id + '"').read()
current_device = current_device.split("\n")
del current_device[0]
if (current_device[0]):
curr_time = datetime.now()
call_id = str(curr_time.strftime('%y')) + str(curr_time.strftime('%m')) + str(curr_time.strftime('%d')) + str(
curr_time.strftime('%H')) + str(curr_time.strftime('%M')) + str(curr_time.strftime('%S')) + str(
curr_time.strftime('%f'))
file_path = ""
if (file):
nomefile = file.filename
extension = nomefile.split(".")[1]

if (extension == "wav"):
file_path = "/data/service/voip.majornet/ivr/" + call_id
renamed_file = file_path + ".wav"
with open(renamed_file, "wb") as f:
shutil.copyfileobj(file.file, f)
f.close()
# p = subprocess.Popen(['(cd /tmp/audioCalls;/usr/local/bin/sox_wav2gsm)'],stdout=subprocess.PIPE)
# os.popen('/usr/local/bin/sox_wav2gsm 1>/dev/null 2>/dev/null')
subprocess.Popen(
['perl', '/opt/api_project_python/addCallQueue.pl', "voicegateway", "digiovine@afasystems.it", call_id,
called_number, ack_id, text_message, "retry message here", timeout, retry, "yes", "notification_to",
"notification_bcc", "setup", file_path, "fromemailssss", hw_id], stdout=subprocess.PIPE)
response = {"id": call_id}
return response
else:
return JSONResponse(status_code=404, content={"message": "Device not found"})


@app.delete("/majortel/calls/", tags=["Majortel"],
responses={200: {"model": httpResponse200}, 400: {"model": httpResponse400},
500: {"model": httpResponse500}})
#async def majortel_calls_id_delete(call_id, current_user: User = Depends(get_current_active_user)):
async def majortel_calls_id_delete(call_id,active_user=Depends(manager)):
p = subprocess.Popen(['perl', '/opt/api_project_python/addCallQueue.pl', "delete_call", call_id],
stdout=subprocess.PIPE)
response = str(p.stdout.read())
response = response.split("'")[1]
if (response == "Success"):
return JSONResponse(status_code=200, content={"message": "Success"})
elif (response == "Not found"):
return JSONResponse(status_code=404, content={"message": "Call not found"})
else:
return JSONResponse(status_code=500, content={"message": "Server error"})





+ 9
- 4
app.py Bestand weergeven

@@ -90,9 +90,14 @@ app = FastAPI(title="MajorNet API", redoc_url=None, docs_url=None, openapi_url=
##app = FastAPI(title=PROJECT_NAME)
app.debug = True


logging.basicConfig(filename='/tmp/app.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')
logging.warning('This will /tmp/app.log')
#logging
from audit import AuditMiddleware
app.add_middleware(AuditMiddleware)
logging.basicConfig(filename='/data/var/log/FastAPI/AuthenticatedAPI.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s:%(name)s:%(message)s"
)


ALLOWED_HOSTS = ["*"]
@@ -119,7 +124,7 @@ app.include_router(user_router)
app.include_router(presence_router)
app.include_router(majornet_router)
app.include_router(contacts_router)
app.include_router(reslevis_router, prefix="/reslevis", tags=["reslevis"])
app.include_router(reslevis_router, prefix="/reslevis", tags=["Reslevis"])

@app.get("/")
async def root():


+ 129
- 0
audit.py Bestand weergeven

@@ -0,0 +1,129 @@
import json
import time
import logging
from datetime import datetime, timezone
from typing import Any, Dict, Optional

from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
from jose import jwt

from security import _get_key, KEYCLOAK_ISSUER, ALGORITHMS

audit_logger = logging.getLogger("audit")
audit_logger.setLevel(logging.INFO)


def _ts_minute_utc() -> str:
# formato: 2025-12-12 15:47 (UTC)
return datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M")


def _compact_json(obj: Any, max_len: int = 2000) -> str:
try:
s = json.dumps(obj, ensure_ascii=False, separators=(",", ":"))
except Exception:
s = str(obj)
if len(s) > max_len:
return s[:max_len] + "...(truncated)"
return s


async def _user_from_bearer(request: Request) -> Optional[str]:
auth = request.headers.get("authorization", "")
if not auth.lower().startswith("bearer "):
return None
token = auth.split(" ", 1)[1].strip()

try:
key = await _get_key(token)
claims = jwt.decode(
token,
key,
algorithms=ALGORITHMS,
issuer=KEYCLOAK_ISSUER,
options={"verify_aud": False, "verify_iss": True},
)
return (
claims.get("preferred_username")
or claims.get("username")
or claims.get("email")
)
except Exception:
return None


async def _read_request_body_if_any(request: Request) -> Optional[str]:
# logga solo metodi che tipicamente hanno body
if request.method not in ("POST", "PUT", "PATCH", "DELETE"):
return None

ctype = (request.headers.get("content-type") or "").lower()
if not ctype:
return None

# Evita file upload / form-data grossi
if "multipart/form-data" in ctype:
return "<multipart/form-data omitted>"

try:
raw = await request.body()
if not raw:
return None

# Prova JSON
if "application/json" in ctype:
try:
return _compact_json(json.loads(raw.decode("utf-8", errors="replace")))
except Exception:
# se non parseabile, logga raw truncato
txt = raw.decode("utf-8", errors="replace")
return (txt[:2000] + "...(truncated)") if len(txt) > 2000 else txt

# Testo semplice
if "text/" in ctype or "application/x-www-form-urlencoded" in ctype:
txt = raw.decode("utf-8", errors="replace")
return (txt[:2000] + "...(truncated)") if len(txt) > 2000 else txt

# Altro (binary)
return f"<body omitted content-type={ctype} bytes={len(raw)}>"
except Exception:
return "<body read error>"


class AuditMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
start = time.time()

method = request.method
path = request.url.path

# 1) via header del proxy (preferito)
user = request.headers.get("x-authenticated-user")

# 2) fallback: decodifica bearer senza usare verify_token (evita spam del logger security)
if not user:
user = await _user_from_bearer(request) or "-"

body_str = await _read_request_body_if_any(request)

status_code = 500
try:
response = await call_next(request)
status_code = response.status_code
return response
finally:
duration_ms = int((time.time() - start) * 1000)
ts = _ts_minute_utc()

if body_str:
audit_logger.info(
"%s user=%s %s %s status=%s ms=%s body=%s",
ts, user, method, path, status_code, duration_ms, body_str
)
else:
audit_logger.info(
"%s user=%s %s %s status=%s ms=%s",
ts, user, method, path, status_code, duration_ms
)


BIN
logica_reslevis/__pycache__/alarm.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/building.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/config.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/operator.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/plan.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/subject.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/track.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/tracker.cpython-310.pyc Bestand weergeven


BIN
logica_reslevis/__pycache__/zone.cpython-310.pyc Bestand weergeven


+ 83
- 0
logica_reslevis/alarm.py Bestand weergeven

@@ -0,0 +1,83 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import AlarmItem
from .config import ALARM_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class AlarmJsonRepository:
def __init__(self, json_path: str = ALARM_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in (
"id",
"status",
"type",
"gatewayName",
"trackerName",
"subjectName",
"operatorName",
"zoneName",
"buildingName",
)
)
]
return rows

def add(self, item: AlarmItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Alarm con id '{obj_id}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: AlarmItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Alarm con id '{obj_id}' non trovato")

rows[idx] = obj
self._write_all(rows)

def remove(self, alarm_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, alarm_id)
if idx is None:
raise ValueError(f"Alarm con id '{alarm_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 73
- 0
logica_reslevis/building.py Bestand weergeven

@@ -0,0 +1,73 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import BuildingItem
from .config import BUILDING_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class BuildingJsonRepository:
def __init__(self, json_path: str = BUILDING_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in ("name", "city", "address")
)
]
return rows

def add(self, item: BuildingItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Building con id '{obj_id}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: BuildingItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Building con id '{obj_id}' non trovato")

rows[idx] = obj
self._write_all(rows)

def remove(self, building_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, building_id)
if idx is None:
raise ValueError(f"Building con id '{building_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 2
- 1
logica_reslevis/config.py Bestand weergeven

@@ -8,7 +8,8 @@ BASE_DIR = Path(__file__).resolve().parent.parent
DATA_DIR = Path(
os.getenv(
"RESLEVIS_DATA_DIR",
"/usr/local/httpd/htdocs/frontend/app_reslevis/db/reslevis"
#"/usr/local/httpd/htdocs/frontend/app_reslevis/db/reslevis"
"/data/conf/presence"
)
)



+ 73
- 0
logica_reslevis/operator.py Bestand weergeven

@@ -0,0 +1,73 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import OperatorItem
from .config import OPERATOR_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class OperatorJsonRepository:
def __init__(self, json_path: str = OPERATOR_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in ("name", "phone", "zones", "groups", "notes")
)
]
return rows

def add(self, item: OperatorItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Operator con id '{obj_id}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: OperatorItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Operator con id '{obj_id}' non trovato")

rows[idx] = obj
self._write_all(rows)

def remove(self, operator_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, operator_id)
if idx is None:
raise ValueError(f"Operator con id '{operator_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 73
- 0
logica_reslevis/plan.py Bestand weergeven

@@ -0,0 +1,73 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import PlanItem
from .config import PLAN_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class PlanJsonRepository:
def __init__(self, json_path: str = PLAN_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in ("name", "image")
)
]
return rows

def add(self, item: PlanItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Plan con id '{obj_id}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: PlanItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Plan con id '{obj_id}' non trovato")

rows[idx] = obj
self._write_all(rows)

def remove(self, plan_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, plan_id)
if idx is None:
raise ValueError(f"Plan con id '{plan_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 73
- 0
logica_reslevis/subject.py Bestand weergeven

@@ -0,0 +1,73 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import SubjectItem
from .config import SUBJECT_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class SubjectJsonRepository:
def __init__(self, json_path: str = SUBJECT_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in ("name", "role", "phone", "zones", "groups", "notes")
)
]
return rows

def add(self, item: SubjectItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Subject con id '{obj_id}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: SubjectItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Subject con id '{obj_id}' non trovato")

rows[idx] = obj
self._write_all(rows)

def remove(self, subject_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, subject_id)
if idx is None:
raise ValueError(f"Subject con id '{subject_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 82
- 0
logica_reslevis/track.py Bestand weergeven

@@ -0,0 +1,82 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import TrackItem
from .config import TRACK_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class TrackJsonRepository:
def __init__(self, json_path: str = TRACK_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in (
"id",
"status",
"type",
"gatewayName",
"trackerName",
"subjectName",
"zoneName",
"buildingName",
)
)
]
return rows

def add(self, item: TrackItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Track con id '{obj_id}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: TrackItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Track con id '{obj_id}' non trovato")

rows[idx] = obj
self._write_all(rows)

def remove(self, track_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, track_id)
if idx is None:
raise ValueError(f"Track con id '{track_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 84
- 0
logica_reslevis/tracker.py Bestand weergeven

@@ -0,0 +1,84 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import TrackerItem
from .config import TRACKER_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class TrackerJsonRepository:
def __init__(self, json_path: str = TRACKER_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in ("name", "mac", "model", "status", "position", "notes")
)
]
return rows

def add(self, item: TrackerItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))
mac = _norm_str(obj.get("mac"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Tracker con id '{obj_id}' già presente")

if mac and any(_norm_str(r.get("mac")) == mac for r in rows):
raise ValueError(f"Tracker con mac '{mac}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: TrackerItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))
mac = _norm_str(obj.get("mac"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Tracker con id '{obj_id}' non trovato")

if mac and any(
_norm_str(r.get("mac")) == mac and _norm_str(r.get("id")) != obj_id
for r in rows
):
raise ValueError(f"Tracker con mac '{mac}' già presente")

rows[idx] = obj
self._write_all(rows)

def remove(self, tracker_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, tracker_id)
if idx is None:
raise ValueError(f"Tracker con id '{tracker_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 73
- 0
logica_reslevis/zone.py Bestand weergeven

@@ -0,0 +1,73 @@
import json
from typing import List, Dict, Any, Optional

from fastapi.encoders import jsonable_encoder

from schemas.reslevis import ZoneItem
from .config import ZONE_JSON_PATH
from .gateway import _LockedFile, _atomic_write, _norm_str, _index_by_id


class ZoneJsonRepository:
def __init__(self, json_path: str = ZONE_JSON_PATH):
self.path = json_path

def _read_all(self) -> List[Dict[str, Any]]:
with _LockedFile(self.path, "r") as fp:
try:
fp.seek(0)
data = fp.read().strip()
return json.loads(data) if data else []
except json.JSONDecodeError:
return []

def _write_all(self, rows: List[Dict[str, Any]]) -> None:
payload = json.dumps(rows, ensure_ascii=False, indent=2)
_atomic_write(self.path, payload)

def list(self, search_string: Optional[str] = None) -> List[Dict[str, Any]]:
rows = self._read_all()
if search_string:
s = search_string.lower()
rows = [
r
for r in rows
if any(
isinstance(r.get(k), str) and s in (r.get(k) or "").lower()
for k in ("name", "groups")
)
]
return rows

def add(self, item: ZoneItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

if any(_norm_str(r.get("id")) == obj_id for r in rows):
raise ValueError(f"Zone con id '{obj_id}' già presente")

rows.append(obj)
self._write_all(rows)

def update(self, item: ZoneItem) -> None:
rows = self._read_all()
obj = jsonable_encoder(item)
obj_id = _norm_str(obj.get("id"))

idx = _index_by_id(rows, obj_id)
if idx is None:
raise ValueError(f"Zone con id '{obj_id}' non trovato")

rows[idx] = obj
self._write_all(rows)

def remove(self, zone_id: str) -> None:
rows = self._read_all()
idx = _index_by_id(rows, zone_id)
if idx is None:
raise ValueError(f"Zone con id '{zone_id}' non trovato")

del rows[idx]
self._write_all(rows)


+ 0
- 23
res-levis-api-client.old/.gitignore Bestand weergeven

@@ -1,23 +0,0 @@
__pycache__/
build/
dist/
*.egg-info/
.pytest_cache/

# pyenv
.python-version

# Environments
.env
.venv

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# JetBrains
.idea/

/coverage.xml
/.coverage

+ 0
- 124
res-levis-api-client.old/README.md Bestand weergeven

@@ -1,124 +0,0 @@
# res-levis-api-client
A client library for accessing RES LEVIS API

## Usage
First, create a client:

```python
from res_levis_api_client import Client

client = Client(base_url="https://api.example.com")
```

If the endpoints you're going to hit require authentication, use `AuthenticatedClient` instead:

```python
from res_levis_api_client import AuthenticatedClient

client = AuthenticatedClient(base_url="https://api.example.com", token="SuperSecretToken")
```

Now call your endpoint and use your models:

```python
from res_levis_api_client.models import MyDataModel
from res_levis_api_client.api.my_tag import get_my_data_model
from res_levis_api_client.types import Response

with client as client:
my_data: MyDataModel = get_my_data_model.sync(client=client)
# or if you need more info (e.g. status_code)
response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client)
```

Or do the same thing with an async version:

```python
from res_levis_api_client.models import MyDataModel
from res_levis_api_client.api.my_tag import get_my_data_model
from res_levis_api_client.types import Response

async with client as client:
my_data: MyDataModel = await get_my_data_model.asyncio(client=client)
response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client)
```

By default, when you're calling an HTTPS API it will attempt to verify that SSL is working correctly. Using certificate verification is highly recommended most of the time, but sometimes you may need to authenticate to a server (especially an internal server) using a custom certificate bundle.

```python
client = AuthenticatedClient(
base_url="https://internal_api.example.com",
token="SuperSecretToken",
verify_ssl="/path/to/certificate_bundle.pem",
)
```

You can also disable certificate validation altogether, but beware that **this is a security risk**.

```python
client = AuthenticatedClient(
base_url="https://internal_api.example.com",
token="SuperSecretToken",
verify_ssl=False
)
```

Things to know:
1. Every path/method combo becomes a Python module with four functions:
1. `sync`: Blocking request that returns parsed data (if successful) or `None`
1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful.
1. `asyncio`: Like `sync` but async instead of blocking
1. `asyncio_detailed`: Like `sync_detailed` but async instead of blocking

1. All path/query params, and bodies become method arguments.
1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above)
1. Any endpoint which did not have a tag will be in `res_levis_api_client.api.default`

## Advanced customizations

There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx.Client` or `httpx.AsyncClient` (depending on your use-case):

```python
from res_levis_api_client import Client

def log_request(request):
print(f"Request event hook: {request.method} {request.url} - Waiting for response")

def log_response(response):
request = response.request
print(f"Response event hook: {request.method} {request.url} - Status {response.status_code}")

client = Client(
base_url="https://api.example.com",
httpx_args={"event_hooks": {"request": [log_request], "response": [log_response]}},
)

# Or get the underlying httpx client to modify directly with client.get_httpx_client() or client.get_async_httpx_client()
```

You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url):

```python
import httpx
from res_levis_api_client import Client

client = Client(
base_url="https://api.example.com",
)
# Note that base_url needs to be re-set, as would any shared cookies, headers, etc.
client.set_httpx_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030"))
```

## Building / publishing this package
This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics:
1. Update the metadata in pyproject.toml (e.g. authors, version)
1. If you're using a private repository, configure it with Poetry
1. `poetry config repositories.<your-repository-name> <url-to-your-repository>`
1. `poetry config http-basic.<your-repository-name> <username> <password>`
1. Publish the client with `poetry publish --build -r <your-repository-name>` or, if for public PyPI, just `poetry publish --build`

If you want to install this client into another project without publishing it (e.g. for development) then:
1. If that project **is using Poetry**, you can simply do `poetry add <path-to-this-client>` from that project
1. If that project is not using Poetry:
1. Build a wheel with `poetry build -f wheel`
1. Install that wheel from the other project `pip install <path-to-wheel>`

+ 0
- 26
res-levis-api-client.old/pyproject.toml Bestand weergeven

@@ -1,26 +0,0 @@
[tool.poetry]
name = "res-levis-api-client"
version = "1.0.2"
description = "A client library for accessing RES LEVIS API"
authors = []
readme = "README.md"
packages = [
{ include = "res_levis_api_client" },
]
include = ["CHANGELOG.md", "res_levis_api_client/py.typed"]

[tool.poetry.dependencies]
python = "^3.9"
httpx = ">=0.23.0,<0.29.0"
attrs = ">=22.2.0"
python-dateutil = "^2.8.0"

[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.ruff]
line-length = 120

[tool.ruff.lint]
select = ["F", "I", "UP"]

+ 0
- 8
res-levis-api-client.old/res_levis_api_client/__init__.py Bestand weergeven

@@ -1,8 +0,0 @@
"""A client library for accessing RES LEVIS API"""

from .client import AuthenticatedClient, Client

__all__ = (
"AuthenticatedClient",
"Client",
)

+ 0
- 1
res-levis-api-client.old/res_levis_api_client/api/__init__.py Bestand weergeven

@@ -1 +0,0 @@
"""Contains methods for accessing the API"""

+ 0
- 1
res-levis-api-client.old/res_levis_api_client/api/developers/__init__.py Bestand weergeven

@@ -1 +0,0 @@
"""Contains endpoint functions for accessing the API"""

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_alarms.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.alarm_item import AlarmItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getAlarms",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["AlarmItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = AlarmItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["AlarmItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["AlarmItem"]]]:
"""Get the alarms

Get the alarms

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['AlarmItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["AlarmItem"]]]:
"""Get the alarms

Get the alarms

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['AlarmItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["AlarmItem"]]]:
"""Get the alarms

Get the alarms

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['AlarmItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["AlarmItem"]]]:
"""Get the alarms

Get the alarms

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['AlarmItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 204
res-levis-api-client.old/res_levis_api_client/api/developers/get_buildings.py Bestand weergeven

@@ -1,204 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.building_item import BuildingItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getBuildings",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["BuildingItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = BuildingItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["BuildingItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["BuildingItem"]]]:
"""Get the buildings

Get the buildings

Args:
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['BuildingItem']]]
"""

kwargs = _get_kwargs(
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["BuildingItem"]]]:
"""Get the buildings

Get the buildings

Args:
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['BuildingItem']]
"""

return sync_detailed(
client=client,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["BuildingItem"]]]:
"""Get the buildings

Get the buildings

Args:
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['BuildingItem']]]
"""

kwargs = _get_kwargs(
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["BuildingItem"]]]:
"""Get the buildings

Get the buildings

Args:
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['BuildingItem']]
"""

return (
await asyncio_detailed(
client=client,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_gateways.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.gateway_item import GatewayItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getGateways",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["GatewayItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = GatewayItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["GatewayItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["GatewayItem"]]]:
"""Get the gateways

Get the gateways

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['GatewayItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["GatewayItem"]]]:
"""Get the gateways

Get the gateways

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['GatewayItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["GatewayItem"]]]:
"""Get the gateways

Get the gateways

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['GatewayItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["GatewayItem"]]]:
"""Get the gateways

Get the gateways

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['GatewayItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_operators.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.operator_item import OperatorItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getOperators",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["OperatorItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = OperatorItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["OperatorItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["OperatorItem"]]]:
"""Get the operators

Get the operators

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['OperatorItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["OperatorItem"]]]:
"""Get the operators

Get the operators

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['OperatorItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["OperatorItem"]]]:
"""Get the operators

Get the operators

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['OperatorItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["OperatorItem"]]]:
"""Get the operators

Get the operators

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['OperatorItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_plans.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.plan_item import PlanItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getPlans",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["PlanItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = PlanItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["PlanItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["PlanItem"]]]:
"""Get the plans

Get the plans

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['PlanItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["PlanItem"]]]:
"""Get the plans

Get the plans

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['PlanItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["PlanItem"]]]:
"""Get the plans

Get the plans

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['PlanItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["PlanItem"]]]:
"""Get the plans

Get the plans

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['PlanItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_subjects.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.subject_item import SubjectItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getSubjects",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["SubjectItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = SubjectItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["SubjectItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["SubjectItem"]]]:
"""Get the subjects

Get the subjects

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['SubjectItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["SubjectItem"]]]:
"""Get the subjects

Get the subjects

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['SubjectItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["SubjectItem"]]]:
"""Get the subjects

Get the subjects

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['SubjectItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["SubjectItem"]]]:
"""Get the subjects

Get the subjects

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['SubjectItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_trackers.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.tracker_item import TrackerItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getTrackers",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["TrackerItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = TrackerItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["TrackerItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["TrackerItem"]]]:
"""Get the trackers

Get the trackers

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['TrackerItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["TrackerItem"]]]:
"""Get the trackers

Get the trackers

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['TrackerItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["TrackerItem"]]]:
"""Get the trackers

Get the trackers

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['TrackerItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["TrackerItem"]]]:
"""Get the trackers

Get the trackers

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['TrackerItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_tracks.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.track_item import TrackItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getTracks",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["TrackItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = TrackItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["TrackItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["TrackItem"]]]:
"""Get the tracks

Get the tracks

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['TrackItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["TrackItem"]]]:
"""Get the tracks

Get the tracks

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['TrackItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["TrackItem"]]]:
"""Get the tracks

Get the tracks

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['TrackItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["TrackItem"]]]:
"""Get the tracks

Get the tracks

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['TrackItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 219
res-levis-api-client.old/res_levis_api_client/api/developers/get_zones.py Bestand weergeven

@@ -1,219 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union, cast

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.zone_item import ZoneItem
from ...types import UNSET, Response, Unset


def _get_kwargs(
*,
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["building"] = building

params["searchString"] = search_string

params["skip"] = skip

params["limit"] = limit

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/getZones",
"params": params,
}

return _kwargs


def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[Union[Any, list["ZoneItem"]]]:
if response.status_code == 200:
response_200 = []
_response_200 = response.json()
for response_200_item_data in _response_200:
response_200_item = ZoneItem.from_dict(response_200_item_data)

response_200.append(response_200_item)

return response_200
if response.status_code == 400:
response_400 = cast(Any, None)
return response_400
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[Union[Any, list["ZoneItem"]]]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["ZoneItem"]]]:
"""Get the zones

Get the zones

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['ZoneItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


def sync(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["ZoneItem"]]]:
"""Get the zones

Get the zones

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['ZoneItem']]
"""

return sync_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
).parsed


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Response[Union[Any, list["ZoneItem"]]]:
"""Get the zones

Get the zones

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Union[Any, list['ZoneItem']]]
"""

kwargs = _get_kwargs(
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)


async def asyncio(
*,
client: Union[AuthenticatedClient, Client],
building: Union[Unset, str] = UNSET,
search_string: Union[Unset, str] = UNSET,
skip: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
) -> Optional[Union[Any, list["ZoneItem"]]]:
"""Get the zones

Get the zones

Args:
building (Union[Unset, str]):
search_string (Union[Unset, str]):
skip (Union[Unset, int]):
limit (Union[Unset, int]):

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Union[Any, list['ZoneItem']]
"""

return (
await asyncio_detailed(
client=client,
building=building,
search_string=search_string,
skip=skip,
limit=limit,
)
).parsed

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_alarm.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.alarm_item import AlarmItem
from ...types import Response


def _get_kwargs(
*,
body: AlarmItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postAlarm",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: AlarmItem,
) -> Response[Any]:
"""Post an alarm

Post an alarm

Args:
body (AlarmItem): Alarm triggered if a monitored subject is lost or out of their zone

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: AlarmItem,
) -> Response[Any]:
"""Post an alarm

Post an alarm

Args:
body (AlarmItem): Alarm triggered if a monitored subject is lost or out of their zone

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_building.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.building_item import BuildingItem
from ...types import Response


def _get_kwargs(
*,
body: BuildingItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postBuilding",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: BuildingItem,
) -> Response[Any]:
"""Post a building item

Post a building

Args:
body (BuildingItem): A building or an area that groups together several plan

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: BuildingItem,
) -> Response[Any]:
"""Post a building item

Post a building

Args:
body (BuildingItem): A building or an area that groups together several plan

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_gateway.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.gateway_item import GatewayItem
from ...types import Response


def _get_kwargs(
*,
body: GatewayItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postGateway",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: GatewayItem,
) -> Response[Any]:
"""Post a gateway item

Post a gateway item

Args:
body (GatewayItem): A gateway of the system

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: GatewayItem,
) -> Response[Any]:
"""Post a gateway item

Post a gateway item

Args:
body (GatewayItem): A gateway of the system

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_operator.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.operator_item import OperatorItem
from ...types import Response


def _get_kwargs(
*,
body: OperatorItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postOperator",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: OperatorItem,
) -> Response[Any]:
"""Post an operator item

Post an operator item

Args:
body (OperatorItem): An operator who monitors the subjects

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: OperatorItem,
) -> Response[Any]:
"""Post an operator item

Post an operator item

Args:
body (OperatorItem): An operator who monitors the subjects

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_plan.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.plan_item import PlanItem
from ...types import Response


def _get_kwargs(
*,
body: PlanItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postPlan",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: PlanItem,
) -> Response[Any]:
"""Post a plan item

Post a plan

Args:
body (PlanItem): A plan is floor or an external space of a building

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: PlanItem,
) -> Response[Any]:
"""Post a plan item

Post a plan

Args:
body (PlanItem): A plan is floor or an external space of a building

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_subject.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.subject_item import SubjectItem
from ...types import Response


def _get_kwargs(
*,
body: SubjectItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postSubject",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: SubjectItem,
) -> Response[Any]:
"""Post a subject item

Post a subject

Args:
body (SubjectItem): Person or object monitored by the operators

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: SubjectItem,
) -> Response[Any]:
"""Post a subject item

Post a subject

Args:
body (SubjectItem): Person or object monitored by the operators

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_track.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.track_item import TrackItem
from ...types import Response


def _get_kwargs(
*,
body: TrackItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postTrack",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: TrackItem,
) -> Response[Any]:
"""Post a track

Post a track

Args:
body (TrackItem): Log of a state change of a tracker with respect to a gateway

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: TrackItem,
) -> Response[Any]:
"""Post a track

Post a track

Args:
body (TrackItem): Log of a state change of a tracker with respect to a gateway

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_tracker.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.tracker_item import TrackerItem
from ...types import Response


def _get_kwargs(
*,
body: TrackerItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postTracker",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: TrackerItem,
) -> Response[Any]:
"""Post a tracker item

Post a tracker item

Args:
body (TrackerItem): A tracker of the system

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: TrackerItem,
) -> Response[Any]:
"""Post a tracker item

Post a tracker item

Args:
body (TrackerItem): A tracker of the system

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 110
res-levis-api-client.old/res_levis_api_client/api/developers/post_zone.py Bestand weergeven

@@ -1,110 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union

import httpx

from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.zone_item import ZoneItem
from ...types import Response


def _get_kwargs(
*,
body: ZoneItem,
) -> dict[str, Any]:
headers: dict[str, Any] = {}

_kwargs: dict[str, Any] = {
"method": "post",
"url": "/postZone",
}

_kwargs["json"] = body.to_dict()

headers["Content-Type"] = "application/json"

_kwargs["headers"] = headers
return _kwargs


def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Any]:
if response.status_code == 201:
return None
if response.status_code == 400:
return None
if response.status_code == 409:
return None
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None


def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Any]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)


def sync_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: ZoneItem,
) -> Response[Any]:
"""Post a zone item

Post a zone item

Args:
body (ZoneItem): A zone is a room or a sub-area of a plan

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = client.get_httpx_client().request(
**kwargs,
)

return _build_response(client=client, response=response)


async def asyncio_detailed(
*,
client: Union[AuthenticatedClient, Client],
body: ZoneItem,
) -> Response[Any]:
"""Post a zone item

Post a zone item

Args:
body (ZoneItem): A zone is a room or a sub-area of a plan

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.

Returns:
Response[Any]
"""

kwargs = _get_kwargs(
body=body,
)

response = await client.get_async_httpx_client().request(**kwargs)

return _build_response(client=client, response=response)

+ 0
- 268
res-levis-api-client.old/res_levis_api_client/client.py Bestand weergeven

@@ -1,268 +0,0 @@
import ssl
from typing import Any, Optional, Union

import httpx
from attrs import define, evolve, field


@define
class Client:
"""A class for keeping track of data related to the API

The following are accepted as keyword arguments and will be used to construct httpx Clients internally:

``base_url``: The base URL for the API, all requests are made to a relative path to this URL

``cookies``: A dictionary of cookies to be sent with every request

``headers``: A dictionary of headers to be sent with every request

``timeout``: The maximum amount of a time a request can take. API functions will raise
httpx.TimeoutException if this is exceeded.

``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
but can be set to False for testing purposes.

``follow_redirects``: Whether or not to follow redirects. Default value is False.

``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.


Attributes:
raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
argument to the constructor.
"""

raise_on_unexpected_status: bool = field(default=False, kw_only=True)
_base_url: str = field(alias="base_url")
_cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
_headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
_timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout")
_verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl")
_follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
_httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
_client: Optional[httpx.Client] = field(default=None, init=False)
_async_client: Optional[httpx.AsyncClient] = field(default=None, init=False)

def with_headers(self, headers: dict[str, str]) -> "Client":
"""Get a new client matching this one with additional headers"""
if self._client is not None:
self._client.headers.update(headers)
if self._async_client is not None:
self._async_client.headers.update(headers)
return evolve(self, headers={**self._headers, **headers})

def with_cookies(self, cookies: dict[str, str]) -> "Client":
"""Get a new client matching this one with additional cookies"""
if self._client is not None:
self._client.cookies.update(cookies)
if self._async_client is not None:
self._async_client.cookies.update(cookies)
return evolve(self, cookies={**self._cookies, **cookies})

def with_timeout(self, timeout: httpx.Timeout) -> "Client":
"""Get a new client matching this one with a new timeout (in seconds)"""
if self._client is not None:
self._client.timeout = timeout
if self._async_client is not None:
self._async_client.timeout = timeout
return evolve(self, timeout=timeout)

def set_httpx_client(self, client: httpx.Client) -> "Client":
"""Manually set the underlying httpx.Client

**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
"""
self._client = client
return self

def get_httpx_client(self) -> httpx.Client:
"""Get the underlying httpx.Client, constructing a new one if not previously set"""
if self._client is None:
self._client = httpx.Client(
base_url=self._base_url,
cookies=self._cookies,
headers=self._headers,
timeout=self._timeout,
verify=self._verify_ssl,
follow_redirects=self._follow_redirects,
**self._httpx_args,
)
return self._client

def __enter__(self) -> "Client":
"""Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
self.get_httpx_client().__enter__()
return self

def __exit__(self, *args: Any, **kwargs: Any) -> None:
"""Exit a context manager for internal httpx.Client (see httpx docs)"""
self.get_httpx_client().__exit__(*args, **kwargs)

def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "Client":
"""Manually the underlying httpx.AsyncClient

**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
"""
self._async_client = async_client
return self

def get_async_httpx_client(self) -> httpx.AsyncClient:
"""Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
if self._async_client is None:
self._async_client = httpx.AsyncClient(
base_url=self._base_url,
cookies=self._cookies,
headers=self._headers,
timeout=self._timeout,
verify=self._verify_ssl,
follow_redirects=self._follow_redirects,
**self._httpx_args,
)
return self._async_client

async def __aenter__(self) -> "Client":
"""Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
await self.get_async_httpx_client().__aenter__()
return self

async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
"""Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
await self.get_async_httpx_client().__aexit__(*args, **kwargs)


@define
class AuthenticatedClient:
"""A Client which has been authenticated for use on secured endpoints

The following are accepted as keyword arguments and will be used to construct httpx Clients internally:

``base_url``: The base URL for the API, all requests are made to a relative path to this URL

``cookies``: A dictionary of cookies to be sent with every request

``headers``: A dictionary of headers to be sent with every request

``timeout``: The maximum amount of a time a request can take. API functions will raise
httpx.TimeoutException if this is exceeded.

``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
but can be set to False for testing purposes.

``follow_redirects``: Whether or not to follow redirects. Default value is False.

``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.


Attributes:
raise_on_unexpected_status: Whether or not to raise an errors.UnexpectedStatus if the API returns a
status code that was not documented in the source OpenAPI document. Can also be provided as a keyword
argument to the constructor.
token: The token to use for authentication
prefix: The prefix to use for the Authorization header
auth_header_name: The name of the Authorization header
"""

raise_on_unexpected_status: bool = field(default=False, kw_only=True)
_base_url: str = field(alias="base_url")
_cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
_headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
_timeout: Optional[httpx.Timeout] = field(default=None, kw_only=True, alias="timeout")
_verify_ssl: Union[str, bool, ssl.SSLContext] = field(default=True, kw_only=True, alias="verify_ssl")
_follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
_httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
_client: Optional[httpx.Client] = field(default=None, init=False)
_async_client: Optional[httpx.AsyncClient] = field(default=None, init=False)

token: str
prefix: str = "Bearer"
auth_header_name: str = "Authorization"

def with_headers(self, headers: dict[str, str]) -> "AuthenticatedClient":
"""Get a new client matching this one with additional headers"""
if self._client is not None:
self._client.headers.update(headers)
if self._async_client is not None:
self._async_client.headers.update(headers)
return evolve(self, headers={**self._headers, **headers})

def with_cookies(self, cookies: dict[str, str]) -> "AuthenticatedClient":
"""Get a new client matching this one with additional cookies"""
if self._client is not None:
self._client.cookies.update(cookies)
if self._async_client is not None:
self._async_client.cookies.update(cookies)
return evolve(self, cookies={**self._cookies, **cookies})

def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient":
"""Get a new client matching this one with a new timeout (in seconds)"""
if self._client is not None:
self._client.timeout = timeout
if self._async_client is not None:
self._async_client.timeout = timeout
return evolve(self, timeout=timeout)

def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClient":
"""Manually set the underlying httpx.Client

**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
"""
self._client = client
return self

def get_httpx_client(self) -> httpx.Client:
"""Get the underlying httpx.Client, constructing a new one if not previously set"""
if self._client is None:
self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
self._client = httpx.Client(
base_url=self._base_url,
cookies=self._cookies,
headers=self._headers,
timeout=self._timeout,
verify=self._verify_ssl,
follow_redirects=self._follow_redirects,
**self._httpx_args,
)
return self._client

def __enter__(self) -> "AuthenticatedClient":
"""Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
self.get_httpx_client().__enter__()
return self

def __exit__(self, *args: Any, **kwargs: Any) -> None:
"""Exit a context manager for internal httpx.Client (see httpx docs)"""
self.get_httpx_client().__exit__(*args, **kwargs)

def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "AuthenticatedClient":
"""Manually the underlying httpx.AsyncClient

**NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
"""
self._async_client = async_client
return self

def get_async_httpx_client(self) -> httpx.AsyncClient:
"""Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
if self._async_client is None:
self._headers[self.auth_header_name] = f"{self.prefix} {self.token}" if self.prefix else self.token
self._async_client = httpx.AsyncClient(
base_url=self._base_url,
cookies=self._cookies,
headers=self._headers,
timeout=self._timeout,
verify=self._verify_ssl,
follow_redirects=self._follow_redirects,
**self._httpx_args,
)
return self._async_client

async def __aenter__(self) -> "AuthenticatedClient":
"""Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
await self.get_async_httpx_client().__aenter__()
return self

async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
"""Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
await self.get_async_httpx_client().__aexit__(*args, **kwargs)

+ 0
- 16
res-levis-api-client.old/res_levis_api_client/errors.py Bestand weergeven

@@ -1,16 +0,0 @@
"""Contains shared errors types that can be raised from API functions"""


class UnexpectedStatus(Exception):
"""Raised by api functions when the response status an undocumented status and Client.raise_on_unexpected_status is True"""

def __init__(self, status_code: int, content: bytes):
self.status_code = status_code
self.content = content

super().__init__(
f"Unexpected status code: {status_code}\n\nResponse content:\n{content.decode(errors='ignore')}"
)


__all__ = ["UnexpectedStatus"]

+ 0
- 23
res-levis-api-client.old/res_levis_api_client/models/__init__.py Bestand weergeven

@@ -1,23 +0,0 @@
"""Contains all the data models used in inputs/outputs"""

from .alarm_item import AlarmItem
from .building_item import BuildingItem
from .gateway_item import GatewayItem
from .operator_item import OperatorItem
from .plan_item import PlanItem
from .subject_item import SubjectItem
from .track_item import TrackItem
from .tracker_item import TrackerItem
from .zone_item import ZoneItem

__all__ = (
"AlarmItem",
"BuildingItem",
"GatewayItem",
"OperatorItem",
"PlanItem",
"SubjectItem",
"TrackerItem",
"TrackItem",
"ZoneItem",
)

+ 0
- 231
res-levis-api-client.old/res_levis_api_client/models/alarm_item.py Bestand weergeven

@@ -1,231 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="AlarmItem")


@_attrs_define
class AlarmItem:
"""Alarm triggered if a monitored subject is lost or out of their zone

Attributes:
id (str):
timestamp (Union[Unset, str]):
type_ (Union[Unset, str]):
status (Union[Unset, str]):
gateway (Union[Unset, UUID]):
gateway_mac (Union[Unset, str]):
tracker (Union[Unset, UUID]):
tracker_bid (Union[Unset, str]):
subject (Union[Unset, UUID]):
subject_name (Union[Unset, str]):
operator (Union[Unset, UUID]):
operator_name (Union[Unset, str]):
zone (Union[Unset, UUID]):
zone_name (Union[Unset, str]):
building (Union[Unset, UUID]):
"""

id: str
timestamp: Union[Unset, str] = UNSET
type_: Union[Unset, str] = UNSET
status: Union[Unset, str] = UNSET
gateway: Union[Unset, UUID] = UNSET
gateway_mac: Union[Unset, str] = UNSET
tracker: Union[Unset, UUID] = UNSET
tracker_bid: Union[Unset, str] = UNSET
subject: Union[Unset, UUID] = UNSET
subject_name: Union[Unset, str] = UNSET
operator: Union[Unset, UUID] = UNSET
operator_name: Union[Unset, str] = UNSET
zone: Union[Unset, UUID] = UNSET
zone_name: Union[Unset, str] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = self.id

timestamp = self.timestamp

type_ = self.type_

status = self.status

gateway: Union[Unset, str] = UNSET
if not isinstance(self.gateway, Unset):
gateway = str(self.gateway)

gateway_mac = self.gateway_mac

tracker: Union[Unset, str] = UNSET
if not isinstance(self.tracker, Unset):
tracker = str(self.tracker)

tracker_bid = self.tracker_bid

subject: Union[Unset, str] = UNSET
if not isinstance(self.subject, Unset):
subject = str(self.subject)

subject_name = self.subject_name

operator: Union[Unset, str] = UNSET
if not isinstance(self.operator, Unset):
operator = str(self.operator)

operator_name = self.operator_name

zone: Union[Unset, str] = UNSET
if not isinstance(self.zone, Unset):
zone = str(self.zone)

zone_name = self.zone_name

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
}
)
if timestamp is not UNSET:
field_dict["timestamp"] = timestamp
if type_ is not UNSET:
field_dict["type"] = type_
if status is not UNSET:
field_dict["status"] = status
if gateway is not UNSET:
field_dict["gateway"] = gateway
if gateway_mac is not UNSET:
field_dict["gatewayMac"] = gateway_mac
if tracker is not UNSET:
field_dict["tracker"] = tracker
if tracker_bid is not UNSET:
field_dict["trackerBid"] = tracker_bid
if subject is not UNSET:
field_dict["subject"] = subject
if subject_name is not UNSET:
field_dict["subjectName"] = subject_name
if operator is not UNSET:
field_dict["operator"] = operator
if operator_name is not UNSET:
field_dict["operatorName"] = operator_name
if zone is not UNSET:
field_dict["zone"] = zone
if zone_name is not UNSET:
field_dict["zoneName"] = zone_name
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = d.pop("id")

timestamp = d.pop("timestamp", UNSET)

type_ = d.pop("type", UNSET)

status = d.pop("status", UNSET)

_gateway = d.pop("gateway", UNSET)
gateway: Union[Unset, UUID]
if isinstance(_gateway, Unset):
gateway = UNSET
else:
gateway = UUID(_gateway)

gateway_mac = d.pop("gatewayMac", UNSET)

_tracker = d.pop("tracker", UNSET)
tracker: Union[Unset, UUID]
if isinstance(_tracker, Unset):
tracker = UNSET
else:
tracker = UUID(_tracker)

tracker_bid = d.pop("trackerBid", UNSET)

_subject = d.pop("subject", UNSET)
subject: Union[Unset, UUID]
if isinstance(_subject, Unset):
subject = UNSET
else:
subject = UUID(_subject)

subject_name = d.pop("subjectName", UNSET)

_operator = d.pop("operator", UNSET)
operator: Union[Unset, UUID]
if isinstance(_operator, Unset):
operator = UNSET
else:
operator = UUID(_operator)

operator_name = d.pop("operatorName", UNSET)

_zone = d.pop("zone", UNSET)
zone: Union[Unset, UUID]
if isinstance(_zone, Unset):
zone = UNSET
else:
zone = UUID(_zone)

zone_name = d.pop("zoneName", UNSET)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

alarm_item = cls(
id=id,
timestamp=timestamp,
type_=type_,
status=status,
gateway=gateway,
gateway_mac=gateway_mac,
tracker=tracker,
tracker_bid=tracker_bid,
subject=subject,
subject_name=subject_name,
operator=operator,
operator_name=operator_name,
zone=zone,
zone_name=zone_name,
building=building,
)

alarm_item.additional_properties = d
return alarm_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 107
res-levis-api-client.old/res_levis_api_client/models/building_item.py Bestand weergeven

@@ -1,107 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="BuildingItem")


@_attrs_define
class BuildingItem:
"""A building or an area that groups together several plan

Attributes:
id (UUID):
name (str): Example: Hospital.
city (Union[Unset, str]):
address (Union[Unset, str]):
latitude (Union[Unset, float]):
longitude (Union[Unset, float]):
"""

id: UUID
name: str
city: Union[Unset, str] = UNSET
address: Union[Unset, str] = UNSET
latitude: Union[Unset, float] = UNSET
longitude: Union[Unset, float] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = str(self.id)

name = self.name

city = self.city

address = self.address

latitude = self.latitude

longitude = self.longitude

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
"name": name,
}
)
if city is not UNSET:
field_dict["city"] = city
if address is not UNSET:
field_dict["address"] = address
if latitude is not UNSET:
field_dict["latitude"] = latitude
if longitude is not UNSET:
field_dict["longitude"] = longitude

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = UUID(d.pop("id"))

name = d.pop("name")

city = d.pop("city", UNSET)

address = d.pop("address", UNSET)

latitude = d.pop("latitude", UNSET)

longitude = d.pop("longitude", UNSET)

building_item = cls(
id=id,
name=name,
city=city,
address=address,
latitude=latitude,
longitude=longitude,
)

building_item.additional_properties = d
return building_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 175
res-levis-api-client.old/res_levis_api_client/models/gateway_item.py Bestand weergeven

@@ -1,175 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="GatewayItem")


@_attrs_define
class GatewayItem:
"""A gateway of the system

Attributes:
id (UUID):
name (str):
mac (Union[Unset, str]):
status (Union[Unset, str]):
model (Union[Unset, str]):
ip (Union[Unset, str]):
position (Union[Unset, str]):
x (Union[Unset, float]):
y (Union[Unset, float]):
notes (Union[Unset, str]):
zone (Union[Unset, UUID]):
building (Union[Unset, UUID]):
"""

id: UUID
name: str
mac: Union[Unset, str] = UNSET
status: Union[Unset, str] = UNSET
model: Union[Unset, str] = UNSET
ip: Union[Unset, str] = UNSET
position: Union[Unset, str] = UNSET
x: Union[Unset, float] = UNSET
y: Union[Unset, float] = UNSET
notes: Union[Unset, str] = UNSET
zone: Union[Unset, UUID] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = str(self.id)

name = self.name

mac = self.mac

status = self.status

model = self.model

ip = self.ip

position = self.position

x = self.x

y = self.y

notes = self.notes

zone: Union[Unset, str] = UNSET
if not isinstance(self.zone, Unset):
zone = str(self.zone)

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
"name": name,
}
)
if mac is not UNSET:
field_dict["mac"] = mac
if status is not UNSET:
field_dict["status"] = status
if model is not UNSET:
field_dict["model"] = model
if ip is not UNSET:
field_dict["ip"] = ip
if position is not UNSET:
field_dict["position"] = position
if x is not UNSET:
field_dict["x"] = x
if y is not UNSET:
field_dict["y"] = y
if notes is not UNSET:
field_dict["notes"] = notes
if zone is not UNSET:
field_dict["zone"] = zone
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = UUID(d.pop("id"))

name = d.pop("name")

mac = d.pop("mac", UNSET)

status = d.pop("status", UNSET)

model = d.pop("model", UNSET)

ip = d.pop("ip", UNSET)

position = d.pop("position", UNSET)

x = d.pop("x", UNSET)

y = d.pop("y", UNSET)

notes = d.pop("notes", UNSET)

_zone = d.pop("zone", UNSET)
zone: Union[Unset, UUID]
if isinstance(_zone, Unset):
zone = UNSET
else:
zone = UUID(_zone)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

gateway_item = cls(
id=id,
name=name,
mac=mac,
status=status,
model=model,
ip=ip,
position=position,
x=x,
y=y,
notes=notes,
zone=zone,
building=building,
)

gateway_item.additional_properties = d
return gateway_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 123
res-levis-api-client.old/res_levis_api_client/models/operator_item.py Bestand weergeven

@@ -1,123 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="OperatorItem")


@_attrs_define
class OperatorItem:
"""An operator who monitors the subjects

Attributes:
id (str):
name (str):
phone (Union[Unset, str]):
zones (Union[Unset, str]):
groups (Union[Unset, str]):
notes (Union[Unset, str]):
building (Union[Unset, UUID]):
"""

id: str
name: str
phone: Union[Unset, str] = UNSET
zones: Union[Unset, str] = UNSET
groups: Union[Unset, str] = UNSET
notes: Union[Unset, str] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = self.id

name = self.name

phone = self.phone

zones = self.zones

groups = self.groups

notes = self.notes

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
"name": name,
}
)
if phone is not UNSET:
field_dict["phone"] = phone
if zones is not UNSET:
field_dict["zones"] = zones
if groups is not UNSET:
field_dict["groups"] = groups
if notes is not UNSET:
field_dict["notes"] = notes
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = d.pop("id")

name = d.pop("name")

phone = d.pop("phone", UNSET)

zones = d.pop("zones", UNSET)

groups = d.pop("groups", UNSET)

notes = d.pop("notes", UNSET)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

operator_item = cls(
id=id,
name=name,
phone=phone,
zones=zones,
groups=groups,
notes=notes,
building=building,
)

operator_item.additional_properties = d
return operator_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 105
res-levis-api-client.old/res_levis_api_client/models/plan_item.py Bestand weergeven

@@ -1,105 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="PlanItem")


@_attrs_define
class PlanItem:
"""A plan is floor or an external space of a building

Attributes:
id (UUID):
name (str): Example: Building 1 - Floor 1.
image (Union[Unset, str]): Example: The URL of the image.
scale (Union[Unset, float]): Example: 1.
building (Union[Unset, UUID]):
"""

id: UUID
name: str
image: Union[Unset, str] = UNSET
scale: Union[Unset, float] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = str(self.id)

name = self.name

image = self.image

scale = self.scale

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
"name": name,
}
)
if image is not UNSET:
field_dict["image"] = image
if scale is not UNSET:
field_dict["scale"] = scale
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = UUID(d.pop("id"))

name = d.pop("name")

image = d.pop("image", UNSET)

scale = d.pop("scale", UNSET)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

plan_item = cls(
id=id,
name=name,
image=image,
scale=scale,
building=building,
)

plan_item.additional_properties = d
return plan_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 132
res-levis-api-client.old/res_levis_api_client/models/subject_item.py Bestand weergeven

@@ -1,132 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="SubjectItem")


@_attrs_define
class SubjectItem:
"""Person or object monitored by the operators

Attributes:
id (str):
name (str):
role (Union[Unset, str]):
phone (Union[Unset, str]):
zones (Union[Unset, str]):
groups (Union[Unset, str]):
notes (Union[Unset, str]):
building (Union[Unset, UUID]):
"""

id: str
name: str
role: Union[Unset, str] = UNSET
phone: Union[Unset, str] = UNSET
zones: Union[Unset, str] = UNSET
groups: Union[Unset, str] = UNSET
notes: Union[Unset, str] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = self.id

name = self.name

role = self.role

phone = self.phone

zones = self.zones

groups = self.groups

notes = self.notes

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
"name": name,
}
)
if role is not UNSET:
field_dict["role"] = role
if phone is not UNSET:
field_dict["phone"] = phone
if zones is not UNSET:
field_dict["zones"] = zones
if groups is not UNSET:
field_dict["groups"] = groups
if notes is not UNSET:
field_dict["notes"] = notes
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = d.pop("id")

name = d.pop("name")

role = d.pop("role", UNSET)

phone = d.pop("phone", UNSET)

zones = d.pop("zones", UNSET)

groups = d.pop("groups", UNSET)

notes = d.pop("notes", UNSET)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

subject_item = cls(
id=id,
name=name,
role=role,
phone=phone,
zones=zones,
groups=groups,
notes=notes,
building=building,
)

subject_item.additional_properties = d
return subject_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 201
res-levis-api-client.old/res_levis_api_client/models/track_item.py Bestand weergeven

@@ -1,201 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="TrackItem")


@_attrs_define
class TrackItem:
"""Log of a state change of a tracker with respect to a gateway

Attributes:
id (str):
timestamp (Union[Unset, str]):
type_ (Union[Unset, str]):
status (Union[Unset, str]):
gateway (Union[Unset, UUID]):
gateway_mac (Union[Unset, str]):
tracker (Union[Unset, UUID]):
tracker_mac (Union[Unset, str]):
subject (Union[Unset, str]):
subject_name (Union[Unset, str]):
zone (Union[Unset, str]):
zone_name (Union[Unset, str]):
signal (Union[Unset, float]):
building (Union[Unset, UUID]):
"""

id: str
timestamp: Union[Unset, str] = UNSET
type_: Union[Unset, str] = UNSET
status: Union[Unset, str] = UNSET
gateway: Union[Unset, UUID] = UNSET
gateway_mac: Union[Unset, str] = UNSET
tracker: Union[Unset, UUID] = UNSET
tracker_mac: Union[Unset, str] = UNSET
subject: Union[Unset, str] = UNSET
subject_name: Union[Unset, str] = UNSET
zone: Union[Unset, str] = UNSET
zone_name: Union[Unset, str] = UNSET
signal: Union[Unset, float] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = self.id

timestamp = self.timestamp

type_ = self.type_

status = self.status

gateway: Union[Unset, str] = UNSET
if not isinstance(self.gateway, Unset):
gateway = str(self.gateway)

gateway_mac = self.gateway_mac

tracker: Union[Unset, str] = UNSET
if not isinstance(self.tracker, Unset):
tracker = str(self.tracker)

tracker_mac = self.tracker_mac

subject = self.subject

subject_name = self.subject_name

zone = self.zone

zone_name = self.zone_name

signal = self.signal

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
}
)
if timestamp is not UNSET:
field_dict["timestamp"] = timestamp
if type_ is not UNSET:
field_dict["type"] = type_
if status is not UNSET:
field_dict["status"] = status
if gateway is not UNSET:
field_dict["gateway"] = gateway
if gateway_mac is not UNSET:
field_dict["gatewayMac"] = gateway_mac
if tracker is not UNSET:
field_dict["tracker"] = tracker
if tracker_mac is not UNSET:
field_dict["trackerMac"] = tracker_mac
if subject is not UNSET:
field_dict["subject"] = subject
if subject_name is not UNSET:
field_dict["subjectName"] = subject_name
if zone is not UNSET:
field_dict["zone"] = zone
if zone_name is not UNSET:
field_dict["zoneName"] = zone_name
if signal is not UNSET:
field_dict["signal"] = signal
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = d.pop("id")

timestamp = d.pop("timestamp", UNSET)

type_ = d.pop("type", UNSET)

status = d.pop("status", UNSET)

_gateway = d.pop("gateway", UNSET)
gateway: Union[Unset, UUID]
if isinstance(_gateway, Unset):
gateway = UNSET
else:
gateway = UUID(_gateway)

gateway_mac = d.pop("gatewayMac", UNSET)

_tracker = d.pop("tracker", UNSET)
tracker: Union[Unset, UUID]
if isinstance(_tracker, Unset):
tracker = UNSET
else:
tracker = UUID(_tracker)

tracker_mac = d.pop("trackerMac", UNSET)

subject = d.pop("subject", UNSET)

subject_name = d.pop("subjectName", UNSET)

zone = d.pop("zone", UNSET)

zone_name = d.pop("zoneName", UNSET)

signal = d.pop("signal", UNSET)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

track_item = cls(
id=id,
timestamp=timestamp,
type_=type_,
status=status,
gateway=gateway,
gateway_mac=gateway_mac,
tracker=tracker,
tracker_mac=tracker_mac,
subject=subject,
subject_name=subject_name,
zone=zone,
zone_name=zone_name,
signal=signal,
building=building,
)

track_item.additional_properties = d
return track_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 166
res-levis-api-client.old/res_levis_api_client/models/tracker_item.py Bestand weergeven

@@ -1,166 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="TrackerItem")


@_attrs_define
class TrackerItem:
"""A tracker of the system

Attributes:
id (UUID):
name (str):
mac (Union[Unset, str]):
status (Union[Unset, str]):
model (Union[Unset, str]):
position (Union[Unset, str]):
notes (Union[Unset, str]):
x (Union[Unset, float]):
y (Union[Unset, float]):
zone (Union[Unset, UUID]):
building (Union[Unset, UUID]):
"""

id: UUID
name: str
mac: Union[Unset, str] = UNSET
status: Union[Unset, str] = UNSET
model: Union[Unset, str] = UNSET
position: Union[Unset, str] = UNSET
notes: Union[Unset, str] = UNSET
x: Union[Unset, float] = UNSET
y: Union[Unset, float] = UNSET
zone: Union[Unset, UUID] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = str(self.id)

name = self.name

mac = self.mac

status = self.status

model = self.model

position = self.position

notes = self.notes

x = self.x

y = self.y

zone: Union[Unset, str] = UNSET
if not isinstance(self.zone, Unset):
zone = str(self.zone)

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
"name": name,
}
)
if mac is not UNSET:
field_dict["mac"] = mac
if status is not UNSET:
field_dict["status"] = status
if model is not UNSET:
field_dict["model"] = model
if position is not UNSET:
field_dict["position"] = position
if notes is not UNSET:
field_dict["notes"] = notes
if x is not UNSET:
field_dict["x"] = x
if y is not UNSET:
field_dict["y"] = y
if zone is not UNSET:
field_dict["zone"] = zone
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = UUID(d.pop("id"))

name = d.pop("name")

mac = d.pop("mac", UNSET)

status = d.pop("status", UNSET)

model = d.pop("model", UNSET)

position = d.pop("position", UNSET)

notes = d.pop("notes", UNSET)

x = d.pop("x", UNSET)

y = d.pop("y", UNSET)

_zone = d.pop("zone", UNSET)
zone: Union[Unset, UUID]
if isinstance(_zone, Unset):
zone = UNSET
else:
zone = UUID(_zone)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

tracker_item = cls(
id=id,
name=name,
mac=mac,
status=status,
model=model,
position=position,
notes=notes,
x=x,
y=y,
zone=zone,
building=building,
)

tracker_item.additional_properties = d
return tracker_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 112
res-levis-api-client.old/res_levis_api_client/models/zone_item.py Bestand weergeven

@@ -1,112 +0,0 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

T = TypeVar("T", bound="ZoneItem")


@_attrs_define
class ZoneItem:
"""A zone is a room or a sub-area of a plan

Attributes:
id (UUID):
name (str): Example: Floor 1 - Room 1.
groups (Union[Unset, str]):
plan (Union[Unset, UUID]):
building (Union[Unset, UUID]):
"""

id: UUID
name: str
groups: Union[Unset, str] = UNSET
plan: Union[Unset, UUID] = UNSET
building: Union[Unset, UUID] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

def to_dict(self) -> dict[str, Any]:
id = str(self.id)

name = self.name

groups = self.groups

plan: Union[Unset, str] = UNSET
if not isinstance(self.plan, Unset):
plan = str(self.plan)

building: Union[Unset, str] = UNSET
if not isinstance(self.building, Unset):
building = str(self.building)

field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"id": id,
"name": name,
}
)
if groups is not UNSET:
field_dict["groups"] = groups
if plan is not UNSET:
field_dict["plan"] = plan
if building is not UNSET:
field_dict["building"] = building

return field_dict

@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
id = UUID(d.pop("id"))

name = d.pop("name")

groups = d.pop("groups", UNSET)

_plan = d.pop("plan", UNSET)
plan: Union[Unset, UUID]
if isinstance(_plan, Unset):
plan = UNSET
else:
plan = UUID(_plan)

_building = d.pop("building", UNSET)
building: Union[Unset, UUID]
if isinstance(_building, Unset):
building = UNSET
else:
building = UUID(_building)

zone_item = cls(
id=id,
name=name,
groups=groups,
plan=plan,
building=building,
)

zone_item.additional_properties = d
return zone_item

@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())

def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]

def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value

def __delitem__(self, key: str) -> None:
del self.additional_properties[key]

def __contains__(self, key: str) -> bool:
return key in self.additional_properties

+ 0
- 1
res-levis-api-client.old/res_levis_api_client/py.typed Bestand weergeven

@@ -1 +0,0 @@
# Marker file for PEP 561

+ 0
- 54
res-levis-api-client.old/res_levis_api_client/types.py Bestand weergeven

@@ -1,54 +0,0 @@
"""Contains some shared types for properties"""

from collections.abc import Mapping, MutableMapping
from http import HTTPStatus
from typing import IO, BinaryIO, Generic, Literal, Optional, TypeVar, Union

from attrs import define


class Unset:
def __bool__(self) -> Literal[False]:
return False


UNSET: Unset = Unset()

# The types that `httpx.Client(files=)` can accept, copied from that library.
FileContent = Union[IO[bytes], bytes, str]
FileTypes = Union[
# (filename, file (or bytes), content_type)
tuple[Optional[str], FileContent, Optional[str]],
# (filename, file (or bytes), content_type, headers)
tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]],
]
RequestFiles = list[tuple[str, FileTypes]]


@define
class File:
"""Contains information for file uploads"""

payload: BinaryIO
file_name: Optional[str] = None
mime_type: Optional[str] = None

def to_tuple(self) -> FileTypes:
"""Return a tuple representation that httpx will accept for multipart/form-data"""
return self.file_name, self.payload, self.mime_type


T = TypeVar("T")


@define
class Response(Generic[T]):
"""A response from an endpoint"""

status_code: HTTPStatus
content: bytes
headers: MutableMapping[str, str]
parsed: Optional[T]


__all__ = ["UNSET", "File", "FileTypes", "RequestFiles", "Response", "Unset"]

BIN
routes/__pycache__/reslevis.cpython-310.pyc Bestand weergeven


+ 523
- 52
routes/reslevis.py Bestand weergeven

@@ -1,56 +1,59 @@
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, Depends, HTTPException
from typing import List

from schemas.reslevis import (
BuildingItem, PlanItem, ZoneItem, GatewayItem, TrackerItem,
OperatorItem, SubjectItem, AlarmItem, TrackItem
BuildingItem,
PlanItem,
ZoneItem,
GatewayItem,
TrackerItem,
OperatorItem,
SubjectItem,
AlarmItem,
TrackItem,
)

from logica_reslevis.gateway import GatewayJsonRepository
from logica_reslevis.building import BuildingJsonRepository
from logica_reslevis.plan import PlanJsonRepository
from logica_reslevis.zone import ZoneJsonRepository
from logica_reslevis.tracker import TrackerJsonRepository
from logica_reslevis.operator import OperatorJsonRepository
from logica_reslevis.subject import SubjectJsonRepository
from logica_reslevis.alarm import AlarmJsonRepository
from logica_reslevis.track import TrackJsonRepository

from security import get_current_user

gateway_repo = GatewayJsonRepository()
router = APIRouter()

@router.get("/getBuildings", response_model=List[BuildingItem], tags=["Reslevis"])
def getBuildings():
return []

@router.get("/getPlans", response_model=List[PlanItem], tags=["Reslevis"])
def getPlans():
return []
gateway_repo = GatewayJsonRepository()
building_repo = BuildingJsonRepository()
plan_repo = PlanJsonRepository()
zone_repo = ZoneJsonRepository()
tracker_repo = TrackerJsonRepository()
operator_repo = OperatorJsonRepository()
subject_repo = SubjectJsonRepository()
alarm_repo = AlarmJsonRepository()
track_repo = TrackJsonRepository()

@router.get("/getZones", response_model=List[ZoneItem], tags=["Reslevis"])
def getZones():
return []

@router.get("/getGateways", response_model=List[GatewayItem], tags=["Reslevis"], dependencies=[Depends(get_current_user)])
@router.get(
"/getGateways",
response_model=List[GatewayItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getGateway",
)
def getGateways():
return gateway_repo.list()

@router.get("/getTrackers", response_model=List[TrackerItem], tags=["Reslevis"], dependencies=[Depends(get_current_user)])
def getTrackers():
return []

@router.get("/getOperators", response_model=List[OperatorItem], tags=["Reslevis"], dependencies=[Depends(get_current_user)])
def getOperators():
return []

@router.get("/getSubjects", response_model=List[SubjectItem], tags=["Reslevis"], dependencies=[Depends(get_current_user)])
def getSubjects():
return []

@router.get("/getAlarms", response_model=List[AlarmItem], tags=["Reslevis"], dependencies=[Depends(get_current_user)])
def getAlarms():
return []

@router.get("/getTracks", response_model=List[TrackItem], tags=["Reslevis"], dependencies=[Depends(get_current_user)])
def getTracks():
return []

@router.post(
"/postGateway",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)]
dependencies=[Depends(get_current_user)],
summary="postGateway",
)
def postGateway(item: GatewayItem):
try:
@@ -61,10 +64,12 @@ def postGateway(item: GatewayItem):
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.put(
"/updateGateway",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)]
dependencies=[Depends(get_current_user)],
summary="putGateway",
)
def updateGateway(item: GatewayItem):
try:
@@ -78,10 +83,12 @@ def updateGateway(item: GatewayItem):
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removeGateway/{gateway_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)]
dependencies=[Depends(get_current_user)],
summary="removeGateway",
)
def removeGateway(gateway_id: str):
try:
@@ -92,35 +99,499 @@ def removeGateway(gateway_id: str):
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")

@router.post("/postBuilding", tags=["Reslevis"], dependencies=[Depends(get_current_user)])

@router.get(
"/getBuildings",
response_model=List[BuildingItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getBuilding",
)
def getBuildings():
return building_repo.list()


@router.post(
"/postBuilding",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postBuilding",
)
def postBuilding(item: BuildingItem):
return {"message": "OK"}
try:
building_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.post("/postPlan", tags=["Reslevis"], dependencies=[Depends(get_current_user)])
@router.put(
"/updateBuilding",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putBuilding",
)
def updateBuilding(item: BuildingItem):
try:
building_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removeBuilding/{building_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removeBuilding",
)
def removeBuilding(building_id: str):
try:
building_repo.remove(building_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.get(
"/getPlans",
response_model=List[PlanItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getPlan",
)
def getPlans():
return plan_repo.list()


@router.post(
"/postPlan",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postPlan",
)
def postPlan(item: PlanItem):
return {"message": "OK"}
try:
plan_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.put(
"/updatePlan",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putPlan",
)
def updatePlan(item: PlanItem):
try:
plan_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removePlan/{plan_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removePlan",
)
def removePlan(plan_id: str):
try:
plan_repo.remove(plan_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.get(
"/getZones",
response_model=List[ZoneItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getZone",
)
def getZones():
return zone_repo.list()


@router.post("/postZone", tags=["Reslevis"], dependencies=[Depends(get_current_user)])
@router.post(
"/postZone",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postZone",
)
def postZone(item: ZoneItem):
return {"message": "OK"}
try:
zone_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.post("/postTracker", tags=["Reslevis"], dependencies=[Depends(get_current_user)])
@router.put(
"/updateZone",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putZone",
)
def updateZone(item: ZoneItem):
try:
zone_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removeZone/{zone_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removeZone",
)
def removeZone(zone_id: str):
try:
zone_repo.remove(zone_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.get(
"/getTrackers",
response_model=List[TrackerItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getTracker",
)
def getTrackers():
return tracker_repo.list()


@router.post(
"/postTracker",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postTracker",
)
def postTracker(item: TrackerItem):
try:
tracker_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.put(
"/updateTracker",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putTracker",
)
def updateTracker(item: TrackerItem):
try:
tracker_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removeTracker/{tracker_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removeTracker",
)
def removeTracker(tracker_id: str):
try:
tracker_repo.remove(tracker_id)
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")
return {"message": "OK"}

@router.post("/postOperator", tags=["Reslevis"], dependencies=[Depends(get_current_user)])

@router.get(
"/getOperators",
response_model=List[OperatorItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getOperator",
)
def getOperators():
return operator_repo.list()


@router.post(
"/postOperator",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postOperator",
)
def postOperator(item: OperatorItem):
return {"message": "OK"}
try:
operator_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.put(
"/updateOperator",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putOperator",
)
def updateOperator(item: OperatorItem):
try:
operator_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")

@router.post("/postSubject", tags=["Reslevis"], dependencies=[Depends(get_current_user)])

@router.delete(
"/removeOperator/{operator_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removeOperator",
)
def removeOperator(operator_id: str):
try:
operator_repo.remove(operator_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.get(
"/getSubjects",
response_model=List[SubjectItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getSubject",
)
def getSubjects():
return subject_repo.list()


@router.post(
"/postSubject",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postSubject",
)
def postSubject(item: SubjectItem):
return {"message": "OK"}
try:
subject_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")

@router.post("/postAlarm", tags=["Reslevis"], dependencies=[Depends(get_current_user)])

@router.put(
"/updateSubject",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putSubject",
)
def updateSubject(item: SubjectItem):
try:
subject_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removeSubject/{subject_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removeSubject",
)
def removeSubject(subject_id: str):
try:
subject_repo.remove(subject_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.get(
"/getAlarms",
response_model=List[AlarmItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getAlarm",
)
def getAlarms():
return alarm_repo.list()


@router.post(
"/postAlarm",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postAlarm",
)
def postAlarm(item: AlarmItem):
return {"message": "OK"}
try:
alarm_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.put(
"/updateAlarm",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putAlarm",
)
def updateAlarm(item: AlarmItem):
try:
alarm_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removeAlarm/{alarm_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removeAlarm",
)
def removeAlarm(alarm_id: str):
try:
alarm_repo.remove(alarm_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.post("/postTrack", tags=["Reslevis"], dependencies=[Depends(get_current_user)])
@router.get(
"/getTracks",
response_model=List[TrackItem],
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="getTrack",
)
def getTracks():
return track_repo.list()


@router.post(
"/postTrack",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="postTrack",
)
def postTrack(item: TrackItem):
return {"message": "OK"}
try:
track_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.put(
"/updateTrack",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="putTrack",
)
def updateTrack(item: TrackItem):
try:
track_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.delete(
"/removeTrack/{track_id}",
tags=["Reslevis"],
dependencies=[Depends(get_current_user)],
summary="removeTrack",
)
def removeTrack(track_id: str):
try:
track_repo.remove(track_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


+ 0
- 116
routes/reslevis.py.ori Bestand weergeven

@@ -1,116 +0,0 @@
from fastapi import APIRouter
from typing import List
from ..schemas.reslevis import (
BuildingItem, PlanItem, ZoneItem, GatewayItem, TrackerItem,
OperatorItem, SubjectItem, AlarmItem, TrackItem
)
from ..logica_reslevis.gateway import GatewayJsonRepository
from ..schemas.reslevis import GatewayItem

from fastapi import HTTPException

gateway_repo = GatewayJsonRepository()
router = APIRouter()

@router.get("/getBuildings", response_model=List[BuildingItem])
def getBuildings():
return []

@router.post("/postBuilding")
def postBuilding(item: BuildingItem):
return {"message": "OK"}

@router.get("/getPlans", response_model=List[PlanItem])
def getPlans():
return []

@router.post("/postPlan")
def postPlan(item: PlanItem):
return {"message": "OK"}

@router.get("/getZones", response_model=List[ZoneItem])
def getZones():
return []

@router.post("/postZone")
def postZone(item: ZoneItem):
return {"message": "OK"}

@router.get("/getGateways", response_model=List[GatewayItem])
def getGateways():
return gateway_repo.list()

@router.post("/postGateway")
def postGateway(item: GatewayItem):
try:
gateway_repo.add(item)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")

@router.put("/updateGateway")
def updateGateway(item: GatewayItem):
try:
gateway_repo.update(item)
return {"message": "OK"}
except ValueError as e:
msg = str(e)
if "non trovato" in msg:
raise HTTPException(status_code=404, detail=msg)
raise HTTPException(status_code=409, detail=msg)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")

@router.delete("/removeGateway/{gateway_id}")
def removeGateway(gateway_id: str):
try:
gateway_repo.remove(gateway_id)
return {"message": "OK"}
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=f"Errore interno: {e}")


@router.get("/getTrackers", response_model=List[TrackerItem])
def getTrackers():
return []

@router.post("/postTracker")
def postTracker(item: TrackerItem):
return {"message": "OK"}

@router.get("/getOperators", response_model=List[OperatorItem])
def getOperators():
return []

@router.post("/postOperator")
def postOperator(item: OperatorItem):
return {"message": "OK"}

@router.get("/getSubjects", response_model=List[SubjectItem])
def getSubjects():
return []

@router.post("/postSubject")
def postSubject(item: SubjectItem):
return {"message": "OK"}

@router.get("/getAlarms", response_model=List[AlarmItem])
def getAlarms():
return []

@router.post("/postAlarm")
def postAlarm(item: AlarmItem):
return {"message": "OK"}

@router.get("/getTracks", response_model=List[TrackItem])
def getTracks():
return []

@router.post("/postTrack")
def postTrack(item: TrackItem):
return {"message": "OK"}


BIN
schemas/__pycache__/reslevis.cpython-310.pyc Bestand weergeven


+ 138
- 24
security.py Bestand weergeven

@@ -1,4 +1,3 @@
# security.py
from typing import Dict, Any, List, Optional
import os
import logging
@@ -7,99 +6,214 @@ import config_env
from jose import jwt, JWTError
from fastapi import HTTPException, status, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import time
from datetime import datetime, timezone
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware

logger = logging.getLogger("security")

# === CONFIG ===
#KEYCLOAK_ISSUER = os.getenv(
# "KEYCLOAK_ISSUER",
# "https://10.251.0.30:10002/realms/API.Server.local",
#"https://192.168.1.3:10002/realms/API.Server.local",
#)
#KEYCLOAK_JWKS_URL = os.getenv(
# "KEYCLOAK_JWKS_URL",
# "https://10.251.0.30:10002/realms/API.Server.local/protocol/openid-connect/certs",
#"https://192.168.1.3:10002/realms/API.Server.local/protocol/openid-connect/certs",
#)
logger.setLevel(logging.WARNING)

KEYCLOAK_ISSUER = config_env.KEYCLOAK_ISSUER
KEYCLOAK_JWKS_URL = config_env.KEYCLOAK_JWKS_URL

KEYCLOAK_AUDIENCE = os.getenv("KEYCLOAK_AUDIENCE", "Fastapi")
KEYCLOAK_AUDIENCES = [
a.strip()
for a in os.getenv("KEYCLOAK_AUDIENCE", "Fastapi").split(",")
if a.strip()
]

ALGORITHMS = ["RS256", "RS384", "RS512", "PS256", "PS384", "PS512"]

# Per test con certificato self-signed. In prod: metti verify="/path/CA.crt"
logger.info(f"KEYCLOAK_ISSUER={KEYCLOAK_ISSUER}")
logger.info(f"KEYCLOAK_JWKS_URL={KEYCLOAK_JWKS_URL}")
logger.info(f"KEYCLOAK_AUDIENCES={KEYCLOAK_AUDIENCES}")
logger.info(f"ALGORITHMS={ALGORITHMS}")

_http = httpx.AsyncClient(timeout=5.0, verify=False)

_cached_jwks: Optional[Dict[str, Any]] = None

# NON chiamarla 'security' per evitare conflitti col nome del modulo.
http_bearer = HTTPBearer(auto_error=True)


async def _get_jwks() -> Dict[str, Any]:
global _cached_jwks
if _cached_jwks is None:
logger.info(f"Fetching JWKS from: {KEYCLOAK_JWKS_URL}")
logger.info(f"_get_jwks: cache miss, fetching from {KEYCLOAK_JWKS_URL}")
resp = await _http.get(KEYCLOAK_JWKS_URL)
logger.info(f"_get_jwks: response status={resp.status_code}")
resp.raise_for_status()
_cached_jwks = resp.json()
logger.debug(f"_get_jwks: jwks keys={len(_cached_jwks.get('keys', []))}")
else:
logger.debug("_get_jwks: cache hit")
return _cached_jwks


async def _get_key(token: str) -> Dict[str, Any]:
logger.debug(f"_get_key: start, token_prefix={token[:20]}")
headers = jwt.get_unverified_header(token)
kid = headers.get("kid")
logger.debug(f"_get_key: kid={kid}")
jwks = await _get_jwks()
for key in jwks.get("keys", []):
if key.get("kid") == kid:
logger.debug("_get_key: key found in cache")
return key
# chiave ruotata? invalida la cache e riprova
global _cached_jwks
logger.info("_get_key: key not found, invalidating cache and refetching")
_cached_jwks = None
jwks = await _get_jwks()
for key in jwks.get("keys", []):
if key.get("kid") == kid:
logger.debug("_get_key: key found after cache refresh")
return key
logger.error("_get_key: signing key not found for kid")
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Signing key not found")


def _audiences_from_claims(claims: Dict[str, Any]) -> List[str]:
aud = claims.get("aud")
if isinstance(aud, str):
return [aud]
if isinstance(aud, (list, tuple, set)):
return [str(x) for x in aud]
return []


async def verify_token(token: str) -> Dict[str, Any]:
logger.info("verify_token: start")
logger.debug(f"verify_token: token_prefix={token[:30]}")
try:
key = await _get_key(token)
logger.debug(f"verify_token: using key kid={key.get('kid')}")
claims = jwt.decode(
token,
key,
algorithms=ALGORITHMS,
audience=KEYCLOAK_AUDIENCE,
issuer=KEYCLOAK_ISSUER,
options={"verify_aud": True, "verify_iss": True},
options={"verify_aud": False, "verify_iss": True},
)
logger.info("verify_token: token decoded")
logger.debug(f"verify_token: claims={claims}")
token_audiences = _audiences_from_claims(claims)
logger.info(f"verify_token: token audiences={token_audiences}")
logger.info(f"verify_token: expected audiences={KEYCLOAK_AUDIENCES}")
if KEYCLOAK_AUDIENCES:
if not any(a in token_audiences for a in KEYCLOAK_AUDIENCES):
logger.error(f"verify_token: invalid audience, token_audiences={token_audiences}")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=f"Invalid audience: {token_audiences}",
)
logger.info("verify_token: audience check passed")
return claims
except HTTPException as e:
logger.error(f"verify_token: HTTPException status={e.status_code} detail={e.detail}")
raise
except JWTError as e:
logger.error(f"verify_token: JWTError={e}")
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
except Exception as e:
logger.error(f"verify_token: unexpected error={e}")
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Token verification error")


async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(http_bearer),
) -> Dict[str, Any]:
logger.info("get_current_user: start")
logger.debug(f"get_current_user: scheme={credentials.scheme}")
token = credentials.credentials
return await verify_token(token)
logger.debug(f"get_current_user: token_prefix={token[:30]}")
claims = await verify_token(token)
logger.info("get_current_user: token verified")
return claims


def require_roles(*roles: str):
async def checker(claims: Dict[str, Any] = Depends(get_current_user)) -> Dict[str, Any]:
# ruoli realm
logger.info(f"require_roles: required_roles={roles}")
realm_roles: List[str] = (claims.get("realm_access") or {}).get("roles", []) or []
# ruoli client
client_roles: List[str] = []
for v in (claims.get("resource_access") or {}).values():
for client_id, v in (claims.get("resource_access") or {}).items():
client_roles += v.get("roles", [])
logger.debug(f"require_roles: realm_roles={realm_roles}")
logger.debug(f"require_roles: client_roles={client_roles}")
have = set(realm_roles + client_roles)
logger.info(f"require_roles: user_roles={have}")
missing = [r for r in roles if r not in have]
if missing:
logger.error(f"require_roles: missing_roles={missing}")
raise HTTPException(status_code=403, detail=f"Missing roles: {missing}")
logger.info("require_roles: role check passed")
return claims
return checker


#Logging
audit_logger = logging.getLogger("audit")
audit_logger.setLevel(logging.INFO)


def _extract_user_from_claims(claims: Dict[str, Any]) -> Dict[str, str]:
return {
"sub": str(claims.get("sub", "-")),
"username": str(
claims.get("preferred_username")
or claims.get("username")
or claims.get("email")
or "-"
),
}


class AuditMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
start = time.time()

method = request.method
path = request.url.path
query = request.url.query

# 1) prova a leggere identità "fidata" passata dal proxy (più veloce)
user = request.headers.get("x-authenticated-user")
sub = request.headers.get("x-authenticated-sub")

# 2) fallback: se non arrivano header, prova a decodificare il Bearer token
if (not user or not sub) and "authorization" in request.headers:
auth = request.headers.get("authorization", "")
if auth.lower().startswith("bearer "):
token = auth.split(" ", 1)[1].strip()
try:
claims = await verify_token(token)
ident = _extract_user_from_claims(claims)
sub = sub or ident["sub"]
user = user or ident["username"]
except Exception:
# non bloccare la request per audit; la security vera la gestiscono le Depends
user = user or "-"
sub = sub or "-"

status_code = 500
try:
response = await call_next(request)
status_code = response.status_code
return response
finally:
duration_ms = int((time.time() - start) * 1000)
ts = datetime.now(timezone.utc).isoformat()

full_path = path + (("?" + query) if query else "")
audit_logger.info(
"ts=%s user=%s sub=%s method=%s path=%s status=%s duration_ms=%s",
ts,
user or "-",
sub or "-",
method,
full_path,
status_code,
duration_ms,
)


+ 105
- 0
security.py.ok Bestand weergeven

@@ -0,0 +1,105 @@
# security.py
from typing import Dict, Any, List, Optional
import os
import logging
import httpx
import config_env
from jose import jwt, JWTError
from fastapi import HTTPException, status, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

logger = logging.getLogger("security")

# === CONFIG ===
#KEYCLOAK_ISSUER = os.getenv(
# "KEYCLOAK_ISSUER",
# "https://10.251.0.30:10002/realms/API.Server.local",
#"https://192.168.1.3:10002/realms/API.Server.local",
#)
#KEYCLOAK_JWKS_URL = os.getenv(
# "KEYCLOAK_JWKS_URL",
# "https://10.251.0.30:10002/realms/API.Server.local/protocol/openid-connect/certs",
#"https://192.168.1.3:10002/realms/API.Server.local/protocol/openid-connect/certs",
#)

KEYCLOAK_ISSUER = config_env.KEYCLOAK_ISSUER
KEYCLOAK_JWKS_URL = config_env.KEYCLOAK_JWKS_URL

KEYCLOAK_AUDIENCE = os.getenv("KEYCLOAK_AUDIENCE", "Fastapi")

ALGORITHMS = ["RS256", "RS384", "RS512", "PS256", "PS384", "PS512"]

# Per test con certificato self-signed. In prod: metti verify="/path/CA.crt"
_http = httpx.AsyncClient(timeout=5.0, verify=False)

_cached_jwks: Optional[Dict[str, Any]] = None

# NON chiamarla 'security' per evitare conflitti col nome del modulo.
http_bearer = HTTPBearer(auto_error=True)


async def _get_jwks() -> Dict[str, Any]:
global _cached_jwks
if _cached_jwks is None:
logger.info(f"Fetching JWKS from: {KEYCLOAK_JWKS_URL}")
resp = await _http.get(KEYCLOAK_JWKS_URL)
resp.raise_for_status()
_cached_jwks = resp.json()
return _cached_jwks


async def _get_key(token: str) -> Dict[str, Any]:
headers = jwt.get_unverified_header(token)
kid = headers.get("kid")
jwks = await _get_jwks()
for key in jwks.get("keys", []):
if key.get("kid") == kid:
return key
# chiave ruotata? invalida la cache e riprova
global _cached_jwks
_cached_jwks = None
jwks = await _get_jwks()
for key in jwks.get("keys", []):
if key.get("kid") == kid:
return key
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Signing key not found")


async def verify_token(token: str) -> Dict[str, Any]:
try:
key = await _get_key(token)
claims = jwt.decode(
token,
key,
algorithms=ALGORITHMS,
audience=KEYCLOAK_AUDIENCE,
issuer=KEYCLOAK_ISSUER,
options={"verify_aud": True, "verify_iss": True},
)
return claims
except JWTError as e:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))


async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(http_bearer),
) -> Dict[str, Any]:
token = credentials.credentials
return await verify_token(token)


def require_roles(*roles: str):
async def checker(claims: Dict[str, Any] = Depends(get_current_user)) -> Dict[str, Any]:
# ruoli realm
realm_roles: List[str] = (claims.get("realm_access") or {}).get("roles", []) or []
# ruoli client
client_roles: List[str] = []
for v in (claims.get("resource_access") or {}).values():
client_roles += v.get("roles", [])
have = set(realm_roles + client_roles)
missing = [r for r in roles if r not in have]
if missing:
raise HTTPException(status_code=403, detail=f"Missing roles: {missing}")
return claims
return checker


BIN
venv.tgz Bestand weergeven


Laden…
Annuleren
Opslaan