"""Gateway web routes.""" from fastapi import APIRouter, Request, Depends, Form, Response from fastapi.responses import HTMLResponse, RedirectResponse from sqlalchemy.orm import Session from ..database import get_db from ..models.user import User, UserRole from ..models.gateway import Gateway, RouterType, ProvisioningMethod from ..models.endpoint import ApplicationTemplate from ..models.tenant import Tenant from ..models.access import UserGatewayAccess from .deps import get_current_user_web, require_admin_web, flash, get_flashed_messages router = APIRouter() def get_accessible_gateways(db: Session, user: User): """Get gateways accessible by user.""" if user.role == UserRole.SUPER_ADMIN: return db.query(Gateway).all() elif user.role == UserRole.ADMIN: return db.query(Gateway).filter(Gateway.tenant_id == user.tenant_id).all() else: return db.query(Gateway).join( UserGatewayAccess, UserGatewayAccess.gateway_id == Gateway.id ).filter(UserGatewayAccess.user_id == user.id).all() @router.get("/gateways", response_class=HTMLResponse) async def list_gateways( request: Request, db: Session = Depends(get_db), current_user: User = Depends(get_current_user_web) ): """List gateways page.""" return request.app.state.templates.TemplateResponse( "gateways/list.html", { "request": request, "current_user": current_user, "flash_messages": get_flashed_messages(request) } ) @router.get("/gateways/new", response_class=HTMLResponse) async def new_gateway_form( request: Request, db: Session = Depends(get_db), current_user: User = Depends(require_admin_web) ): """New gateway form.""" tenants = db.query(Tenant).filter(Tenant.is_active == True).all() return request.app.state.templates.TemplateResponse( "gateways/form.html", { "request": request, "current_user": current_user, "gateway": None, "tenants": tenants, "flash_messages": get_flashed_messages(request) } ) @router.post("/gateways/new", response_class=HTMLResponse) async def create_gateway( request: Request, name: str = Form(...), router_type: str = Form(...), firmware_version: str = Form(None), serial_number: str = Form(None), location: str = Form(None), vpn_subnet: str = Form(None), description: str = Form(None), tenant_id: int = Form(None), db: Session = Depends(get_db), current_user: User = Depends(require_admin_web) ): """Create new gateway.""" # Determine tenant if current_user.role == UserRole.SUPER_ADMIN and tenant_id: gateway_tenant_id = tenant_id else: gateway_tenant_id = current_user.tenant_id # Generate VPN cert CN vpn_cert_cn = f"gateway-{name.lower().replace(' ', '-')}" gateway = Gateway( name=name, router_type=RouterType(router_type), firmware_version=firmware_version or None, serial_number=serial_number or None, location=location or None, vpn_subnet=vpn_subnet or None, description=description or None, tenant_id=gateway_tenant_id, vpn_cert_cn=vpn_cert_cn ) db.add(gateway) db.commit() db.refresh(gateway) flash(request, f"Gateway '{name}' erfolgreich erstellt", "success") return RedirectResponse(url=f"/gateways/{gateway.id}", status_code=303) @router.get("/gateways/{gateway_id}", response_class=HTMLResponse) async def gateway_detail( request: Request, gateway_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user_web) ): """Gateway detail page.""" gateway = db.query(Gateway).filter(Gateway.id == gateway_id).first() if not gateway: flash(request, "Gateway nicht gefunden", "danger") return RedirectResponse(url="/gateways", status_code=303) # Check access if current_user.role == UserRole.TECHNICIAN: access = db.query(UserGatewayAccess).filter( UserGatewayAccess.user_id == current_user.id, UserGatewayAccess.gateway_id == gateway_id ).first() if not access: flash(request, "Kein Zugriff auf dieses Gateway", "danger") return RedirectResponse(url="/gateways", status_code=303) templates = db.query(ApplicationTemplate).all() return request.app.state.templates.TemplateResponse( "gateways/detail.html", { "request": request, "current_user": current_user, "gateway": gateway, "templates": templates, "flash_messages": get_flashed_messages(request) } ) @router.get("/gateways/{gateway_id}/edit", response_class=HTMLResponse) async def edit_gateway_form( request: Request, gateway_id: int, db: Session = Depends(get_db), current_user: User = Depends(require_admin_web) ): """Edit gateway form.""" gateway = db.query(Gateway).filter(Gateway.id == gateway_id).first() if not gateway: flash(request, "Gateway nicht gefunden", "danger") return RedirectResponse(url="/gateways", status_code=303) tenants = db.query(Tenant).filter(Tenant.is_active == True).all() return request.app.state.templates.TemplateResponse( "gateways/form.html", { "request": request, "current_user": current_user, "gateway": gateway, "tenants": tenants, "flash_messages": get_flashed_messages(request) } ) @router.post("/gateways/{gateway_id}/edit") async def update_gateway( request: Request, gateway_id: int, name: str = Form(...), router_type: str = Form(...), firmware_version: str = Form(None), serial_number: str = Form(None), location: str = Form(None), vpn_subnet: str = Form(None), description: str = Form(None), db: Session = Depends(get_db), current_user: User = Depends(require_admin_web) ): """Update gateway.""" gateway = db.query(Gateway).filter(Gateway.id == gateway_id).first() if not gateway: flash(request, "Gateway nicht gefunden", "danger") return RedirectResponse(url="/gateways", status_code=303) gateway.name = name gateway.router_type = RouterType(router_type) gateway.firmware_version = firmware_version or None gateway.serial_number = serial_number or None gateway.location = location or None gateway.vpn_subnet = vpn_subnet or None gateway.description = description or None db.commit() flash(request, "Gateway aktualisiert", "success") return RedirectResponse(url=f"/gateways/{gateway_id}", status_code=303) @router.post("/gateways/{gateway_id}/delete") async def delete_gateway( request: Request, gateway_id: int, db: Session = Depends(get_db), current_user: User = Depends(require_admin_web) ): """Delete gateway.""" gateway = db.query(Gateway).filter(Gateway.id == gateway_id).first() if not gateway: flash(request, "Gateway nicht gefunden", "danger") return RedirectResponse(url="/gateways", status_code=303) db.delete(gateway) db.commit() flash(request, f"Gateway '{gateway.name}' gelöscht", "warning") return RedirectResponse(url="/gateways", status_code=303) @router.get("/gateways/{gateway_id}/provision") async def download_provisioning( request: Request, gateway_id: int, db: Session = Depends(get_db), current_user: User = Depends(require_admin_web) ): """Redirect to VPN profiles for provisioning. Provisioning is now done through VPN profiles. Each profile contains its own certificate and VPN server configuration. """ gateway = db.query(Gateway).filter(Gateway.id == gateway_id).first() if not gateway: flash(request, "Gateway nicht gefunden", "danger") return RedirectResponse(url="/gateways", status_code=303) # Redirect to profiles page flash(request, "Bitte erstellen Sie ein VPN-Profil für das Provisioning", "info") return RedirectResponse(url=f"/gateways/{gateway_id}/profiles", status_code=303)