forked from baron/baron-sso
test code 수정
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
Reference in New Issue
Block a user