forked from baron/baron-sso
158 lines
4.6 KiB
Go
158 lines
4.6 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"baron-sso-backend/internal/domain"
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func TestEnsureSuperAdminCreatesIdentityLocalUserAndKetoRelation(t *testing.T) {
|
|
ctx := context.Background()
|
|
identityAdmin := &fakeSuperAdminIdentityAdmin{createdID: "identity-1"}
|
|
store := &fakeSuperAdminStore{}
|
|
|
|
result, err := EnsureSuperAdmin(ctx, identityAdmin, store, EnsureSuperAdminOptions{
|
|
Email: "new-admin@example.com",
|
|
Password: "Password!123",
|
|
Name: "New Admin",
|
|
Source: "test",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("EnsureSuperAdmin returned error: %v", err)
|
|
}
|
|
if !result.IdentityCreated {
|
|
t.Fatal("identity must be created")
|
|
}
|
|
if !result.LocalUserCreated {
|
|
t.Fatal("local user must be created")
|
|
}
|
|
if result.IdentityID != "identity-1" {
|
|
t.Fatalf("identity ID = %q, want identity-1", result.IdentityID)
|
|
}
|
|
if store.user == nil {
|
|
t.Fatal("local user was not stored")
|
|
}
|
|
if store.user.Email != "new-admin@example.com" {
|
|
t.Fatalf("local user email = %q", store.user.Email)
|
|
}
|
|
if store.user.Role != domain.RoleSuperAdmin {
|
|
t.Fatalf("local user role = %q, want %q", store.user.Role, domain.RoleSuperAdmin)
|
|
}
|
|
if len(store.ketoSubjects) != 1 || store.ketoSubjects[0] != "User:identity-1" {
|
|
t.Fatalf("keto subjects = %#v, want User:identity-1", store.ketoSubjects)
|
|
}
|
|
if identityAdmin.createdUser == nil || identityAdmin.createdUser.Attributes["role"] != domain.RoleSuperAdmin {
|
|
t.Fatalf("created identity attributes = %#v", identityAdmin.createdUser)
|
|
}
|
|
}
|
|
|
|
func TestEnsureSuperAdminPromotesExistingLocalUser(t *testing.T) {
|
|
ctx := context.Background()
|
|
identityAdmin := &fakeSuperAdminIdentityAdmin{existingID: "identity-1"}
|
|
store := &fakeSuperAdminStore{
|
|
user: &domain.User{
|
|
ID: "local-user-1",
|
|
Email: "existing@example.com",
|
|
Name: "Existing",
|
|
Role: domain.RoleUser,
|
|
Status: domain.UserStatusPreboarding,
|
|
},
|
|
}
|
|
|
|
result, err := EnsureSuperAdmin(ctx, identityAdmin, store, EnsureSuperAdminOptions{
|
|
Email: "existing@example.com",
|
|
Password: "Password!123",
|
|
Name: "Existing Admin",
|
|
Source: "test",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("EnsureSuperAdmin returned error: %v", err)
|
|
}
|
|
if result.IdentityCreated {
|
|
t.Fatal("existing identity must not be recreated")
|
|
}
|
|
if !result.LocalUserUpdated {
|
|
t.Fatal("local user must be promoted")
|
|
}
|
|
if store.user.Role != domain.RoleSuperAdmin {
|
|
t.Fatalf("local user role = %q, want %q", store.user.Role, domain.RoleSuperAdmin)
|
|
}
|
|
if store.user.Status != domain.UserStatusActive {
|
|
t.Fatalf("local user status = %q, want %q", store.user.Status, domain.UserStatusActive)
|
|
}
|
|
if len(store.ketoSubjects) != 1 || store.ketoSubjects[0] != "User:local-user-1" {
|
|
t.Fatalf("keto subjects = %#v, want User:local-user-1", store.ketoSubjects)
|
|
}
|
|
}
|
|
|
|
func TestEnsureSuperAdminRequiresPasswordForNewIdentity(t *testing.T) {
|
|
_, err := EnsureSuperAdmin(context.Background(), &fakeSuperAdminIdentityAdmin{}, &fakeSuperAdminStore{}, EnsureSuperAdminOptions{
|
|
Email: "new-admin@example.com",
|
|
Name: "New Admin",
|
|
})
|
|
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
}
|
|
|
|
type fakeSuperAdminIdentityAdmin struct {
|
|
existingID string
|
|
createdID string
|
|
createdUser *domain.BrokerUser
|
|
createdSecret string
|
|
}
|
|
|
|
func (f *fakeSuperAdminIdentityAdmin) FindIdentityIDByIdentifier(ctx context.Context, identifier string) (string, error) {
|
|
return f.existingID, nil
|
|
}
|
|
|
|
func (f *fakeSuperAdminIdentityAdmin) CreateUser(ctx context.Context, user *domain.BrokerUser, password string) (string, error) {
|
|
if f.createdID == "" {
|
|
return "", errors.New("created id is not configured")
|
|
}
|
|
f.createdUser = user
|
|
f.createdSecret = password
|
|
return f.createdID, nil
|
|
}
|
|
|
|
func (f *fakeSuperAdminIdentityAdmin) UpdateIdentityPassword(ctx context.Context, identityID string, newPassword string) error {
|
|
return nil
|
|
}
|
|
|
|
type fakeSuperAdminStore struct {
|
|
user *domain.User
|
|
ketoSubjects []string
|
|
}
|
|
|
|
func (f *fakeSuperAdminStore) FindUserByEmail(ctx context.Context, email string) (*domain.User, error) {
|
|
if f.user == nil {
|
|
return nil, nil
|
|
}
|
|
return f.user, nil
|
|
}
|
|
|
|
func (f *fakeSuperAdminStore) CreateUser(ctx context.Context, user *domain.User) error {
|
|
copied := *user
|
|
f.user = &copied
|
|
return nil
|
|
}
|
|
|
|
func (f *fakeSuperAdminStore) UpdateUserSuperAdmin(ctx context.Context, userID string, name string) (*domain.User, error) {
|
|
if f.user == nil {
|
|
return nil, errors.New("user not found")
|
|
}
|
|
f.user.Role = domain.RoleSuperAdmin
|
|
f.user.Status = domain.UserStatusActive
|
|
if name != "" {
|
|
f.user.Name = name
|
|
}
|
|
return f.user, nil
|
|
}
|
|
|
|
func (f *fakeSuperAdminStore) EnqueueSuperAdminRelation(ctx context.Context, userID string) error {
|
|
f.ketoSubjects = append(f.ketoSubjects, "User:"+userID)
|
|
return nil
|
|
}
|