1
0
forked from baron/baron-sso

custom claim 권한체크 확인

This commit is contained in:
2026-06-11 08:29:25 +09:00
parent 839ca9d407
commit 4d77060b5d
79 changed files with 4268 additions and 670 deletions

View File

@@ -342,6 +342,97 @@ func TestGetCurrentProfile_PreservesExistingAuditUserContext(t *testing.T) {
assert.Equal(t, "existing-user", body["user_id"])
}
func TestListMyTenants_UserIncludesPrimaryJoinedAndMetadataAppointments(t *testing.T) {
primaryTenantID := "tenant-primary"
mockAuth := new(devMockAuthProvider)
mockTenant := new(MockTenantService)
handler := &DevHandler{Auth: mockAuth, TenantSvc: mockTenant}
app := fiber.New()
app.Get("/api/v1/dev/my-tenants", handler.ListMyTenants)
profile := &domain.UserProfileResponse{
ID: "user-1",
Role: domain.RoleUser,
TenantID: &primaryTenantID,
JoinedTenants: []domain.Tenant{
{ID: "tenant-joined", Slug: "joined", Name: "Joined Tenant", Status: domain.TenantStatusActive},
},
Metadata: map[string]any{
"additionalAppointments": []any{
map[string]any{"tenantId": "tenant-extra"},
map[string]any{"tenantSlug": "slug-extra"},
},
},
}
mockAuth.On("GetEnrichedProfile", mock.Anything).Return(profile, nil).Once()
mockTenant.On("GetTenant", mock.Anything, primaryTenantID).Return(&domain.Tenant{
ID: primaryTenantID, Slug: "primary", Name: "Primary Tenant", Status: domain.TenantStatusActive,
}, nil).Once()
mockTenant.On("GetTenant", mock.Anything, "tenant-extra").Return(&domain.Tenant{
ID: "tenant-extra", Slug: "extra-id", Name: "Extra Tenant By ID", Status: domain.TenantStatusActive,
}, nil).Once()
mockTenant.On("GetTenantBySlug", mock.Anything, "slug-extra").Return(&domain.Tenant{
ID: "tenant-slug-extra", Slug: "slug-extra", Name: "Extra Tenant By Slug", Status: domain.TenantStatusActive,
}, nil).Once()
req := httptest.NewRequest(http.MethodGet, "/api/v1/dev/my-tenants", nil)
resp, _ := app.Test(req, -1)
assert.Equal(t, http.StatusOK, resp.StatusCode)
var tenants []domain.Tenant
assert.NoError(t, json.NewDecoder(resp.Body).Decode(&tenants))
assert.NoError(t, resp.Body.Close())
assertTenantIDs(t, tenants, []string{"tenant-primary", "tenant-joined", "tenant-extra", "tenant-slug-extra"})
mockAuth.AssertExpectations(t)
mockTenant.AssertExpectations(t)
}
func TestListMyTenants_TenantAdminIncludesManageableJoinedAndPrimary(t *testing.T) {
primaryTenantID := "tenant-primary"
mockAuth := new(devMockAuthProvider)
mockTenant := new(MockTenantService)
handler := &DevHandler{Auth: mockAuth, TenantSvc: mockTenant}
app := fiber.New()
app.Get("/api/v1/dev/my-tenants", handler.ListMyTenants)
profile := &domain.UserProfileResponse{
ID: "tenant-admin-1",
Role: "tenant_admin",
TenantID: &primaryTenantID,
JoinedTenants: []domain.Tenant{
{ID: "tenant-joined", Slug: "joined", Name: "Joined Tenant", Status: domain.TenantStatusActive},
},
}
mockAuth.On("GetEnrichedProfile", mock.Anything).Return(profile, nil).Once()
mockTenant.On("ListManageableTenants", mock.Anything, "tenant-admin-1").Return([]domain.Tenant{
{ID: "tenant-managed", Slug: "managed", Name: "Managed Tenant", Status: domain.TenantStatusActive},
}, nil).Once()
mockTenant.On("GetTenant", mock.Anything, primaryTenantID).Return(&domain.Tenant{
ID: primaryTenantID, Slug: "primary", Name: "Primary Tenant", Status: domain.TenantStatusActive,
}, nil).Once()
req := httptest.NewRequest(http.MethodGet, "/api/v1/dev/my-tenants", nil)
resp, _ := app.Test(req, -1)
assert.Equal(t, http.StatusOK, resp.StatusCode)
var tenants []domain.Tenant
assert.NoError(t, json.NewDecoder(resp.Body).Decode(&tenants))
assert.NoError(t, resp.Body.Close())
assertTenantIDs(t, tenants, []string{"tenant-managed", "tenant-joined", "tenant-primary"})
mockAuth.AssertExpectations(t)
mockTenant.AssertExpectations(t)
}
func assertTenantIDs(t *testing.T, tenants []domain.Tenant, expected []string) {
t.Helper()
actual := make([]string, 0, len(tenants))
for _, tenant := range tenants {
actual = append(actual, tenant.ID)
}
assert.ElementsMatch(t, expected, actual)
}
func TestListClients_Success(t *testing.T) {
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
if r.URL.Path == "/clients" {
@@ -3334,6 +3425,32 @@ func TestNormalizeIDTokenClaimsMetadata_AllowsDateAndDatetime(t *testing.T) {
assert.Equal(t, "datetime", claims[1].ValueType)
}
func TestNormalizeIDTokenClaimsMetadata_PreservesNullableDefaultValue(t *testing.T) {
metadata, err := normalizeIDTokenClaimsMetadata(map[string]any{
domain.MetadataIDTokenClaims: []any{
map[string]any{
"namespace": "rp_claims",
"key": "contract_date",
"value": "",
"valueType": "date",
"nullable": true,
"readPermission": "user_and_admin",
"writePermission": "user_and_admin",
},
},
})
assert.NoError(t, err)
claims := metadata[domain.MetadataIDTokenClaims].([]normalizedIDTokenClaim)
if assert.Len(t, claims, 1) {
assert.Equal(t, "contract_date", claims[0].Key)
assert.Equal(t, "date", claims[0].ValueType)
assert.True(t, claims[0].Nullable)
assert.Equal(t, "user_and_admin", claims[0].ReadPermission)
assert.Equal(t, "user_and_admin", claims[0].WritePermission)
}
}
func TestUpdateClient_RejectsTopLevelIDTokenClaimsFromDevConsole(t *testing.T) {
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
if r.Method == http.MethodGet && r.URL.Path == "/clients/client-1" {