251 lines
8.0 KiB
Python
251 lines
8.0 KiB
Python
"""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)
|