1
0
forked from baron/baron-sso

test code 수정

This commit is contained in:
2026-02-23 16:50:26 +09:00
parent 68becb43bc
commit 4dc4e19c27
18 changed files with 187 additions and 90 deletions

View File

@@ -21,18 +21,27 @@ type KratosIdentity struct {
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
type KratosAdminService struct {
type KratosAdminService interface {
ListIdentities(ctx context.Context) ([]KratosIdentity, error)
FindIdentityIDByIdentifier(ctx context.Context, identifier string) (string, error)
GetIdentity(ctx context.Context, identityID string) (*KratosIdentity, error)
UpdateIdentity(ctx context.Context, identityID string, traits map[string]interface{}, state string) (*KratosIdentity, error)
UpdateIdentityPassword(ctx context.Context, identityID, newPassword string) error
DeleteIdentity(ctx context.Context, identityID string) error
}
type kratosAdminService struct {
AdminURL string
HTTPClient *http.Client
}
func NewKratosAdminService() *KratosAdminService {
return &KratosAdminService{
func NewKratosAdminService() KratosAdminService {
return &kratosAdminService{
AdminURL: getenvKratos("KRATOS_ADMIN_URL", "http://kratos:4434"),
}
}
func (s *KratosAdminService) ListIdentities(ctx context.Context) ([]KratosIdentity, error) {
func (s *kratosAdminService) ListIdentities(ctx context.Context) ([]KratosIdentity, error) {
endpoint := strings.TrimRight(s.AdminURL, "/") + "/admin/identities"
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
@@ -57,7 +66,7 @@ func (s *KratosAdminService) ListIdentities(ctx context.Context) ([]KratosIdenti
return identities, nil
}
func (s *KratosAdminService) FindIdentityIDByIdentifier(ctx context.Context, identifier string) (string, error) {
func (s *kratosAdminService) FindIdentityIDByIdentifier(ctx context.Context, identifier string) (string, error) {
identifier = strings.TrimSpace(identifier)
if identifier == "" {
return "", nil
@@ -99,7 +108,7 @@ func (s *KratosAdminService) FindIdentityIDByIdentifier(ctx context.Context, ide
return identities[0].ID, nil
}
func (s *KratosAdminService) GetIdentity(ctx context.Context, identityID string) (*KratosIdentity, error) {
func (s *kratosAdminService) GetIdentity(ctx context.Context, identityID string) (*KratosIdentity, error) {
endpoint := fmt.Sprintf("%s/admin/identities/%s", strings.TrimRight(s.AdminURL, "/"), identityID)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
@@ -127,7 +136,7 @@ func (s *KratosAdminService) GetIdentity(ctx context.Context, identityID string)
return &identity, nil
}
func (s *KratosAdminService) UpdateIdentity(ctx context.Context, identityID string, traits map[string]interface{}, state string) (*KratosIdentity, error) {
func (s *kratosAdminService) UpdateIdentity(ctx context.Context, identityID string, traits map[string]interface{}, state string) (*KratosIdentity, error) {
payload := map[string]interface{}{
"schema_id": "default",
"traits": traits,
@@ -162,7 +171,7 @@ func (s *KratosAdminService) UpdateIdentity(ctx context.Context, identityID stri
return &updated, nil
}
func (s *KratosAdminService) UpdateIdentityPassword(ctx context.Context, identityID, newPassword string) error {
func (s *kratosAdminService) UpdateIdentityPassword(ctx context.Context, identityID, newPassword string) error {
patchOps := []map[string]interface{}{
{
"op": "add",
@@ -190,7 +199,7 @@ func (s *KratosAdminService) UpdateIdentityPassword(ctx context.Context, identit
return nil
}
func (s *KratosAdminService) DeleteIdentity(ctx context.Context, identityID string) error {
func (s *kratosAdminService) DeleteIdentity(ctx context.Context, identityID string) error {
endpoint := fmt.Sprintf("%s/admin/identities/%s", strings.TrimRight(s.AdminURL, "/"), identityID)
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, endpoint, nil)
if err != nil {
@@ -210,7 +219,7 @@ func (s *KratosAdminService) DeleteIdentity(ctx context.Context, identityID stri
return nil
}
func (s *KratosAdminService) httpClient() *http.Client {
func (s *kratosAdminService) httpClient() *http.Client {
if s.HTTPClient != nil {
return s.HTTPClient
}

View File

@@ -72,3 +72,41 @@ func (m *MockKetoServiceShared) ListObjects(ctx context.Context, namespace, rela
}
return args.Get(0).([]string), args.Error(1)
}
type MockKratosAdminServiceShared struct {
mock.Mock
}
func (m *MockKratosAdminServiceShared) ListIdentities(ctx context.Context) ([]KratosIdentity, error) {
args := m.Called(ctx)
return args.Get(0).([]KratosIdentity), args.Error(1)
}
func (m *MockKratosAdminServiceShared) FindIdentityIDByIdentifier(ctx context.Context, identifier string) (string, error) {
args := m.Called(ctx, identifier)
return args.String(0), args.Error(1)
}
func (m *MockKratosAdminServiceShared) GetIdentity(ctx context.Context, identityID string) (*KratosIdentity, error) {
args := m.Called(ctx, identityID)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*KratosIdentity), args.Error(1)
}
func (m *MockKratosAdminServiceShared) UpdateIdentity(ctx context.Context, identityID string, traits map[string]interface{}, state string) (*KratosIdentity, error) {
args := m.Called(ctx, identityID, traits, state)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*KratosIdentity), args.Error(1)
}
func (m *MockKratosAdminServiceShared) UpdateIdentityPassword(ctx context.Context, identityID, newPassword string) error {
return m.Called(ctx, identityID, newPassword).Error(0)
}
func (m *MockKratosAdminServiceShared) DeleteIdentity(ctx context.Context, identityID string) error {
return m.Called(ctx, identityID).Error(0)
}

View File

@@ -22,7 +22,7 @@ type orgChartService struct {
userGroupRepo repository.UserGroupRepository
userRepo repository.UserRepository
ketoOutboxRepo repository.KetoOutboxRepository
kratos *KratosAdminService
kratos KratosAdminService
}
func NewOrgChartService(
@@ -30,7 +30,7 @@ func NewOrgChartService(
userGroupRepo repository.UserGroupRepository,
userRepo repository.UserRepository,
ketoOutbox repository.KetoOutboxRepository,
kratos *KratosAdminService,
kratos KratosAdminService,
) OrgChartService {
return &orgChartService{
tenantRepo: tenantRepo,

View File

@@ -33,7 +33,7 @@ type userGroupService struct {
tenantRepo repository.TenantRepository
ketoService KetoService
outboxRepo repository.KetoOutboxRepository
kratos *KratosAdminService
kratos KratosAdminService
}
func NewUserGroupService(
@@ -42,7 +42,7 @@ func NewUserGroupService(
tenantRepo repository.TenantRepository,
keto KetoService,
outbox repository.KetoOutboxRepository,
kratos *KratosAdminService,
kratos KratosAdminService,
) UserGroupService {
return &userGroupService{
repo: repo,
@@ -59,6 +59,12 @@ func (s *userGroupService) Create(ctx context.Context, tenantID string, parentID
if parentID == nil || *parentID == "" {
parentID = &tenantID
}
// Validate parent tenant exists
if _, err := s.tenantRepo.FindByID(ctx, *parentID); err != nil {
return nil, fmt.Errorf("parent tenant not found or invalid: %w", err)
}
unitID := uuid.NewString()
// 1. Create Tenant (Type: USER_GROUP)
@@ -199,6 +205,11 @@ func (s *userGroupService) List(ctx context.Context, tenantID string) ([]domain.
}
func (s *userGroupService) AddMember(ctx context.Context, groupID, userID string) error {
// Validate group exists
if _, err := s.repo.FindByID(ctx, groupID); err != nil {
return fmt.Errorf("user group not found: %w", err)
}
// Keto via Outbox: Tenant:<groupID>#members@User:<userID>
if s.outboxRepo != nil {
_ = s.outboxRepo.Create(ctx, &domain.KetoOutbox{
@@ -214,6 +225,11 @@ func (s *userGroupService) AddMember(ctx context.Context, groupID, userID string
}
func (s *userGroupService) RemoveMember(ctx context.Context, groupID, userID string) error {
// Validate group exists
if _, err := s.repo.FindByID(ctx, groupID); err != nil {
return fmt.Errorf("user group not found: %w", err)
}
// Keto via Outbox: Delete relation
if s.outboxRepo != nil {
_ = s.outboxRepo.Create(ctx, &domain.KetoOutbox{
@@ -267,6 +283,11 @@ func (s *userGroupService) ListRoles(ctx context.Context, groupID string) ([]dom
}
func (s *userGroupService) AssignRoleToTenant(ctx context.Context, groupID, tenantID, relation string) error {
// Validate group exists
if _, err := s.repo.FindByID(ctx, groupID); err != nil {
return fmt.Errorf("user group not found: %w", err)
}
// Keto via Outbox: Tenant:<tenantID>#<relation>@Tenant:<groupID>#members
if s.outboxRepo != nil {
subject := "Tenant:" + groupID + "#members"

View File

@@ -1,9 +1,7 @@
package service
import (
"baron-sso-backend/internal/domain"
"context"
"errors"
"testing"
"github.com/stretchr/testify/assert"