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>
93 lines
3.0 KiB
Go
93 lines
3.0 KiB
Go
// Package infra gère l'infrastructure (serveurs, containers, nginx).
|
|
package infra
|
|
|
|
import "fmt"
|
|
|
|
// migrations contient les migrations SQL à exécuter dans l'ordre.
|
|
var migrations = []string{
|
|
// Table servers
|
|
`CREATE TABLE IF NOT EXISTS servers (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
host TEXT NOT NULL,
|
|
vpn_ip TEXT,
|
|
ssh_port INTEGER NOT NULL DEFAULT 22,
|
|
ssh_user TEXT NOT NULL DEFAULT 'root',
|
|
ssh_key_file TEXT NOT NULL,
|
|
has_incus INTEGER NOT NULL DEFAULT 0,
|
|
has_nginx INTEGER NOT NULL DEFAULT 0,
|
|
status TEXT NOT NULL DEFAULT 'unknown',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
)`,
|
|
|
|
// Table containers
|
|
`CREATE TABLE IF NOT EXISTS containers (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
server_id INTEGER NOT NULL,
|
|
name TEXT NOT NULL,
|
|
incus_name TEXT NOT NULL,
|
|
ip TEXT,
|
|
vpn_ip TEXT,
|
|
image TEXT,
|
|
status TEXT NOT NULL DEFAULT 'unknown',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE CASCADE,
|
|
UNIQUE(server_id, incus_name)
|
|
)`,
|
|
|
|
// Table nginx_configs
|
|
`CREATE TABLE IF NOT EXISTS nginx_configs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
server_id INTEGER NOT NULL,
|
|
domain TEXT NOT NULL,
|
|
type TEXT NOT NULL DEFAULT 'proxy',
|
|
template TEXT,
|
|
upstream TEXT,
|
|
ssl_enabled INTEGER NOT NULL DEFAULT 1,
|
|
config_content TEXT,
|
|
status TEXT NOT NULL DEFAULT 'inactive',
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE CASCADE,
|
|
UNIQUE(server_id, domain)
|
|
)`,
|
|
|
|
// Table app_bindings
|
|
`CREATE TABLE IF NOT EXISTS app_bindings (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
app_id TEXT NOT NULL,
|
|
container_id INTEGER,
|
|
nginx_config_id INTEGER,
|
|
server_id INTEGER,
|
|
type TEXT NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (container_id) REFERENCES containers(id) ON DELETE SET NULL,
|
|
FOREIGN KEY (nginx_config_id) REFERENCES nginx_configs(id) ON DELETE SET NULL,
|
|
FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE SET NULL
|
|
)`,
|
|
|
|
// Index pour accélérer les requêtes
|
|
`CREATE INDEX IF NOT EXISTS idx_containers_server ON containers(server_id)`,
|
|
`CREATE INDEX IF NOT EXISTS idx_nginx_configs_server ON nginx_configs(server_id)`,
|
|
`CREATE INDEX IF NOT EXISTS idx_nginx_configs_domain ON nginx_configs(domain)`,
|
|
`CREATE INDEX IF NOT EXISTS idx_app_bindings_app ON app_bindings(app_id)`,
|
|
|
|
// Table migrations pour tracking des versions
|
|
`CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
version INTEGER PRIMARY KEY,
|
|
applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
)`,
|
|
}
|
|
|
|
// Migrate exécute toutes les migrations.
|
|
func (db *DB) Migrate() error {
|
|
for i, migration := range migrations {
|
|
if _, err := db.Exec(migration); err != nil {
|
|
return fmt.Errorf("migration %d failed: %w", i+1, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|