Files
Borealis-Github-Replica/Data/Engine/interfaces/http/sites.py

113 lines
3.8 KiB
Python

from __future__ import annotations
from flask import Blueprint, Flask, current_app, jsonify, request
from Data.Engine.services.container import EngineServiceContainer
blueprint = Blueprint("engine_sites", __name__)
def register(app: Flask, _services: EngineServiceContainer) -> None:
if "engine_sites" not in app.blueprints:
app.register_blueprint(blueprint)
def _services() -> EngineServiceContainer:
services = current_app.extensions.get("engine_services")
if services is None: # pragma: no cover - defensive
raise RuntimeError("engine services not initialized")
return services
def _site_service():
return _services().site_service
@blueprint.route("/api/sites", methods=["GET"])
def list_sites() -> object:
records = _site_service().list_sites()
return jsonify({"sites": [record.to_dict() for record in records]})
@blueprint.route("/api/sites", methods=["POST"])
def create_site() -> object:
payload = request.get_json(silent=True) or {}
name = payload.get("name")
description = payload.get("description")
try:
record = _site_service().create_site(name or "", description or "")
except ValueError as exc:
if str(exc) == "missing_name":
return jsonify({"error": "name is required"}), 400
if str(exc) == "duplicate":
return jsonify({"error": "name already exists"}), 409
raise
response = jsonify(record.to_dict())
response.status_code = 201
return response
@blueprint.route("/api/sites/delete", methods=["POST"])
def delete_sites() -> object:
payload = request.get_json(silent=True) or {}
ids = payload.get("ids") or []
if not isinstance(ids, list):
return jsonify({"error": "ids must be a list"}), 400
deleted = _site_service().delete_sites(ids)
return jsonify({"status": "ok", "deleted": deleted})
@blueprint.route("/api/sites/device_map", methods=["GET"])
def sites_device_map() -> object:
host_param = (request.args.get("hostnames") or "").strip()
filter_set = []
if host_param:
for part in host_param.split(","):
normalized = part.strip()
if normalized:
filter_set.append(normalized)
mapping = _site_service().map_devices(filter_set or None)
return jsonify({"mapping": {hostname: entry.to_dict() for hostname, entry in mapping.items()}})
@blueprint.route("/api/sites/assign", methods=["POST"])
def assign_devices_to_site() -> object:
payload = request.get_json(silent=True) or {}
site_id = payload.get("site_id")
hostnames = payload.get("hostnames") or []
if not isinstance(hostnames, list):
return jsonify({"error": "hostnames must be a list of strings"}), 400
try:
_site_service().assign_devices(site_id, hostnames)
except ValueError as exc:
message = str(exc)
if message == "invalid_site_id":
return jsonify({"error": "invalid site_id"}), 400
if message == "invalid_hostnames":
return jsonify({"error": "hostnames must be a list of strings"}), 400
raise
except LookupError:
return jsonify({"error": "site not found"}), 404
return jsonify({"status": "ok"})
@blueprint.route("/api/sites/rename", methods=["POST"])
def rename_site() -> object:
payload = request.get_json(silent=True) or {}
site_id = payload.get("id")
new_name = payload.get("new_name") or ""
try:
record = _site_service().rename_site(site_id, new_name)
except ValueError as exc:
if str(exc) == "missing_name":
return jsonify({"error": "new_name is required"}), 400
if str(exc) == "duplicate":
return jsonify({"error": "name already exists"}), 409
raise
except LookupError:
return jsonify({"error": "site not found"}), 404
return jsonify(record.to_dict())
__all__ = ["register", "blueprint"]