From e322cbffb877e23eed11b019abaa383ba1d9aa05 Mon Sep 17 00:00:00 2001 From: chan Date: Fri, 13 Feb 2026 15:18:38 +0900 Subject: [PATCH] =?UTF-8?q?lint=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/domain/auth_models.go | 24 +++++++-------- .../handler/auth_handler_async_test.go | 29 +++++++++++++++++-- .../handler/user_group_handler_test.go | 11 ++++++- .../service/user_group_service_test.go | 19 ++++++++++-- 4 files changed, 65 insertions(+), 18 deletions(-) diff --git a/backend/internal/domain/auth_models.go b/backend/internal/domain/auth_models.go index e1f07919..b81181fe 100644 --- a/backend/internal/domain/auth_models.go +++ b/backend/internal/domain/auth_models.go @@ -68,18 +68,18 @@ type SignupRequest struct { // User Profile Models type UserProfileResponse struct { - ID string `json:"id"` - Email string `json:"email"` - Name string `json:"name"` - Phone string `json:"phone"` - Role string `json:"role"` // 추가 - Department string `json:"department"` - AffiliationType string `json:"affiliationType"` - CompanyCode string `json:"companyCode,omitempty"` - TenantID *string `json:"tenantId,omitempty"` // 추가 - RelyingPartyID *string `json:"relyingPartyId,omitempty"` // 추가 - Metadata map[string]any `json:"metadata,omitempty"` - Tenant *Tenant `json:"tenant,omitempty"` + ID string `json:"id"` + Email string `json:"email"` + Name string `json:"name"` + Phone string `json:"phone"` + Role string `json:"role"` // 추가 + Department string `json:"department"` + AffiliationType string `json:"affiliationType"` + CompanyCode string `json:"companyCode,omitempty"` + TenantID *string `json:"tenantId,omitempty"` // 추가 + RelyingPartyID *string `json:"relyingPartyId,omitempty"` // 추가 + Metadata map[string]any `json:"metadata,omitempty"` + Tenant *Tenant `json:"tenant,omitempty"` ManageableTenants []Tenant `json:"manageableTenants,omitempty"` // 추가: 관리 가능한 테넌트 목록 } diff --git a/backend/internal/handler/auth_handler_async_test.go b/backend/internal/handler/auth_handler_async_test.go index 48db4a75..350864e6 100644 --- a/backend/internal/handler/auth_handler_async_test.go +++ b/backend/internal/handler/auth_handler_async_test.go @@ -27,24 +27,31 @@ func (m *AsyncMockIdpProvider) Name() string { return "mock-idp" } func (m *AsyncMockIdpProvider) GetMetadata() (*domain.IDPMetadata, error) { return &domain.IDPMetadata{}, nil } + func (m *AsyncMockIdpProvider) UserExists(loginID string) (bool, error) { args := m.Called(loginID) return args.Bool(0), args.Error(1) } + func (m *AsyncMockIdpProvider) CreateUser(user *domain.BrokerUser, password string) (string, error) { args := m.Called(user, password) return args.String(0), args.Error(1) } + func (m *AsyncMockIdpProvider) SignIn(loginID, password string) (*domain.AuthInfo, error) { return nil, nil } -func (m *AsyncMockIdpProvider) IssueSession(loginID string) (*domain.AuthInfo, error) { return nil, nil } +func (m *AsyncMockIdpProvider) IssueSession(loginID string) (*domain.AuthInfo, error) { + return nil, nil +} func (m *AsyncMockIdpProvider) InitiateLinkLogin(loginID, returnTo string) (*domain.LinkLoginInit, error) { return nil, nil } + func (m *AsyncMockIdpProvider) VerifyLoginCode(loginID, flowID, code string) (*domain.AuthInfo, error) { return nil, nil } + func (m *AsyncMockIdpProvider) GetPasswordPolicy() (*domain.PasswordPolicy, error) { return &domain.PasswordPolicy{MinLength: 12}, nil } @@ -52,6 +59,7 @@ func (m *AsyncMockIdpProvider) InitiatePasswordReset(loginID, redirectUrl string func (m *AsyncMockIdpProvider) VerifyPasswordResetToken(token string) (*domain.AuthInfo, error) { return nil, nil } + func (m *AsyncMockIdpProvider) UpdateUserPassword(loginID, newPassword string, r *http.Request) error { return nil } @@ -74,15 +82,19 @@ func (m *AsyncMockUserRepo) Update(ctx context.Context, user *domain.User) error func (m *AsyncMockUserRepo) FindByEmail(ctx context.Context, email string) (*domain.User, error) { return nil, nil } + func (m *AsyncMockUserRepo) FindByID(ctx context.Context, id string) (*domain.User, error) { return nil, nil } + func (m *AsyncMockUserRepo) FindByIDs(ctx context.Context, ids []string) ([]domain.User, error) { return nil, nil } + func (m *AsyncMockUserRepo) ListByTenant(ctx context.Context, tenantID string) ([]domain.User, error) { return nil, nil } + func (m *AsyncMockUserRepo) List(ctx context.Context, offset, limit int, search string) ([]domain.User, int64, error) { return nil, 0, nil } @@ -95,10 +107,12 @@ func (m *AsyncMockRedisRepo) Set(key string, value string, expiration time.Durat args := m.Called(key, value, expiration) return args.Error(0) } + func (m *AsyncMockRedisRepo) Get(key string) (string, error) { args := m.Called(key) return args.String(0), args.Error(1) } + func (m *AsyncMockRedisRepo) Delete(key string) error { args := m.Called(key) return args.Error(0) @@ -114,9 +128,11 @@ type AsyncMockTenantService struct { func (m *AsyncMockTenantService) RegisterTenant(ctx context.Context, name, slug, description string, domains []string) (*domain.Tenant, error) { return nil, nil } + func (m *AsyncMockTenantService) RequestRegistration(ctx context.Context, name, slug, description string, domainName string, adminEmail string) (*domain.Tenant, error) { return nil, nil } + func (m *AsyncMockTenantService) GetTenantByDomain(ctx context.Context, emailDomain string) (*domain.Tenant, error) { args := m.Called(ctx, emailDomain) if args.Get(0) == nil { @@ -124,23 +140,28 @@ func (m *AsyncMockTenantService) GetTenantByDomain(ctx context.Context, emailDom } return args.Get(0).(*domain.Tenant), args.Error(1) } + func (m *AsyncMockTenantService) GetTenantBySlug(ctx context.Context, slug string) (*domain.Tenant, error) { return nil, nil } + func (m *AsyncMockTenantService) GetTenant(ctx context.Context, id string) (*domain.Tenant, error) { return nil, nil } + func (m *AsyncMockTenantService) ListManageableTenants(ctx context.Context, userID string) ([]domain.Tenant, error) { return nil, nil } func (m *AsyncMockTenantService) ApproveTenant(ctx context.Context, id string) error { return nil } -func (m *AsyncMockTenantService) SetKetoService(keto service.KetoService) {} +func (m *AsyncMockTenantService) SetKetoService(keto service.KetoService) {} func (m *AsyncMockTenantService) AddTenantAdmin(ctx context.Context, tenantID, userID string) error { return nil } + func (m *AsyncMockTenantService) RemoveTenantAdmin(ctx context.Context, tenantID, userID string) error { return nil } + func (m *AsyncMockTenantService) ListTenantAdmins(ctx context.Context, tenantID string) ([]string, error) { return nil, nil } @@ -153,15 +174,19 @@ func (m *AsyncMockKetoService) CreateRelation(ctx context.Context, namespace, ob args := m.Called(ctx, namespace, object, relation, subject) return args.Error(0) } + func (m *AsyncMockKetoService) DeleteRelation(ctx context.Context, namespace, object, relation, subject string) error { return nil } + func (m *AsyncMockKetoService) CheckPermission(ctx context.Context, namespace, object, relation, subject string) (bool, error) { return false, nil } + func (m *AsyncMockKetoService) ListObjects(ctx context.Context, namespace, relation, subject string) ([]string, error) { return nil, nil } + func (m *AsyncMockKetoService) ListRelations(ctx context.Context, namespace, object, relation, subject string) ([]service.RelationTuple, error) { return nil, nil } diff --git a/backend/internal/handler/user_group_handler_test.go b/backend/internal/handler/user_group_handler_test.go index a8082f11..9ad62959 100644 --- a/backend/internal/handler/user_group_handler_test.go +++ b/backend/internal/handler/user_group_handler_test.go @@ -23,12 +23,15 @@ type MockUserGroupService struct { func (m *MockUserGroupService) Create(ctx context.Context, group *domain.UserGroup) error { return m.Called(ctx, group).Error(0) } + func (m *MockUserGroupService) Update(ctx context.Context, group *domain.UserGroup) error { return m.Called(ctx, group).Error(0) } + func (m *MockUserGroupService) Delete(ctx context.Context, id string) error { return m.Called(ctx, id).Error(0) } + func (m *MockUserGroupService) Get(ctx context.Context, id string) (*domain.UserGroup, error) { args := m.Called(ctx, id) if args.Get(0) == nil { @@ -36,23 +39,29 @@ func (m *MockUserGroupService) Get(ctx context.Context, id string) (*domain.User } return args.Get(0).(*domain.UserGroup), args.Error(1) } + func (m *MockUserGroupService) List(ctx context.Context, tenantID string) ([]domain.UserGroup, error) { args := m.Called(ctx, tenantID) return args.Get(0).([]domain.UserGroup), args.Error(1) } + func (m *MockUserGroupService) AddMember(ctx context.Context, groupID, userID string) error { return m.Called(ctx, groupID, userID).Error(0) } + func (m *MockUserGroupService) RemoveMember(ctx context.Context, groupID, userID string) error { return m.Called(ctx, groupID, userID).Error(0) } + func (m *MockUserGroupService) ListRoles(ctx context.Context, groupID string) ([]domain.GroupRole, error) { args := m.Called(ctx, groupID) return args.Get(0).([]domain.GroupRole), args.Error(1) } + func (m *MockUserGroupService) AssignRoleToTenant(ctx context.Context, groupID, tenantID, relation string) error { return m.Called(ctx, groupID, tenantID, relation).Error(0) } + func (m *MockUserGroupService) RemoveRoleFromTenant(ctx context.Context, groupID, tenantID, relation string) error { return m.Called(ctx, groupID, tenantID, relation).Error(0) } @@ -106,7 +115,7 @@ func TestUserGroupHandler_AddMember(t *testing.T) { groupID := "g1" userID := "u1" body, _ := json.Marshal(map[string]string{"userId": userID}) - + mockSvc.On("AddMember", mock.Anything, groupID, userID).Return(nil) req := httptest.NewRequest("POST", "/user-groups/g1/members", bytes.NewReader(body)) diff --git a/backend/internal/service/user_group_service_test.go b/backend/internal/service/user_group_service_test.go index 11c7b69f..71cedb29 100644 --- a/backend/internal/service/user_group_service_test.go +++ b/backend/internal/service/user_group_service_test.go @@ -18,12 +18,15 @@ type MockUserGroupRepository struct { func (m *MockUserGroupRepository) Create(ctx context.Context, group *domain.UserGroup) error { return m.Called(ctx, group).Error(0) } + func (m *MockUserGroupRepository) Update(ctx context.Context, group *domain.UserGroup) error { return m.Called(ctx, group).Error(0) } + func (m *MockUserGroupRepository) Delete(ctx context.Context, id string) error { return m.Called(ctx, id).Error(0) } + func (m *MockUserGroupRepository) FindByID(ctx context.Context, id string) (*domain.UserGroup, error) { args := m.Called(ctx, id) if args.Get(0) == nil { @@ -31,6 +34,7 @@ func (m *MockUserGroupRepository) FindByID(ctx context.Context, id string) (*dom } return args.Get(0).(*domain.UserGroup), args.Error(1) } + func (m *MockUserGroupRepository) ListByTenantID(ctx context.Context, tenantID string) ([]domain.UserGroup, error) { args := m.Called(ctx, tenantID) return args.Get(0).([]domain.UserGroup), args.Error(1) @@ -45,16 +49,20 @@ func (m *MockUserRepository) Update(ctx context.Context, user *domain.User) erro func (m *MockUserRepository) FindByEmail(ctx context.Context, email string) (*domain.User, error) { return nil, nil } + func (m *MockUserRepository) FindByID(ctx context.Context, id string) (*domain.User, error) { return nil, nil } + func (m *MockUserRepository) FindByIDs(ctx context.Context, ids []string) ([]domain.User, error) { args := m.Called(ctx, ids) return args.Get(0).([]domain.User), args.Error(1) } + func (m *MockUserRepository) ListByTenant(ctx context.Context, tenantID string) ([]domain.User, error) { return nil, nil } + func (m *MockUserRepository) List(ctx context.Context, offset, limit int, search string) ([]domain.User, int64, error) { return nil, 0, nil } @@ -68,19 +76,24 @@ func (m *MockTenantRepository) Update(ctx context.Context, tenant *domain.Tenant func (m *MockTenantRepository) FindByID(ctx context.Context, id string) (*domain.Tenant, error) { return nil, nil } + func (m *MockTenantRepository) FindByIDs(ctx context.Context, ids []string) ([]domain.Tenant, error) { args := m.Called(ctx, ids) return args.Get(0).([]domain.Tenant), args.Error(1) } + func (m *MockTenantRepository) FindBySlug(ctx context.Context, slug string) (*domain.Tenant, error) { return nil, nil } + func (m *MockTenantRepository) FindByName(ctx context.Context, name string) (*domain.Tenant, error) { return nil, nil } + func (m *MockTenantRepository) FindByDomain(ctx context.Context, domainName string) (*domain.Tenant, error) { return nil, nil } + func (m *MockTenantRepository) AddDomain(ctx context.Context, tenantID string, domainName string) error { return nil } @@ -180,17 +193,17 @@ func TestUserGroupService_Get_WithKratosFallback(t *testing.T) { // We need a way to mock KratosAdminService but it's a struct, not an interface. // For this POC test, we'll focus on the Keto and UserRepo parts. // If needed, we can refactor KratosAdminService to an interface. - + svc := NewUserGroupService(mockRepo, mockUserRepo, nil, mockKeto, nil) groupID := "group-1" mockRepo.On("FindByID", mock.Anything, groupID).Return(&domain.UserGroup{ID: groupID, Name: "Test"}, nil) - + tuples := []RelationTuple{ {Object: groupID, Relation: "members", SubjectID: "User:u1"}, } mockKeto.On("ListRelations", mock.Anything, "UserGroup", groupID, "members", "").Return(tuples, nil) - + // User u1 not in local DB mockUserRepo.On("FindByIDs", mock.Anything, []string{"u1"}).Return([]domain.User{}, nil)