""" Node router — handles /health, /api/v1/verify/{cid}, and /api/v1/node/info endpoints. """ import hashlib import json from datetime import datetime import httpx from fastapi import APIRouter from dependencies import ipfs_cat from config import IPFS_API_URL router = APIRouter() @router.get("/health") async def health_check(): """Health Check für DSMS Gateway""" try: async with httpx.AsyncClient(timeout=5.0) as client: response = await client.post(f"{IPFS_API_URL}/api/v0/id") ipfs_status = response.status_code == 200 except Exception: ipfs_status = False return { "status": "healthy" if ipfs_status else "degraded", "ipfs_connected": ipfs_status, "timestamp": datetime.utcnow().isoformat() } @router.get("/api/v1/verify/{cid}") async def verify_document(cid: str): """ Verifiziert die Integrität eines Dokuments. Öffentlich zugänglich für Audit-Zwecke. - **cid**: Content Identifier (IPFS Hash) """ try: content = await ipfs_cat(cid) package = json.loads(content) # Checksum verifizieren stored_checksum = package.get("metadata", {}).get("checksum") if "content_base64" in package: original_content = bytes.fromhex(package["content_base64"]) calculated_checksum = hashlib.sha256(original_content).hexdigest() elif "content" in package: calculated_checksum = hashlib.sha256( package["content"].encode('utf-8') ).hexdigest() else: calculated_checksum = None integrity_valid = ( stored_checksum == calculated_checksum if stored_checksum and calculated_checksum else None ) return { "cid": cid, "exists": True, "integrity_valid": integrity_valid, "metadata": package.get("metadata", {}), "stored_checksum": stored_checksum, "calculated_checksum": calculated_checksum, "verified_at": datetime.utcnow().isoformat() } except Exception as e: return { "cid": cid, "exists": False, "error": str(e), "verified_at": datetime.utcnow().isoformat() } @router.get("/api/v1/node/info") async def get_node_info(): """ Gibt Informationen über den DSMS Node zurück. """ try: async with httpx.AsyncClient(timeout=10.0) as client: # Node ID id_response = await client.post(f"{IPFS_API_URL}/api/v0/id") node_info = id_response.json() if id_response.status_code == 200 else {} # Repo Stats stat_response = await client.post(f"{IPFS_API_URL}/api/v0/repo/stat") repo_stats = stat_response.json() if stat_response.status_code == 200 else {} return { "node_id": node_info.get("ID"), "protocol_version": node_info.get("ProtocolVersion"), "agent_version": node_info.get("AgentVersion"), "repo_size": repo_stats.get("RepoSize"), "storage_max": repo_stats.get("StorageMax"), "num_objects": repo_stats.get("NumObjects"), "addresses": node_info.get("Addresses", [])[:5] # Erste 5 } except Exception as e: return {"error": str(e)}