forked from baron/baron-sso
4단계 역할 정규화 및 dev 권한 스코프 검증 강화
This commit is contained in:
@@ -266,8 +266,6 @@ func TestGetStats_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
mockKeto := new(devMockKetoService)
|
||||
// mockKeto setup to allow stats view
|
||||
mockKeto.On("CheckPermission", mock.Anything, "u1", "System", "AppManager", "member").Return(true, nil)
|
||||
|
||||
h := &DevHandler{
|
||||
Hydra: &service.HydraAdminService{
|
||||
@@ -281,7 +279,7 @@ func TestGetStats_Success(t *testing.T) {
|
||||
tenantID := "t1"
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("user_profile", &domain.UserProfileResponse{
|
||||
ID: "u1", Role: domain.RoleUser, TenantID: &tenantID,
|
||||
ID: "u1", Role: domain.RoleTenantAdmin, TenantID: &tenantID,
|
||||
})
|
||||
return c.Next()
|
||||
})
|
||||
@@ -297,7 +295,7 @@ func TestGetStats_Success(t *testing.T) {
|
||||
assert.Equal(t, int64(2), res.TotalClients)
|
||||
assert.Equal(t, int64(7), res.AuthFailures)
|
||||
assert.Equal(t, int64(3), res.ActiveSessions)
|
||||
mockKeto.AssertExpectations(t)
|
||||
mockKeto.AssertNotCalled(t, "CheckPermission", mock.Anything, mock.Anything, "System", "AppManager", "member")
|
||||
}
|
||||
|
||||
func TestDevHandler_NoAuditNoAction(t *testing.T) {
|
||||
@@ -323,3 +321,78 @@ func TestDevHandler_NoAuditNoAction(t *testing.T) {
|
||||
assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode)
|
||||
})
|
||||
}
|
||||
|
||||
func TestListAuditLogs_TenantMemberForbidden(t *testing.T) {
|
||||
h := &DevHandler{
|
||||
Hydra: &service.HydraAdminService{AdminURL: "http://hydra.test"},
|
||||
AuditRepo: &mockAuditRepo{},
|
||||
Keto: new(devMockKetoService),
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
tenantID := "tenant-a"
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("user_profile", &domain.UserProfileResponse{
|
||||
ID: "u-member",
|
||||
Role: domain.RoleUser,
|
||||
TenantID: &tenantID,
|
||||
})
|
||||
return c.Next()
|
||||
})
|
||||
app.Get("/api/v1/dev/audit-logs", h.ListAuditLogs)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/dev/audit-logs", nil)
|
||||
resp, _ := app.Test(req, -1)
|
||||
assert.Equal(t, http.StatusForbidden, resp.StatusCode)
|
||||
}
|
||||
|
||||
func TestListAuditLogs_RPAdminScope(t *testing.T) {
|
||||
auditRepo := &mockAuditRepo{
|
||||
logs: []domain.AuditLog{
|
||||
{
|
||||
EventID: "evt-1",
|
||||
EventType: "POST /api/v1/dev/clients",
|
||||
Status: "success",
|
||||
Timestamp: time.Now().UTC(),
|
||||
Details: `{"target_id":"client-allowed","tenant_id":"tenant-a","action":"CREATE_CLIENT"}`,
|
||||
},
|
||||
{
|
||||
EventID: "evt-2",
|
||||
EventType: "POST /api/v1/dev/clients",
|
||||
Status: "success",
|
||||
Timestamp: time.Now().UTC().Add(-time.Minute),
|
||||
Details: `{"target_id":"client-other","tenant_id":"tenant-a","action":"CREATE_CLIENT"}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
h := &DevHandler{
|
||||
Hydra: &service.HydraAdminService{AdminURL: "http://hydra.test"},
|
||||
AuditRepo: auditRepo,
|
||||
Keto: new(devMockKetoService),
|
||||
}
|
||||
|
||||
app := fiber.New()
|
||||
tenantID := "tenant-a"
|
||||
app.Use(func(c *fiber.Ctx) error {
|
||||
c.Locals("user_profile", &domain.UserProfileResponse{
|
||||
ID: "u-rp-admin",
|
||||
Role: domain.RoleRPAdmin,
|
||||
TenantID: &tenantID,
|
||||
Metadata: map[string]any{
|
||||
"managed_client_ids": []any{"client-allowed"},
|
||||
},
|
||||
})
|
||||
return c.Next()
|
||||
})
|
||||
app.Get("/api/v1/dev/audit-logs", h.ListAuditLogs)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/v1/dev/audit-logs?limit=50", nil)
|
||||
resp, _ := app.Test(req, -1)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var result devAuditListResponse
|
||||
_ = json.NewDecoder(resp.Body).Decode(&result)
|
||||
assert.Len(t, result.Items, 1)
|
||||
assert.Equal(t, "evt-1", result.Items[0].EventID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user