Files
nessi ff7eff8242 feat: add public status page with component health monitoring and system metrics visualization
Add statuspage package with service, handler, and types for exposing platform health. Implement GET /api/v1/status endpoint returning operational status, component health (API, database, gateway runtime), and control plane summary counts.

Add Service.Snapshot method querying database connectivity, user/device/gateway/service/policy counts, connected device count via handshake timestamps, and gateway runtime tel
2026-03-24 18:25:55 +01:00

75 lines
2.2 KiB
Go

package app
import (
"context"
"net/http"
"github.com/jackc/pgx/v5/pgxpool"
"nexavpn/backend/internal/audit"
"nexavpn/backend/internal/auth"
"nexavpn/backend/internal/config"
"nexavpn/backend/internal/db"
"nexavpn/backend/internal/device"
"nexavpn/backend/internal/gateway"
"nexavpn/backend/internal/group"
"nexavpn/backend/internal/httpserver"
"nexavpn/backend/internal/ipam"
"nexavpn/backend/internal/policy"
"nexavpn/backend/internal/servicecatalog"
"nexavpn/backend/internal/statuspage"
"nexavpn/backend/internal/user"
)
type App struct {
DB *pgxpool.Pool
Router http.Handler
}
func New(cfg config.Config) (*App, error) {
ctx := context.Background()
pool, err := db.Connect(ctx, cfg.DatabaseURL)
if err != nil {
return nil, err
}
if err := db.EnsureSchema(ctx, pool); err != nil {
return nil, err
}
authRepo := auth.NewPGRepository(pool)
authService := auth.NewService(authRepo, cfg.JWTSecret, cfg.JWTIssuer, cfg.AccessTokenTTL, cfg.RefreshTokenTTL)
userService := user.NewService(user.NewPGRepository(pool))
groupService := group.NewService(group.NewPGRepository(pool))
serviceCatalogService := servicecatalog.NewService(servicecatalog.NewPGRepository(pool))
policyService := policy.NewService(policy.NewPGRepository(pool))
gatewayService := gateway.NewService(gateway.NewPGRepository(pool))
deviceService := device.NewService(device.NewPGRepository(pool), policyService, gatewayService, ipam.NewService())
auditService := audit.NewService(audit.NewPGRepository(pool))
statusService := statuspage.NewService(pool)
router := httpserver.NewRouter(cfg.JWTSecret, httpserver.Handlers{
Auth: auth.NewHandler(authService, auditService),
User: user.NewHandler(userService, auditService),
Device: device.NewHandler(deviceService, auditService),
Group: group.NewHandler(groupService, auditService),
Service: servicecatalog.NewHandler(serviceCatalogService),
Policy: policy.NewHandler(policyService, auditService),
Gateway: gateway.NewHandler(gatewayService, cfg.GatewayBootstrapToken),
Audit: audit.NewHandler(auditService),
Status: statuspage.NewHandler(statusService),
})
return &App{
DB: pool,
Router: router,
}, nil
}
func (a *App) Close() {
if a.DB != nil {
a.DB.Close()
}
}