BOOTSTRAP_ADMIN_EMAIL/PASSWORD seed a role=admin account at boot if absent — the only way to get the first admin, since /register makes plain users and promotion needs an existing admin. Idempotent and race-safe. Tests included.
72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
package usecase_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/emil28092005/SciMesh/users/internal/auth"
|
|
"github.com/emil28092005/SciMesh/users/internal/domain"
|
|
"github.com/emil28092005/SciMesh/users/internal/memstore"
|
|
"github.com/emil28092005/SciMesh/users/internal/usecase"
|
|
)
|
|
|
|
func newBootstrap() (*usecase.BootstrapAdmin, *memstore.UserRepo) {
|
|
users := memstore.NewUserRepo()
|
|
hasher := auth.NewHasher(4)
|
|
clk := memstore.Clock{T: time.Date(2026, 7, 26, 0, 0, 0, 0, time.UTC)}
|
|
return usecase.NewBootstrapAdmin(users, hasher, clk), users
|
|
}
|
|
|
|
func TestBootstrapCreatesAdmin(t *testing.T) {
|
|
bs, users := newBootstrap()
|
|
|
|
created, err := bs.Execute(context.Background(), "Root@Example.com", "rootpassword")
|
|
if err != nil {
|
|
t.Fatalf("bootstrap: %v", err)
|
|
}
|
|
if !created {
|
|
t.Fatal("expected an admin to be created")
|
|
}
|
|
|
|
u, err := users.GetByEmail(context.Background(), "root@example.com")
|
|
if err != nil {
|
|
t.Fatalf("admin not persisted: %v", err)
|
|
}
|
|
if u.Role != domain.RoleAdmin {
|
|
t.Errorf("role = %q, want admin", u.Role)
|
|
}
|
|
if !u.Verified {
|
|
t.Error("bootstrap admin should be verified")
|
|
}
|
|
}
|
|
|
|
func TestBootstrapIsIdempotent(t *testing.T) {
|
|
bs, users := newBootstrap()
|
|
ctx := context.Background()
|
|
|
|
if _, err := bs.Execute(ctx, "root@example.com", "rootpassword"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
created, err := bs.Execute(ctx, "root@example.com", "rootpassword")
|
|
if err != nil {
|
|
t.Fatalf("second run: %v", err)
|
|
}
|
|
if created {
|
|
t.Error("second run must not create a duplicate admin")
|
|
}
|
|
|
|
// The account must still be a single admin.
|
|
if u, _ := users.GetByEmail(ctx, "root@example.com"); u.Role != domain.RoleAdmin {
|
|
t.Errorf("role changed: %q", u.Role)
|
|
}
|
|
}
|
|
|
|
func TestBootstrapRejectsWeakPassword(t *testing.T) {
|
|
bs, _ := newBootstrap()
|
|
if _, err := bs.Execute(context.Background(), "root@example.com", "short"); !errors.Is(err, usecase.ErrPasswordTooShort) {
|
|
t.Errorf("got %v, want ErrPasswordTooShort", err)
|
|
}
|
|
}
|