Phase 17g - Double Authentification: - TOTP avec Google Authenticator/Authy - QR code pour enrôlement - Codes de backup (10 codes usage unique) - Page /admin/security pour gestion 2FA - Page /admin/users avec Reset 2FA (super_admin) - 2FA obligatoire pour rôles configurés Phase 21 - Infrastructure Management: - SQLite pour données infra (/data/infra.db) - SSH Pool avec reconnexion auto - Gestion Incus (list, start, stop, restart, sync) - Gestion Nginx (test, reload, deploy, sync, certbot) - Interface admin /admin/infra - Formulaire ajout serveur - Page détail serveur avec containers et sites Fichiers créés: - internal/infra/ (db, models, migrations, repository, ssh, incus, nginx) - cmd/sogoms/admin/totp.go - cmd/sogoms/admin/handlers_2fa.go - cmd/sogoms/admin/handlers_infra.go - Templates: 2fa_*, security, users, infra, server_* 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
160 lines
4.6 KiB
HTML
160 lines
4.6 KiB
HTML
{{define "infra.html"}}
|
|
{{template "partials/header.html" .}}
|
|
|
|
<style>
|
|
.server-card {
|
|
margin-bottom: 1rem;
|
|
}
|
|
.server-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
.server-info {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
|
gap: 0.5rem;
|
|
margin-top: 0.5rem;
|
|
font-size: 0.9rem;
|
|
}
|
|
.server-info dt {
|
|
color: var(--pico-muted-color);
|
|
font-size: 0.8rem;
|
|
}
|
|
.server-info dd {
|
|
margin: 0;
|
|
font-weight: 500;
|
|
}
|
|
.badge {
|
|
display: inline-block;
|
|
padding: 0.2rem 0.5rem;
|
|
border-radius: 4px;
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
}
|
|
.badge-online { background: #dcfce7; color: #166534; }
|
|
.badge-offline { background: #fef2f2; color: #dc2626; }
|
|
.badge-unknown { background: #f3f4f6; color: #6b7280; }
|
|
.badge-incus { background: #dbeafe; color: #1d4ed8; }
|
|
.badge-nginx { background: #fef3c7; color: #92400e; }
|
|
.stats-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
|
gap: 0.5rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
.stat-card {
|
|
background: var(--pico-card-background-color);
|
|
border: 1px solid var(--pico-muted-border-color);
|
|
border-radius: var(--pico-border-radius);
|
|
padding: 1rem;
|
|
text-align: center;
|
|
}
|
|
.stat-value {
|
|
font-size: 1.5rem;
|
|
font-weight: bold;
|
|
color: var(--pico-primary);
|
|
}
|
|
.stat-label {
|
|
font-size: 0.8rem;
|
|
color: var(--pico-muted-color);
|
|
}
|
|
</style>
|
|
|
|
<h1>Infrastructure</h1>
|
|
|
|
<p class="user-info">
|
|
Gestion des serveurs, containers Incus et configurations Nginx.
|
|
</p>
|
|
|
|
{{if eq .Flash "success"}}
|
|
<div style="background:#f0fdf4;border:1px solid #bbf7d0;color:#16a34a;padding:0.75rem 1rem;border-radius:var(--pico-border-radius);margin-bottom:1rem;">
|
|
{{.FlashMessage}}
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if eq .Flash "error"}}
|
|
<div style="background:#fef2f2;border:1px solid #fecaca;color:#dc2626;padding:0.75rem 1rem;border-radius:var(--pico-border-radius);margin-bottom:1rem;">
|
|
{{.FlashMessage}}
|
|
</div>
|
|
{{end}}
|
|
|
|
<!-- Statistiques -->
|
|
<div class="stats-grid" hx-get="/admin/api/infra/status" hx-trigger="every 30s" hx-swap="innerHTML">
|
|
{{$online := 0}}
|
|
{{$containers := 0}}
|
|
{{range .Servers}}
|
|
{{if eq .Status "online"}}{{$online = 1}}{{end}}
|
|
{{$containers = .ContainerCount}}
|
|
{{end}}
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{len .Servers}}</div>
|
|
<div class="stat-label">Serveurs</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{range .Servers}}{{.ContainerCount}}{{end}}</div>
|
|
<div class="stat-label">Containers</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{range .Servers}}{{.NginxCount}}{{end}}</div>
|
|
<div class="stat-label">Sites Nginx</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div style="margin-bottom: 1rem;">
|
|
<a href="/admin/infra/servers/new" role="button">+ Nouveau Serveur</a>
|
|
</div>
|
|
|
|
<!-- Liste des serveurs -->
|
|
{{if .Servers}}
|
|
{{range .Servers}}
|
|
<article class="server-card">
|
|
<header class="server-header">
|
|
<div>
|
|
<strong>{{.Name}}</strong>
|
|
{{if eq .Status "online"}}<span class="badge badge-online">Online</span>{{end}}
|
|
{{if eq .Status "offline"}}<span class="badge badge-offline">Offline</span>{{end}}
|
|
{{if eq .Status "unknown"}}<span class="badge badge-unknown">?</span>{{end}}
|
|
{{if .HasIncus}}<span class="badge badge-incus">Incus</span>{{end}}
|
|
{{if .HasNginx}}<span class="badge badge-nginx">Nginx</span>{{end}}
|
|
</div>
|
|
<a href="/admin/infra/servers/{{.ID}}" role="button" class="outline">Détails</a>
|
|
</header>
|
|
<dl class="server-info">
|
|
<div>
|
|
<dt>Host</dt>
|
|
<dd>{{.Host}}</dd>
|
|
</div>
|
|
{{if .VpnIP}}
|
|
<div>
|
|
<dt>VPN IP</dt>
|
|
<dd>{{.VpnIP}}</dd>
|
|
</div>
|
|
{{end}}
|
|
<div>
|
|
<dt>SSH</dt>
|
|
<dd>{{.SSHUser}}@:{{.SSHPort}}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Containers</dt>
|
|
<dd>{{.ContainerCount}}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Sites Nginx</dt>
|
|
<dd>{{.NginxCount}}</dd>
|
|
</div>
|
|
</dl>
|
|
</article>
|
|
{{end}}
|
|
{{else}}
|
|
<article>
|
|
<p style="text-align:center;color:var(--pico-muted-color);">
|
|
Aucun serveur configuré. <a href="/admin/infra/servers/new">Ajouter un serveur</a>
|
|
</p>
|
|
</article>
|
|
{{end}}
|
|
|
|
{{template "partials/footer.html" .}}
|
|
{{end}}
|