190 lines
5.9 KiB
Python
190 lines
5.9 KiB
Python
from models.models import Client
|
|
# Neue Route: Liefert alle Gruppen mit zugehörigen Clients und deren Alive-Status
|
|
|
|
from server.database import Session
|
|
from models.models import ClientGroup
|
|
from flask import Blueprint, request, jsonify
|
|
from sqlalchemy import func
|
|
import sys
|
|
import os
|
|
from datetime import datetime, timedelta
|
|
|
|
sys.path.append('/workspace')
|
|
|
|
groups_bp = Blueprint("groups", __name__, url_prefix="/api/groups")
|
|
|
|
|
|
def get_grace_period():
|
|
"""Wählt die Grace-Periode abhängig von ENV."""
|
|
env = os.environ.get("ENV", "production").lower()
|
|
if env == "development" or env == "dev":
|
|
return int(os.environ.get("HEARTBEAT_GRACE_PERIOD_DEV", "15"))
|
|
return int(os.environ.get("HEARTBEAT_GRACE_PERIOD_PROD", "180"))
|
|
|
|
|
|
def is_client_alive(last_alive, is_active):
|
|
"""Berechnet, ob ein Client als alive gilt."""
|
|
if not last_alive or not is_active:
|
|
return False
|
|
grace_period = get_grace_period()
|
|
# last_alive kann ein String oder datetime sein
|
|
if isinstance(last_alive, str):
|
|
last_alive_str = last_alive[:-
|
|
1] if last_alive.endswith('Z') else last_alive
|
|
try:
|
|
last_alive_dt = datetime.fromisoformat(last_alive_str)
|
|
except Exception:
|
|
return False
|
|
else:
|
|
last_alive_dt = last_alive
|
|
return datetime.utcnow() - last_alive_dt <= timedelta(seconds=grace_period)
|
|
|
|
|
|
@groups_bp.route("", methods=["POST"])
|
|
def create_group():
|
|
data = request.get_json()
|
|
name = data.get("name")
|
|
if not name or not name.strip():
|
|
return jsonify({"error": "Gruppenname erforderlich"}), 400
|
|
|
|
session = Session()
|
|
if session.query(ClientGroup).filter_by(name=name).first():
|
|
session.close()
|
|
return jsonify({"error": "Gruppe existiert bereits"}), 409
|
|
|
|
group = ClientGroup(name=name, is_active=True)
|
|
session.add(group)
|
|
session.commit()
|
|
result = {
|
|
"id": group.id,
|
|
"name": group.name,
|
|
"created_at": group.created_at.isoformat() if group.created_at else None,
|
|
"is_active": group.is_active,
|
|
}
|
|
session.close()
|
|
return jsonify(result), 201
|
|
|
|
|
|
@groups_bp.route("", methods=["GET"])
|
|
def get_groups():
|
|
session = Session()
|
|
groups = session.query(ClientGroup).all()
|
|
result = [
|
|
{
|
|
"id": g.id,
|
|
"name": g.name,
|
|
"created_at": g.created_at.isoformat() if g.created_at else None,
|
|
"is_active": g.is_active,
|
|
}
|
|
for g in groups
|
|
]
|
|
session.close()
|
|
return jsonify(result)
|
|
|
|
|
|
@groups_bp.route("/<int:group_id>", methods=["PUT"])
|
|
def update_group(group_id):
|
|
data = request.get_json()
|
|
session = Session()
|
|
group = session.query(ClientGroup).filter_by(id=group_id).first()
|
|
if not group:
|
|
session.close()
|
|
return jsonify({"error": "Gruppe nicht gefunden"}), 404
|
|
if "name" in data:
|
|
group.name = data["name"]
|
|
if "is_active" in data:
|
|
group.is_active = bool(data["is_active"])
|
|
session.commit()
|
|
result = {
|
|
"id": group.id,
|
|
"name": group.name,
|
|
"created_at": group.created_at.isoformat() if group.created_at else None,
|
|
"is_active": group.is_active,
|
|
}
|
|
session.close()
|
|
return jsonify(result)
|
|
|
|
|
|
@groups_bp.route("/<int:group_id>", methods=["DELETE"])
|
|
def delete_group(group_id):
|
|
session = Session()
|
|
group = session.query(ClientGroup).filter_by(id=group_id).first()
|
|
if not group:
|
|
session.close()
|
|
return jsonify({"error": "Gruppe nicht gefunden"}), 404
|
|
session.delete(group)
|
|
session.commit()
|
|
session.close()
|
|
return jsonify({"success": True})
|
|
|
|
|
|
@groups_bp.route("/byname/<string:group_name>", methods=["DELETE"])
|
|
def delete_group_by_name(group_name):
|
|
session = Session()
|
|
group = session.query(ClientGroup).filter_by(name=group_name).first()
|
|
if not group:
|
|
session.close()
|
|
return jsonify({"error": "Gruppe nicht gefunden"}), 404
|
|
session.delete(group)
|
|
session.commit()
|
|
session.close()
|
|
return jsonify({"success": True})
|
|
|
|
|
|
@groups_bp.route("/byname/<string:old_name>", methods=["PUT"])
|
|
def rename_group_by_name(old_name):
|
|
data = request.get_json()
|
|
new_name = data.get("newName")
|
|
if not new_name or not new_name.strip():
|
|
return jsonify({"error": "Neuer Name erforderlich"}), 400
|
|
|
|
session = Session()
|
|
group = session.query(ClientGroup).filter_by(name=old_name).first()
|
|
if not group:
|
|
session.close()
|
|
return jsonify({"error": "Gruppe nicht gefunden"}), 404
|
|
|
|
# Prüfe, ob der neue Name schon existiert
|
|
if session.query(ClientGroup).filter(func.binary(ClientGroup.name) == new_name).first():
|
|
session.close()
|
|
return jsonify({"error": f'Gruppe mit dem Namen "{new_name}" existiert bereits', "duplicate_name": new_name}), 409
|
|
|
|
group.name = new_name
|
|
session.commit()
|
|
result = {
|
|
"id": group.id,
|
|
"name": group.name,
|
|
"created_at": group.created_at.isoformat() if group.created_at else None,
|
|
"is_active": group.is_active,
|
|
}
|
|
session.close()
|
|
return jsonify(result)
|
|
|
|
|
|
@groups_bp.route("/with_clients", methods=["GET"])
|
|
def get_groups_with_clients():
|
|
session = Session()
|
|
groups = session.query(ClientGroup).all()
|
|
result = []
|
|
for g in groups:
|
|
clients = session.query(Client).filter_by(group_id=g.id).all()
|
|
client_list = []
|
|
for c in clients:
|
|
client_list.append({
|
|
"uuid": c.uuid,
|
|
"description": c.description,
|
|
"ip": c.ip,
|
|
"last_alive": c.last_alive.isoformat() if c.last_alive else None,
|
|
"is_active": c.is_active,
|
|
"is_alive": is_client_alive(c.last_alive, c.is_active),
|
|
})
|
|
result.append({
|
|
"id": g.id,
|
|
"name": g.name,
|
|
"created_at": g.created_at.isoformat() if g.created_at else None,
|
|
"is_active": g.is_active,
|
|
"clients": client_list,
|
|
})
|
|
session.close()
|
|
return jsonify(result)
|