feat: add api
docker-publish / publish (push) Failing after 14m14s

This commit is contained in:
Nuxgrid
2026-07-27 16:06:19 +02:00
parent 8397a4470f
commit 6b4274d12b
46 changed files with 3922 additions and 0 deletions
+167
View File
@@ -0,0 +1,167 @@
// Commande api : point d'entrée du control-plane Omnex.
package main
import (
"context"
"log"
"os"
"strings"
"github.com/google/uuid"
"github.com/redis/go-redis/v9"
"github.com/omnex/control-plane/api/internal/auth"
"github.com/omnex/control-plane/api/internal/config"
"github.com/omnex/control-plane/api/internal/db"
"github.com/omnex/control-plane/api/internal/demos"
"github.com/omnex/control-plane/api/internal/k8s"
"github.com/omnex/control-plane/api/internal/leads"
"github.com/omnex/control-plane/api/internal/router"
"github.com/omnex/control-plane/api/internal/sav"
"github.com/omnex/control-plane/api/internal/session"
"github.com/omnex/control-plane/api/internal/sub"
)
// memUsers : store utilisateurs en mémoire (fallback dev sans base).
type memUsers map[string]auth.User
func (m memUsers) ByUsername(username string) (auth.User, bool) {
u, ok := m[strings.ToLower(strings.TrimSpace(username))]
return u, ok
}
func (m memUsers) Create(username, passwordHash string, role auth.Role) (auth.User, error) {
key := strings.ToLower(strings.TrimSpace(username))
u := auth.User{ID: uuid.NewString(), Username: key, PasswordHash: passwordHash, Role: role}
m[key] = u
return u, nil
}
func main() {
cfg, err := config.Load()
if err != nil {
log.Fatalf("config: %v", err)
}
iss := auth.NewIssuer(cfg.JWTSecret, cfg.SessionTTL)
// Sessions : Redis en prod/dev configuré, mémoire en fallback dev.
var sessions session.Manager
if cfg.RedisURL != "" {
opt, err := redis.ParseURL(cfg.RedisURL)
if err != nil {
log.Fatalf("redis url: %v", err)
}
rdb := redis.NewClient(opt)
if err := rdb.Ping(context.Background()).Err(); err != nil {
log.Fatalf("redis ping: %v", err)
}
sessions = session.NewRedisManager(rdb, cfg.SessionTTL)
log.Printf("sessions: Redis")
} else {
sessions = session.NewMemManager(cfg.SessionTTL)
log.Printf("sessions: mémoire (dev — définir OMNEX_REDIS_URL pour Redis)")
}
var userStore auth.UserStore
var leadStore leads.Store
var demoStore demos.Store
var demoPool demos.Pool
var codeStore sub.Store
var contactStore sav.Store
if cfg.DatabaseURL != "" {
gdb, err := db.Open(cfg.DatabaseURL)
if err != nil {
log.Fatalf("db: %v", err)
}
if err := db.AutoMigrate(gdb); err != nil {
log.Fatalf("migrate: %v", err)
}
if err := db.SeedExternalPool(gdb); err != nil {
log.Fatalf("seed pool: %v", err)
}
users := auth.NewGormStore(gdb)
seedAdmin(users)
userStore = users
codeStore = sub.NewGormStore(gdb)
leadStore = leads.NewGormStore(gdb)
demoStore = demos.NewGormStore(gdb)
demoPool = demos.NewGormPool(gdb)
contactStore = sav.NewGormStore(gdb)
log.Printf("persistance: PostgreSQL (GORM)")
} else {
userStore = seedMemUsers()
codeStore = sub.NewMemStore()
leadStore = leads.NewMemStore()
demoStore = demos.NewMemStore()
demoPool = demos.NewMemPool()
contactStore = sav.NewMemContactStore()
log.Printf("persistance: mémoire (dev — définir OMNEX_DATABASE_URL pour PostgreSQL)")
}
// Créer le client Kubernetes
k8sClient, err := k8s.NewClient(&cfg)
if err != nil {
log.Fatalf("k8s client: %v", err)
}
helmProv, err := demos.NewHelmProvisioner(&cfg, k8sClient, "/charts", "helm")
if err != nil {
log.Fatalf("helm provisioner: %v", err)
}
// Service de démos avec le provisioner Helm
demoSvc := demos.NewService(demoStore, demoPool, helmProv, demos.Config{
BaseDomain: cfg.DemoDomain,
TTL: demos.TTL,
MaxDemos: demos.MaxConcurrentDemos,
})
deps := router.Deps{
Cfg: cfg,
Issuer: iss,
Sessions: sessions,
AuthH: auth.NewHandler(userStore, sessions, iss, cfg.Secure()),
LeadsH: leads.NewHandler(leadStore),
DemosH: demos.NewHandler(demoSvc),
SubH: sub.NewHandler(codeStore),
ContactH: sav.NewHandler(contactStore),
}
r := router.New(deps)
log.Printf("Omnex API sur %s (env=%s)", cfg.Addr, cfg.Env)
if err := r.Run(cfg.Addr); err != nil {
log.Fatal(err)
}
}
// seedAdmin crée l'utilisateur admin de départ depuis l'env (idempotent).
func seedAdmin(users *auth.GormStore) {
username, pass := os.Getenv("OMNEX_SEED_USERNAME"), os.Getenv("OMNEX_SEED_PASSWORD")
if username == "" || pass == "" {
return
}
hash, err := auth.HashPassword(pass)
if err != nil {
log.Fatalf("seed: %v", err)
}
if err := users.EnsureUser(username, hash, auth.RoleAdmin); err != nil {
log.Fatalf("seed: %v", err)
}
log.Printf("utilisateur admin seedé: %s", username)
}
// seedMemUsers construit un store mémoire depuis l'env (dev uniquement).
func seedMemUsers() memUsers {
users := memUsers{}
if username, pass := os.Getenv("OMNEX_SEED_USERNAME"), os.Getenv("OMNEX_SEED_PASSWORD"); username != "" && pass != "" {
hash, err := auth.HashPassword(pass)
if err != nil {
log.Fatalf("seed: %v", err)
}
key := strings.ToLower(strings.TrimSpace(username))
users[key] = auth.User{ID: "seed-admin", Username: key, PasswordHash: hash, Role: auth.RoleAdmin}
log.Printf("utilisateur admin seedé (mémoire): %s", key)
}
return users
}