| @@ -8,8 +8,8 @@ | |||||
| #CLINET SETTINGS | #CLINET SETTINGS | ||||
| KEYCLOAK_AUDIENCE=Fastapi | |||||
| SECRET=568bd5bcbe553e2692fc0476e4e176b4c6df57771235fbb2 | |||||
| KEYCLOAK_AUDIENCE=account,reslevis-frontend,Fastapi | |||||
| SECRET=wojuoB7Z5xhlPFrF2lIxJSSdVHCApEgC | |||||
| #KEYCLOAK URLS | #KEYCLOAK URLS | ||||
| KEYCLOAK_SERVER=https://10.251.0.30:10002 | KEYCLOAK_SERVER=https://10.251.0.30:10002 | ||||
| @@ -1 +1,4 @@ | |||||
| /code_to_inspect_and_delete/ | /code_to_inspect_and_delete/ | ||||
| venv/ | |||||
| venv.tgz | |||||
| .ev | |||||
| @@ -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"}) | |||||
| @@ -90,9 +90,14 @@ app = FastAPI(title="MajorNet API", redoc_url=None, docs_url=None, openapi_url= | |||||
| ##app = FastAPI(title=PROJECT_NAME) | ##app = FastAPI(title=PROJECT_NAME) | ||||
| app.debug = True | 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 = ["*"] | ALLOWED_HOSTS = ["*"] | ||||
| @@ -119,7 +124,7 @@ app.include_router(user_router) | |||||
| app.include_router(presence_router) | app.include_router(presence_router) | ||||
| app.include_router(majornet_router) | app.include_router(majornet_router) | ||||
| app.include_router(contacts_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("/") | @app.get("/") | ||||
| async def root(): | async def root(): | ||||
| @@ -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 | |||||
| ) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -8,7 +8,8 @@ BASE_DIR = Path(__file__).resolve().parent.parent | |||||
| DATA_DIR = Path( | DATA_DIR = Path( | ||||
| os.getenv( | os.getenv( | ||||
| "RESLEVIS_DATA_DIR", | "RESLEVIS_DATA_DIR", | ||||
| "/usr/local/httpd/htdocs/frontend/app_reslevis/db/reslevis" | |||||
| #"/usr/local/httpd/htdocs/frontend/app_reslevis/db/reslevis" | |||||
| "/data/conf/presence" | |||||
| ) | ) | ||||
| ) | ) | ||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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 | |||||
| @@ -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>` | |||||
| @@ -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"] | |||||
| @@ -1,8 +0,0 @@ | |||||
| """A client library for accessing RES LEVIS API""" | |||||
| from .client import AuthenticatedClient, Client | |||||
| __all__ = ( | |||||
| "AuthenticatedClient", | |||||
| "Client", | |||||
| ) | |||||
| @@ -1 +0,0 @@ | |||||
| """Contains methods for accessing the API""" | |||||
| @@ -1 +0,0 @@ | |||||
| """Contains endpoint functions for accessing the API""" | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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) | |||||
| @@ -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"] | |||||
| @@ -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", | |||||
| ) | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -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 | |||||
| @@ -1 +0,0 @@ | |||||
| # Marker file for PEP 561 | |||||
| @@ -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"] | |||||
| @@ -1,56 +1,59 @@ | |||||
| from fastapi import APIRouter, Depends, HTTPException, status | |||||
| from fastapi import APIRouter, Depends, HTTPException | |||||
| from typing import List | from typing import List | ||||
| from schemas.reslevis import ( | 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.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 | from security import get_current_user | ||||
| gateway_repo = GatewayJsonRepository() | |||||
| router = APIRouter() | 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(): | def getGateways(): | ||||
| return gateway_repo.list() | 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( | @router.post( | ||||
| "/postGateway", | "/postGateway", | ||||
| tags=["Reslevis"], | tags=["Reslevis"], | ||||
| dependencies=[Depends(get_current_user)] | |||||
| dependencies=[Depends(get_current_user)], | |||||
| summary="postGateway", | |||||
| ) | ) | ||||
| def postGateway(item: GatewayItem): | def postGateway(item: GatewayItem): | ||||
| try: | try: | ||||
| @@ -61,10 +64,12 @@ def postGateway(item: GatewayItem): | |||||
| except Exception as e: | except Exception as e: | ||||
| raise HTTPException(status_code=500, detail=f"Errore interno: {e}") | raise HTTPException(status_code=500, detail=f"Errore interno: {e}") | ||||
| @router.put( | @router.put( | ||||
| "/updateGateway", | "/updateGateway", | ||||
| tags=["Reslevis"], | tags=["Reslevis"], | ||||
| dependencies=[Depends(get_current_user)] | |||||
| dependencies=[Depends(get_current_user)], | |||||
| summary="putGateway", | |||||
| ) | ) | ||||
| def updateGateway(item: GatewayItem): | def updateGateway(item: GatewayItem): | ||||
| try: | try: | ||||
| @@ -78,10 +83,12 @@ def updateGateway(item: GatewayItem): | |||||
| except Exception as e: | except Exception as e: | ||||
| raise HTTPException(status_code=500, detail=f"Errore interno: {e}") | raise HTTPException(status_code=500, detail=f"Errore interno: {e}") | ||||
| @router.delete( | @router.delete( | ||||
| "/removeGateway/{gateway_id}", | "/removeGateway/{gateway_id}", | ||||
| tags=["Reslevis"], | tags=["Reslevis"], | ||||
| dependencies=[Depends(get_current_user)] | |||||
| dependencies=[Depends(get_current_user)], | |||||
| summary="removeGateway", | |||||
| ) | ) | ||||
| def removeGateway(gateway_id: str): | def removeGateway(gateway_id: str): | ||||
| try: | try: | ||||
| @@ -92,35 +99,499 @@ def removeGateway(gateway_id: str): | |||||
| except Exception as e: | except Exception as e: | ||||
| raise HTTPException(status_code=500, detail=f"Errore interno: {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): | 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): | 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): | 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): | 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"} | 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): | 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): | 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): | 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): | 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}") | |||||
| @@ -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"} | |||||
| @@ -1,4 +1,3 @@ | |||||
| # security.py | |||||
| from typing import Dict, Any, List, Optional | from typing import Dict, Any, List, Optional | ||||
| import os | import os | ||||
| import logging | import logging | ||||
| @@ -7,99 +6,214 @@ import config_env | |||||
| from jose import jwt, JWTError | from jose import jwt, JWTError | ||||
| from fastapi import HTTPException, status, Depends | from fastapi import HTTPException, status, Depends | ||||
| from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials | 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") | 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_ISSUER = config_env.KEYCLOAK_ISSUER | ||||
| KEYCLOAK_JWKS_URL = config_env.KEYCLOAK_JWKS_URL | 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"] | 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) | _http = httpx.AsyncClient(timeout=5.0, verify=False) | ||||
| _cached_jwks: Optional[Dict[str, Any]] = None | _cached_jwks: Optional[Dict[str, Any]] = None | ||||
| # NON chiamarla 'security' per evitare conflitti col nome del modulo. | |||||
| http_bearer = HTTPBearer(auto_error=True) | http_bearer = HTTPBearer(auto_error=True) | ||||
| async def _get_jwks() -> Dict[str, Any]: | async def _get_jwks() -> Dict[str, Any]: | ||||
| global _cached_jwks | global _cached_jwks | ||||
| if _cached_jwks is None: | 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) | resp = await _http.get(KEYCLOAK_JWKS_URL) | ||||
| logger.info(f"_get_jwks: response status={resp.status_code}") | |||||
| resp.raise_for_status() | resp.raise_for_status() | ||||
| _cached_jwks = resp.json() | _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 | return _cached_jwks | ||||
| async def _get_key(token: str) -> Dict[str, Any]: | 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) | headers = jwt.get_unverified_header(token) | ||||
| kid = headers.get("kid") | kid = headers.get("kid") | ||||
| logger.debug(f"_get_key: kid={kid}") | |||||
| jwks = await _get_jwks() | jwks = await _get_jwks() | ||||
| for key in jwks.get("keys", []): | for key in jwks.get("keys", []): | ||||
| if key.get("kid") == kid: | if key.get("kid") == kid: | ||||
| logger.debug("_get_key: key found in cache") | |||||
| return key | return key | ||||
| # chiave ruotata? invalida la cache e riprova | |||||
| global _cached_jwks | global _cached_jwks | ||||
| logger.info("_get_key: key not found, invalidating cache and refetching") | |||||
| _cached_jwks = None | _cached_jwks = None | ||||
| jwks = await _get_jwks() | jwks = await _get_jwks() | ||||
| for key in jwks.get("keys", []): | for key in jwks.get("keys", []): | ||||
| if key.get("kid") == kid: | if key.get("kid") == kid: | ||||
| logger.debug("_get_key: key found after cache refresh") | |||||
| return key | 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") | 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]: | async def verify_token(token: str) -> Dict[str, Any]: | ||||
| logger.info("verify_token: start") | |||||
| logger.debug(f"verify_token: token_prefix={token[:30]}") | |||||
| try: | try: | ||||
| key = await _get_key(token) | key = await _get_key(token) | ||||
| logger.debug(f"verify_token: using key kid={key.get('kid')}") | |||||
| claims = jwt.decode( | claims = jwt.decode( | ||||
| token, | token, | ||||
| key, | key, | ||||
| algorithms=ALGORITHMS, | algorithms=ALGORITHMS, | ||||
| audience=KEYCLOAK_AUDIENCE, | |||||
| issuer=KEYCLOAK_ISSUER, | 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 | return claims | ||||
| except HTTPException as e: | |||||
| logger.error(f"verify_token: HTTPException status={e.status_code} detail={e.detail}") | |||||
| raise | |||||
| except JWTError as e: | except JWTError as e: | ||||
| logger.error(f"verify_token: JWTError={e}") | |||||
| raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(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( | async def get_current_user( | ||||
| credentials: HTTPAuthorizationCredentials = Depends(http_bearer), | credentials: HTTPAuthorizationCredentials = Depends(http_bearer), | ||||
| ) -> Dict[str, Any]: | ) -> Dict[str, Any]: | ||||
| logger.info("get_current_user: start") | |||||
| logger.debug(f"get_current_user: scheme={credentials.scheme}") | |||||
| token = credentials.credentials | 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): | def require_roles(*roles: str): | ||||
| async def checker(claims: Dict[str, Any] = Depends(get_current_user)) -> Dict[str, Any]: | 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 [] | realm_roles: List[str] = (claims.get("realm_access") or {}).get("roles", []) or [] | ||||
| # ruoli client | |||||
| client_roles: List[str] = [] | 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", []) | 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) | 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] | missing = [r for r in roles if r not in have] | ||||
| if missing: | if missing: | ||||
| logger.error(f"require_roles: missing_roles={missing}") | |||||
| raise HTTPException(status_code=403, detail=f"Missing roles: {missing}") | raise HTTPException(status_code=403, detail=f"Missing roles: {missing}") | ||||
| logger.info("require_roles: role check passed") | |||||
| return claims | return claims | ||||
| return checker | 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, | |||||
| ) | |||||
| @@ -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 | |||||