This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new 170a318  SCB-2176 Add response filter (#1005)
170a318 is described below

commit 170a3185652a3ab8a02b7959f9c06794b900a829
Author: little-cui <[email protected]>
AuthorDate: Wed May 26 10:27:36 2021 +0800

    SCB-2176 Add response filter (#1005)
    
    * SCB-2176 Add response filter
    
    * SCB-2176 Resolve comments
    
    * SCB-2176 Resolve comments
    
    * SCB-2176 Resolve comments
---
 server/handler/auth/auth.go                        |  25 +++-
 server/resource/register.go                        |   2 +-
 .../{resource/register.go => response/filter.go}   |  24 ++--
 server/response/response.go                        | 123 ++++++++++++++++++
 server/response/response_test.go                   | 137 +++++++++++++++++++++
 5 files changed, 290 insertions(+), 21 deletions(-)

diff --git a/server/handler/auth/auth.go b/server/handler/auth/auth.go
index bfbabce..32b5597 100644
--- a/server/handler/auth/auth.go
+++ b/server/handler/auth/auth.go
@@ -18,6 +18,9 @@
 package auth
 
 import (
+       "github.com/apache/servicecomb-service-center/pkg/util"
+       "github.com/apache/servicecomb-service-center/server/response"
+       "github.com/apache/servicecomb-service-center/server/rest/controller"
        "net/http"
 
        "github.com/apache/servicecomb-service-center/pkg/chain"
@@ -27,6 +30,8 @@ import (
        "github.com/go-chassis/cari/discovery"
 )
 
+const CtxResourceLabels util.CtxKey = "_resource_labels"
+
 type Handler struct {
 }
 
@@ -43,16 +48,24 @@ func (h *Handler) Handle(i *chain.Invocation) {
                if !ret.OK {
                        return
                }
-
-               obj := i.Context().Value(rest.CtxResponseObject)
+               apiPath, obj := 
i.Context().Value(rest.CtxMatchPattern).(string),
+                       i.Context().Value(rest.CtxResponseObject)
                if obj == nil {
                        return
                }
 
-               // TODO filter and rewrite here!
-               // data, _ := json.Marshal(obj)
-               // w := 
i.Context().Value(rest.CtxResponse).(http.ResponseWriter)
-               // w.Write(data)
+               labels, ok := 
i.Context().Value(CtxResourceLabels).([]map[string]string)
+               if !ok {
+                       return
+               }
+               if len(labels) == 0 {
+                       // all allowed
+                       return
+               }
+               obj = response.Filter(apiPath, obj, labels)
+
+               w := i.Context().Value(rest.CtxResponse).(http.ResponseWriter)
+               controller.WriteResponse(w, r, nil, obj)
        }))
 }
 
diff --git a/server/resource/register.go b/server/resource/register.go
index be0ceea..026b770 100644
--- a/server/resource/register.go
+++ b/server/resource/register.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package v4
+package resource
 
 import (
        roa "github.com/apache/servicecomb-service-center/pkg/rest"
diff --git a/server/resource/register.go b/server/response/filter.go
similarity index 62%
copy from server/resource/register.go
copy to server/response/filter.go
index be0ceea..667c280 100644
--- a/server/resource/register.go
+++ b/server/response/filter.go
@@ -15,23 +15,19 @@
  * limitations under the License.
  */
 
-package v4
+package response
 
-import (
-       roa "github.com/apache/servicecomb-service-center/pkg/rest"
-       v1 "github.com/apache/servicecomb-service-center/server/resource/v1"
-       v4 "github.com/apache/servicecomb-service-center/server/resource/v4"
-       "github.com/apache/servicecomb-service-center/server/service/rbac"
-)
+var filters = map[string]FilterFunc{}
 
-func init() {
-       initRouter()
+type FilterFunc func(obj interface{}, filters []map[string]string) interface{}
+
+func RegisterFilter(apiPath string, f FilterFunc) {
+       filters[apiPath] = f
 }
 
-func initRouter() {
-       if rbac.Enabled() {
-               roa.RegisterServant(&v4.AuthResource{})
-               roa.RegisterServant(&v4.RoleResource{})
+func Filter(apiPath string, obj interface{}, labels []map[string]string) 
interface{} {
+       if f, ok := filters[apiPath]; ok {
+               return f(obj, labels)
        }
-       roa.RegisterServant(&v1.Governance{})
+       return obj
 }
diff --git a/server/response/response.go b/server/response/response.go
new file mode 100644
index 0000000..3c01f10
--- /dev/null
+++ b/server/response/response.go
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package response
+
+import (
+       "github.com/go-chassis/cari/discovery"
+)
+
+func init() {
+       RegisterFilter("/v4/:project/registry/microservices", 
MicroserviceListFilter)
+       //response.RegisterFilter("/v4/:project/registry/instances", )
+       
RegisterFilter("/v4/:project/registry/microservices/:providerId/consumers", 
ProvidersListFilter)
+       
RegisterFilter("/v4/:project/registry/microservices/:consumerId/providers", 
ConsumersListFilter)
+       // control panel apis
+       RegisterFilter("/v4/:project/govern/microservices", 
MicroServiceInfoListFilter)
+       RegisterFilter("/v4/:project/govern/apps", AppIdListFilter)
+}
+
+func MicroserviceListFilter(obj interface{}, labels []map[string]string) 
interface{} {
+       servicesResponse, ok := obj.(*discovery.GetServicesResponse)
+       if !ok {
+               return obj
+       }
+       servicesResponse.Services = 
filterMicroservices(servicesResponse.Services, labels)
+       return servicesResponse
+}
+
+func filterMicroservices(sources []*discovery.MicroService, labelsList 
[]map[string]string) []*discovery.MicroService {
+       var services []*discovery.MicroService
+       for _, service := range sources {
+               for _, labels := range labelsList {
+                       if env, ok := labels["environment"]; ok && 
service.Environment != env {
+                               continue
+                       }
+                       if app, ok := labels["appId"]; ok && service.AppId != 
app {
+                               continue
+                       }
+                       if name, ok := labels["serviceName"]; ok && 
service.ServiceName != name {
+                               continue
+                       }
+                       services = append(services, service)
+                       break
+               }
+       }
+       return services
+}
+
+func ProvidersListFilter(obj interface{}, labels []map[string]string) 
interface{} {
+       servicesResponse, ok := obj.(*discovery.GetConDependenciesResponse)
+       if !ok {
+               return obj
+       }
+       servicesResponse.Providers = 
filterMicroservices(servicesResponse.Providers, labels)
+       return servicesResponse
+}
+
+func ConsumersListFilter(obj interface{}, labels []map[string]string) 
interface{} {
+       servicesResponse, ok := obj.(*discovery.GetProDependenciesResponse)
+       if !ok {
+               return obj
+       }
+       servicesResponse.Consumers = 
filterMicroservices(servicesResponse.Consumers, labels)
+       return servicesResponse
+}
+
+func MicroServiceInfoListFilter(obj interface{}, labelsList 
[]map[string]string) interface{} {
+       servicesResponse, ok := obj.(*discovery.GetServicesInfoResponse)
+       if !ok {
+               return obj
+       }
+       var services []*discovery.ServiceDetail
+       for _, service := range servicesResponse.AllServicesDetail {
+               for _, labels := range labelsList {
+                       if env, ok := labels["environment"]; ok && 
service.MicroService.Environment != env {
+                               continue
+                       }
+                       if app, ok := labels["appId"]; ok && 
service.MicroService.AppId != app {
+                               continue
+                       }
+                       if name, ok := labels["serviceName"]; ok && 
service.MicroService.ServiceName != name {
+                               continue
+                       }
+                       services = append(services, service)
+                       break
+               }
+       }
+       servicesResponse.AllServicesDetail = services
+       return servicesResponse
+}
+
+func AppIdListFilter(obj interface{}, labelsList []map[string]string) 
interface{} {
+       appsResponse, ok := obj.(*discovery.GetAppsResponse)
+       if !ok {
+               return obj
+       }
+       var apps []string
+       for _, appId := range appsResponse.AppIds {
+               for _, labels := range labelsList {
+                       if app, ok := labels["appId"]; ok && appId != app {
+                               continue
+                       }
+                       apps = append(apps, appId)
+                       break
+               }
+       }
+       appsResponse.AppIds = apps
+       return appsResponse
+}
diff --git a/server/response/response_test.go b/server/response/response_test.go
new file mode 100644
index 0000000..233a764
--- /dev/null
+++ b/server/response/response_test.go
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package response_test
+
+import (
+       "github.com/apache/servicecomb-service-center/server/response"
+       "github.com/go-chassis/cari/discovery"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func TestMicroServiceInfoListFilter(t *testing.T) {
+       t.Run("obj is invalid, should do nothing", func(t *testing.T) {
+               other := &discovery.MicroService{}
+               assert.Equal(t, other, 
response.MicroServiceInfoListFilter(other, nil))
+       })
+
+       t.Run("labels is empty, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+                       AllServicesDetail: []*discovery.ServiceDetail{
+                               {MicroService: 
&discovery.MicroService{ServiceName: "A"}}, {MicroService: 
&discovery.MicroService{ServiceName: "B"}},
+                       },
+               }, nil)
+               assert.Equal(t, 0, 
len(rs.(*discovery.GetServicesInfoResponse).AllServicesDetail))
+       })
+
+       t.Run("not match name, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+                       AllServicesDetail: []*discovery.ServiceDetail{
+                               {MicroService: 
&discovery.MicroService{ServiceName: "A"}}, {MicroService: 
&discovery.MicroService{ServiceName: "B"}},
+                       },
+               }, []map[string]string{{"serviceName": "NONE"}})
+               assert.Equal(t, 0, 
len(rs.(*discovery.GetServicesInfoResponse).AllServicesDetail))
+       })
+
+       t.Run("match A, should return A resources", func(t *testing.T) {
+               rs := 
response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+                       AllServicesDetail: []*discovery.ServiceDetail{
+                               {MicroService: 
&discovery.MicroService{ServiceName: "A"}}, {MicroService: 
&discovery.MicroService{ServiceName: "B"}},
+                       },
+               }, []map[string]string{{"serviceName": "A"}})
+               mss := rs.(*discovery.GetServicesInfoResponse).AllServicesDetail
+               assert.Equal(t, 1, len(mss))
+               assert.Equal(t, "A", mss[0].MicroService.ServiceName)
+       })
+
+       t.Run("not match name & appId, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+                       AllServicesDetail: []*discovery.ServiceDetail{
+                               {MicroService: 
&discovery.MicroService{ServiceName: "A"}}, {MicroService: 
&discovery.MicroService{ServiceName: "B"}},
+                       },
+               }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+               mss := rs.(*discovery.GetServicesInfoResponse).AllServicesDetail
+               assert.Equal(t, 0, len(mss))
+       })
+
+       t.Run("match name & appId, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroServiceInfoListFilter(&discovery.GetServicesInfoResponse{
+                       AllServicesDetail: []*discovery.ServiceDetail{
+                               {MicroService: &discovery.MicroService{AppId: 
"A", ServiceName: "A"}}, {MicroService: &discovery.MicroService{ServiceName: 
"B"}},
+                       },
+               }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+               mss := rs.(*discovery.GetServicesInfoResponse).AllServicesDetail
+               assert.Equal(t, 1, len(mss))
+       })
+}
+
+func TestMicroserviceListFilter(t *testing.T) {
+       t.Run("obj is invalid, should do nothing", func(t *testing.T) {
+               other := &discovery.MicroService{}
+               assert.Equal(t, other, response.MicroserviceListFilter(other, 
nil))
+       })
+
+       t.Run("labels is empty, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroserviceListFilter(&discovery.GetServicesResponse{
+                       Services: []*discovery.MicroService{
+                               {ServiceName: "A"}, {ServiceName: "B"},
+                       },
+               }, nil)
+               assert.Equal(t, 0, 
len(rs.(*discovery.GetServicesResponse).Services))
+       })
+
+       t.Run("not match name, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroserviceListFilter(&discovery.GetServicesResponse{
+                       Services: []*discovery.MicroService{
+                               {ServiceName: "A"}, {ServiceName: "B"},
+                       },
+               }, []map[string]string{{"serviceName": "NONE"}})
+               assert.Equal(t, 0, 
len(rs.(*discovery.GetServicesResponse).Services))
+       })
+
+       t.Run("match A, should return A resources", func(t *testing.T) {
+               rs := 
response.MicroserviceListFilter(&discovery.GetServicesResponse{
+                       Services: []*discovery.MicroService{
+                               {ServiceName: "A"}, {ServiceName: "B"},
+                       },
+               }, []map[string]string{{"serviceName": "A"}})
+               mss := rs.(*discovery.GetServicesResponse).Services
+               assert.Equal(t, 1, len(mss))
+               assert.Equal(t, "A", mss[0].ServiceName)
+       })
+
+       t.Run("not match name & appId, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroserviceListFilter(&discovery.GetServicesResponse{
+                       Services: []*discovery.MicroService{
+                               {ServiceName: "A"}, {ServiceName: "B"},
+                       },
+               }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+               mss := rs.(*discovery.GetServicesResponse).Services
+               assert.Equal(t, 0, len(mss))
+       })
+
+       t.Run("match name & appId, should return empty resources", func(t 
*testing.T) {
+               rs := 
response.MicroserviceListFilter(&discovery.GetServicesResponse{
+                       Services: []*discovery.MicroService{
+                               {AppId: "A", ServiceName: "A"}, {ServiceName: 
"B"},
+                       },
+               }, []map[string]string{{"serviceName": "A", "appId": "A"}})
+               mss := rs.(*discovery.GetServicesResponse).Services
+               assert.Equal(t, 1, len(mss))
+       })
+}

Reply via email to