1
0
forked from baron/baron-sso

worksmobile 연동 & ory stack 26.2.0으로 업그레이드

This commit is contained in:
2026-05-06 09:30:00 +09:00
parent 3dcdd97882
commit 2495fcb13d
74 changed files with 8698 additions and 212 deletions

View File

@@ -97,6 +97,27 @@ func (m *MockOryProvider) GetPasswordPolicy() (*domain.PasswordPolicy, error) {
return args.Get(0).(*domain.PasswordPolicy), args.Error(1)
}
type fakeUserHandlerWorksmobileSyncer struct {
upserts []domain.User
}
func (f *fakeUserHandlerWorksmobileSyncer) EnqueueTenantUpsertIfInScope(ctx context.Context, tenant domain.Tenant) error {
return nil
}
func (f *fakeUserHandlerWorksmobileSyncer) EnqueueTenantDeleteIfInScope(ctx context.Context, tenant domain.Tenant) error {
return nil
}
func (f *fakeUserHandlerWorksmobileSyncer) EnqueueUserUpsertIfInScope(ctx context.Context, user domain.User) error {
f.upserts = append(f.upserts, user)
return nil
}
func (f *fakeUserHandlerWorksmobileSyncer) EnqueueUserDeleteIfInScope(ctx context.Context, user domain.User) error {
return nil
}
type MockTenantServiceForUser struct {
mock.Mock
service.TenantService
@@ -576,7 +597,9 @@ func TestUserHandler_CreateUser_HanmacEmailPolicyBlocksDuplicateLocalPart(t *tes
func TestUserHandler_BulkUpdateUsers(t *testing.T) {
app := fiber.New()
mockKratos := new(MockKratosAdmin)
h := &UserHandler{KratosAdmin: mockKratos}
mockRepo := new(MockUserRepoForHandler)
worksmobile := &fakeUserHandlerWorksmobileSyncer{}
h := &UserHandler{KratosAdmin: mockKratos, UserRepo: mockRepo, Worksmobile: worksmobile}
app.Put("/users/bulk", func(c *fiber.Ctx) error {
c.Locals("user_profile", &domain.UserProfileResponse{Role: domain.RoleSuperAdmin})
@@ -585,10 +608,18 @@ func TestUserHandler_BulkUpdateUsers(t *testing.T) {
t.Run("Success - Update Role and Status", func(t *testing.T) {
mockKratos.On("GetIdentity", mock.Anything, "u-1").Return(&service.KratosIdentity{
ID: "u-1", Traits: map[string]interface{}{"email": "u1@test.com"}, State: "active",
ID: "u-1", Traits: map[string]interface{}{"email": "u1@test.com", "tenant_id": "tenant-1"}, State: "active",
}, nil).Once()
mockKratos.On("UpdateIdentity", mock.Anything, "u-1", mock.Anything, "inactive").Return(&service.KratosIdentity{}, nil).Once()
mockKratos.On("UpdateIdentity", mock.Anything, "u-1", mock.Anything, "inactive").Return(&service.KratosIdentity{
ID: "u-1",
Traits: map[string]interface{}{
"email": "u1@test.com",
"name": "Bulk User",
"tenant_id": "tenant-1",
},
State: "inactive",
}, nil).Once()
status := "inactive"
payload := map[string]interface{}{
@@ -606,6 +637,9 @@ func TestUserHandler_BulkUpdateUsers(t *testing.T) {
json.NewDecoder(resp.Body).Decode(&result)
results := result["results"].([]interface{})
assert.True(t, results[0].(map[string]interface{})["success"].(bool))
assert.Len(t, worksmobile.upserts, 1)
assert.Equal(t, "u-1", worksmobile.upserts[0].ID)
assert.Equal(t, domain.UserStatusInactive, worksmobile.upserts[0].Status)
})
}
@@ -1033,6 +1067,74 @@ func TestUserHandler_CreateUser_LoginIDSync(t *testing.T) {
})
}
func TestUserHandler_CreateUser_UsesAdditionalAppointmentAsPrimaryTenant(t *testing.T) {
app := fiber.New()
mockKratos := new(MockKratosAdmin)
mockOry := new(MockOryProvider)
mockTenant := new(MockTenantServiceForUser)
mockRepo := new(MockUserRepoForHandler)
worksmobile := &fakeUserHandlerWorksmobileSyncer{}
h := &UserHandler{
KratosAdmin: mockKratos,
OryProvider: mockOry,
TenantService: mockTenant,
UserRepo: mockRepo,
Worksmobile: worksmobile,
}
app.Post("/users", h.CreateUser)
tenantID := "33333333-3333-3333-3333-333333333333"
mockTenant.On("GetTenant", mock.Anything, tenantID).Return(&domain.Tenant{
ID: tenantID,
Slug: "saman",
}, nil)
mockTenant.On("GetTenantBySlug", mock.Anything, "saman").Return(&domain.Tenant{
ID: tenantID,
Slug: "saman",
}, nil)
mockTenant.On("ListTenants", mock.Anything, 10000, 0, "").Return([]domain.Tenant{}, int64(0), nil)
mockOry.On("GetPasswordPolicy").Return(&domain.PasswordPolicy{MinLength: 8}, nil)
mockOry.On("CreateUser", mock.MatchedBy(func(user *domain.BrokerUser) bool {
return user.Attributes["tenant_id"] == tenantID &&
user.Attributes["companyCode"] == "saman" &&
user.Attributes["additionalAppointments"] != nil
}), mock.Anything).Return("u-appointment", nil).Once()
mockKratos.On("GetIdentity", mock.Anything, "u-appointment").Return(&service.KratosIdentity{
ID: "u-appointment",
Traits: map[string]interface{}{
"email": "new@samaneng.com",
"name": "Appointment User",
"companyCode": "saman",
"tenant_id": tenantID,
"additionalAppointments": []interface{}{
map[string]interface{}{"tenantId": tenantID, "tenantSlug": "saman"},
},
},
State: "active",
}, nil).Once()
payload := map[string]interface{}{
"email": "new@samaneng.com",
"name": "Appointment User",
"additionalAppointments": []map[string]interface{}{
{"tenantId": tenantID, "tenantSlug": "saman", "tenantName": "삼안"},
},
"metadata": map[string]interface{}{
"userType": "hanmac",
},
}
body, _ := json.Marshal(payload)
req := httptest.NewRequest("POST", "/users", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
resp, _ := app.Test(req)
assert.Equal(t, 201, resp.StatusCode)
assert.Len(t, worksmobile.upserts, 1)
assert.Equal(t, tenantID, *worksmobile.upserts[0].TenantID)
mockOry.AssertExpectations(t)
}
func (m *MockKratosAdmin) CreateUser(ctx context.Context, user *domain.BrokerUser, password string) (string, error) {
return "", nil
}