Phase 13 : sogoms-cron
- Jobs planifiés avec schedule cron standard
- Types: query_email, http, service
- Actions: list, trigger, status
Phase 16 : Réorganisation config/apps/{app}/
- Tous les fichiers d'une app dans un seul dossier
- Migration prokov vers nouvelle structure
Phase 17 : sogoms-admin
- Interface web d'administration (Go templates + htmx)
- Auth sessions cookies signées HMAC-SHA256
- Rôles super_admin / app_admin avec permissions
Phase 19 : Création d'app via Admin UI
- Formulaire création app avec config DB/auth
- Bouton "Scanner la base" : introspection + schema.yaml
- Rechargement automatique sogoway via SIGHUP
Infrastructure :
- sogoctl : socket de contrôle /run/sogoctl.sock
- sogoway : reload config sur SIGHUP sans restart
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
113 lines
2.9 KiB
Go
113 lines
2.9 KiB
Go
// Package admin gère la configuration et les permissions de l'interface d'administration.
|
|
package admin
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// AdminConfig représente la configuration complète de l'admin.
|
|
type AdminConfig struct {
|
|
Session SessionConfig `yaml:"session"`
|
|
RateLimit RateLimitConfig `yaml:"rate_limit"`
|
|
Users []AdminUser `yaml:"users"`
|
|
}
|
|
|
|
// SessionConfig configure les sessions.
|
|
type SessionConfig struct {
|
|
SecretFile string `yaml:"secret_file"`
|
|
MaxAge int `yaml:"max_age"` // secondes
|
|
CookieName string `yaml:"cookie_name"`
|
|
Secret string `yaml:"-"` // chargé depuis fichier
|
|
}
|
|
|
|
// RateLimitConfig configure le rate limiting.
|
|
type RateLimitConfig struct {
|
|
LoginMax int `yaml:"login_max"`
|
|
LoginWindow int `yaml:"login_window"` // secondes
|
|
}
|
|
|
|
// AdminUser représente un utilisateur admin.
|
|
type AdminUser struct {
|
|
Username string `yaml:"username"`
|
|
PasswordHash string `yaml:"password_hash"`
|
|
Role string `yaml:"role"`
|
|
Email string `yaml:"email"`
|
|
Apps []string `yaml:"apps,omitempty"` // pour app_admin
|
|
Permissions []string `yaml:"permissions,omitempty"` // pour app_admin
|
|
}
|
|
|
|
// IsSuperAdmin retourne true si l'utilisateur est super_admin.
|
|
func (u *AdminUser) IsSuperAdmin() bool {
|
|
return u.Role == "super_admin"
|
|
}
|
|
|
|
// LoadAdminConfig charge la configuration admin depuis un fichier YAML.
|
|
func LoadAdminConfig(path string) (*AdminConfig, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read admin config: %w", err)
|
|
}
|
|
|
|
var cfg AdminConfig
|
|
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
|
return nil, fmt.Errorf("parse admin config: %w", err)
|
|
}
|
|
|
|
// Valeurs par défaut
|
|
if cfg.Session.MaxAge == 0 {
|
|
cfg.Session.MaxAge = 3600 // 1 heure
|
|
}
|
|
if cfg.Session.CookieName == "" {
|
|
cfg.Session.CookieName = "sogoms_admin_sid"
|
|
}
|
|
if cfg.RateLimit.LoginMax == 0 {
|
|
cfg.RateLimit.LoginMax = 5
|
|
}
|
|
if cfg.RateLimit.LoginWindow == 0 {
|
|
cfg.RateLimit.LoginWindow = 60
|
|
}
|
|
|
|
// Charger le secret de session depuis le fichier
|
|
if cfg.Session.SecretFile != "" {
|
|
secretData, err := os.ReadFile(cfg.Session.SecretFile)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read session secret: %w", err)
|
|
}
|
|
cfg.Session.Secret = strings.TrimSpace(string(secretData))
|
|
}
|
|
|
|
// Valider
|
|
if len(cfg.Users) == 0 {
|
|
return nil, fmt.Errorf("no users defined")
|
|
}
|
|
if cfg.Session.Secret == "" {
|
|
return nil, fmt.Errorf("session secret is required")
|
|
}
|
|
|
|
return &cfg, nil
|
|
}
|
|
|
|
// GetUser retourne un utilisateur par son username.
|
|
func (cfg *AdminConfig) GetUser(username string) *AdminUser {
|
|
for i := range cfg.Users {
|
|
if cfg.Users[i].Username == username {
|
|
return &cfg.Users[i]
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetUserByEmail retourne un utilisateur par son email.
|
|
func (cfg *AdminConfig) GetUserByEmail(email string) *AdminUser {
|
|
for i := range cfg.Users {
|
|
if cfg.Users[i].Email == email {
|
|
return &cfg.Users[i]
|
|
}
|
|
}
|
|
return nil
|
|
}
|