package apitest import ( "context" "testing" "time" "github.com/omnex/control-plane/api/internal/auth" "github.com/omnex/control-plane/api/internal/session" ) func TestHashAndVerifyPassword(t *testing.T) { hash, err := auth.HashPassword("s3cret-password") if err != nil { t.Fatalf("hash: %v", err) } if hash == "s3cret-password" { t.Fatal("le mot de passe ne doit pas être stocké en clair") } ok, err := auth.VerifyPassword("s3cret-password", hash) if err != nil || !ok { t.Fatalf("verify bon mdp: ok=%v err=%v", ok, err) } if ok, _ := auth.VerifyPassword("mauvais", hash); ok { t.Fatal("un mauvais mot de passe ne doit pas passer") } } func TestHashUniqueSalt(t *testing.T) { h1, _ := auth.HashPassword("same") h2, _ := auth.HashPassword("same") if h1 == h2 { t.Fatal("deux hash du même mdp doivent différer (salt aléatoire)") } } func TestVerifyRejectsMalformed(t *testing.T) { if _, err := auth.VerifyPassword("x", "pas-un-hash"); err == nil { t.Fatal("un hash malformé doit être rejeté") } } func TestJWTIssueVerify(t *testing.T) { iss := auth.NewIssuer([]byte(testSecret), time.Minute) tok, err := iss.Issue("user-1", auth.RoleClient, "sid-123") if err != nil { t.Fatalf("issue: %v", err) } claims, err := iss.Verify(tok) if err != nil { t.Fatalf("verify: %v", err) } if claims.Subject != "user-1" || claims.Role != auth.RoleClient || claims.SessionID != "sid-123" { t.Fatalf("claims inattendus: %+v", claims) } } // Sécurité : token signé avec une autre clé rejeté. func TestJWTRejectsWrongKey(t *testing.T) { a := auth.NewIssuer([]byte(testSecret), time.Minute) b := auth.NewIssuer([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), time.Minute) tok, _ := a.Issue("u", auth.RoleClient, "sid") if _, err := b.Verify(tok); err == nil { t.Fatal("un token d'une autre clé ne doit pas être accepté") } } // Sécurité : token expiré rejeté. func TestJWTRejectsExpired(t *testing.T) { iss := auth.NewIssuer([]byte(testSecret), -time.Minute) tok, _ := iss.Issue("u", auth.RoleClient, "sid") if _, err := iss.Verify(tok); err == nil { t.Fatal("un token expiré ne doit pas être accepté") } } // Session Redis(mem) : create → get → delete. func TestSessionManagerLifecycle(t *testing.T) { mgr := session.NewMemManager(time.Hour) sid, err := mgr.Create(context.Background(), session.Session{UserID: "u1", Role: "sales"}) if err != nil || sid == "" { t.Fatalf("create: sid=%q err=%v", sid, err) } if _, found, _ := mgr.Get(context.Background(), sid); !found { t.Fatal("session attendue présente") } if err := mgr.Delete(context.Background(), sid); err != nil { t.Fatalf("delete: %v", err) } if _, found, _ := mgr.Get(context.Background(), sid); found { t.Fatal("session ne doit plus exister après delete") } }