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

tokers pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new b3463fd  fix: delete POST method in /apisix/admin/consumer  (#1109)
b3463fd is described below

commit b3463fda2c949833d5dba2c12c8fe3ab6a25399a
Author: Peter Zhu <[email protected]>
AuthorDate: Fri Dec 25 14:02:09 2020 +0800

    fix: delete POST method in /apisix/admin/consumer  (#1109)
    
    fixed #852
    related #868
---
 api/internal/handler/consumer/consumer.go      |  38 +++---
 api/internal/handler/consumer/consumer_test.go |  87 ++++++------
 api/test/e2e/consumer_test.go                  | 179 +++++++++++++++++++++++++
 api/test/e2e/route_online_debug_test.go        |   2 +-
 api/test/shell/cli_test.sh                     |   4 +-
 web/src/pages/Consumer/service.ts              |   2 +-
 6 files changed, 248 insertions(+), 64 deletions(-)

diff --git a/api/internal/handler/consumer/consumer.go 
b/api/internal/handler/consumer/consumer.go
index 31b7af3..b3ea5a1 100644
--- a/api/internal/handler/consumer/consumer.go
+++ b/api/internal/handler/consumer/consumer.go
@@ -17,17 +17,21 @@
 package consumer
 
 import (
+       "fmt"
+       "net/http"
        "reflect"
        "strings"
 
        "github.com/gin-gonic/gin"
        "github.com/shiningrush/droplet"
+       "github.com/shiningrush/droplet/data"
        "github.com/shiningrush/droplet/wrapper"
        wgin "github.com/shiningrush/droplet/wrapper/gin"
 
        "github.com/apisix/manager-api/internal/core/entity"
        "github.com/apisix/manager-api/internal/core/store"
        "github.com/apisix/manager-api/internal/handler"
+       "github.com/apisix/manager-api/internal/utils"
 )
 
 type Handler struct {
@@ -45,12 +49,10 @@ func (h *Handler) ApplyRoute(r *gin.Engine) {
                wrapper.InputType(reflect.TypeOf(GetInput{}))))
        r.GET("/apisix/admin/consumers", wgin.Wraps(h.List,
                wrapper.InputType(reflect.TypeOf(ListInput{}))))
-       r.POST("/apisix/admin/consumers", wgin.Wraps(h.Create,
-               wrapper.InputType(reflect.TypeOf(entity.Consumer{}))))
-       r.PUT("/apisix/admin/consumers/:username", wgin.Wraps(h.Update,
-               wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
-       r.PUT("/apisix/admin/consumers", wgin.Wraps(h.Update,
-               wrapper.InputType(reflect.TypeOf(UpdateInput{}))))
+       r.PUT("/apisix/admin/consumers/:username", wgin.Wraps(h.Set,
+               wrapper.InputType(reflect.TypeOf(SetInput{}))))
+       r.PUT("/apisix/admin/consumers", wgin.Wraps(h.Set,
+               wrapper.InputType(reflect.TypeOf(SetInput{}))))
        r.DELETE("/apisix/admin/consumers/:usernames", wgin.Wraps(h.BatchDelete,
                wrapper.InputType(reflect.TypeOf(BatchDeleteInput{}))))
 }
@@ -128,25 +130,17 @@ func (h *Handler) List(c droplet.Context) (interface{}, 
error) {
        return ret, nil
 }
 
-func (h *Handler) Create(c droplet.Context) (interface{}, error) {
-       input := c.Input().(*entity.Consumer)
-       input.ID = input.Username
-
-       ensurePluginsDefValue(input.Plugins)
-       if err := h.consumerStore.Create(c.Context(), input); err != nil {
-               return handler.SpecCodeResponse(err), err
-       }
-
-       return nil, nil
-}
-
-type UpdateInput struct {
-       Username string `auto_read:"username,path"`
+type SetInput struct {
        entity.Consumer
+       Username string `auto_read:"username,path"`
 }
 
-func (h *Handler) Update(c droplet.Context) (interface{}, error) {
-       input := c.Input().(*UpdateInput)
+func (h *Handler) Set(c droplet.Context) (interface{}, error) {
+       input := c.Input().(*SetInput)
+       if input.ID != nil && utils.InterfaceToString(input.ID) != 
input.Username {
+               return &data.SpecCodeResponse{StatusCode: 
http.StatusBadRequest},
+                       fmt.Errorf("consumer's id and username must be a same 
value")
+       }
        if input.Username != "" {
                input.Consumer.Username = input.Username
        }
diff --git a/api/internal/handler/consumer/consumer_test.go 
b/api/internal/handler/consumer/consumer_test.go
index 6a82154..5c80d90 100644
--- a/api/internal/handler/consumer/consumer_test.go
+++ b/api/internal/handler/consumer/consumer_test.go
@@ -20,14 +20,16 @@ package consumer
 import (
        "context"
        "fmt"
-       "github.com/apisix/manager-api/internal/core/entity"
-       "github.com/apisix/manager-api/internal/core/store"
+       "net/http"
+       "testing"
+
        "github.com/shiningrush/droplet"
        "github.com/shiningrush/droplet/data"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/mock"
-       "net/http"
-       "testing"
+
+       "github.com/apisix/manager-api/internal/core/entity"
+       "github.com/apisix/manager-api/internal/core/store"
 )
 
 func TestHandler_Get(t *testing.T) {
@@ -172,31 +174,35 @@ func TestHandler_List(t *testing.T) {
 func TestHandler_Create(t *testing.T) {
        tests := []struct {
                caseDesc   string
-               giveInput  *entity.Consumer
+               giveInput  *SetInput
                giveCtx    context.Context
                giveErr    error
                wantErr    error
-               wantInput  *entity.Consumer
+               wantInput  *SetInput
                wantRet    interface{}
                wantCalled bool
        }{
                {
                        caseDesc: "normal",
-                       giveInput: &entity.Consumer{
-                               Username: "name",
-                               Plugins: map[string]interface{}{
-                                       "jwt-auth": map[string]interface{}{},
+                       giveInput: &SetInput{
+                               Consumer: entity.Consumer{
+                                       Username: "name",
+                                       Plugins: map[string]interface{}{
+                                               "jwt-auth": 
map[string]interface{}{},
+                                       },
                                },
                        },
                        giveCtx: context.WithValue(context.Background(), 
"test", "value"),
-                       wantInput: &entity.Consumer{
-                               BaseInfo: entity.BaseInfo{
-                                       ID: "name",
-                               },
-                               Username: "name",
-                               Plugins: map[string]interface{}{
-                                       "jwt-auth": map[string]interface{}{
-                                               "exp": 86400,
+                       wantInput: &SetInput{
+                               Consumer: entity.Consumer{
+                                       BaseInfo: entity.BaseInfo{
+                                               ID: "name",
+                                       },
+                                       Username: "name",
+                                       Plugins: map[string]interface{}{
+                                               "jwt-auth": 
map[string]interface{}{
+                                                       "exp": 86400,
+                                               },
                                        },
                                },
                        },
@@ -205,23 +211,27 @@ func TestHandler_Create(t *testing.T) {
                },
                {
                        caseDesc: "store create failed",
-                       giveInput: &entity.Consumer{
-                               Username: "name",
-                               Plugins: map[string]interface{}{
-                                       "jwt-auth": map[string]interface{}{
-                                               "exp": 5000,
+                       giveInput: &SetInput{
+                               Consumer: entity.Consumer{
+                                       Username: "name",
+                                       Plugins: map[string]interface{}{
+                                               "jwt-auth": 
map[string]interface{}{
+                                                       "exp": 5000,
+                                               },
                                        },
                                },
                        },
                        giveErr: fmt.Errorf("create failed"),
-                       wantInput: &entity.Consumer{
-                               BaseInfo: entity.BaseInfo{
-                                       ID: "name",
-                               },
-                               Username: "name",
-                               Plugins: map[string]interface{}{
-                                       "jwt-auth": map[string]interface{}{
-                                               "exp": 5000,
+                       wantInput: &SetInput{
+                               Consumer: entity.Consumer{
+                                       BaseInfo: entity.BaseInfo{
+                                               ID: "name",
+                                       },
+                                       Username: "name",
+                                       Plugins: map[string]interface{}{
+                                               "jwt-auth": 
map[string]interface{}{
+                                                       "exp": 5000,
+                                               },
                                        },
                                },
                        },
@@ -237,17 +247,18 @@ func TestHandler_Create(t *testing.T) {
                t.Run(tc.caseDesc, func(t *testing.T) {
                        methodCalled := true
                        mStore := &store.MockInterface{}
-                       mStore.On("Create", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                       mStore.On("Update", mock.Anything, mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
                                methodCalled = true
                                assert.Equal(t, tc.giveCtx, args.Get(0))
-                               assert.Equal(t, tc.wantInput, args.Get(1))
+                               assert.Equal(t, &tc.wantInput.Consumer, 
args.Get(1))
+                               assert.True(t, args.Bool(2))
                        }).Return(tc.giveErr)
 
                        h := Handler{consumerStore: mStore}
                        ctx := droplet.NewContext()
                        ctx.SetInput(tc.giveInput)
                        ctx.SetContext(tc.giveCtx)
-                       ret, err := h.Create(ctx)
+                       ret, err := h.Set(ctx)
                        assert.Equal(t, tc.wantCalled, methodCalled)
                        assert.Equal(t, tc.wantRet, ret)
                        assert.Equal(t, tc.wantErr, err)
@@ -258,7 +269,7 @@ func TestHandler_Create(t *testing.T) {
 func TestHandler_Update(t *testing.T) {
        tests := []struct {
                caseDesc   string
-               giveInput  *UpdateInput
+               giveInput  *SetInput
                giveCtx    context.Context
                giveErr    error
                wantErr    error
@@ -268,7 +279,7 @@ func TestHandler_Update(t *testing.T) {
        }{
                {
                        caseDesc: "normal",
-                       giveInput: &UpdateInput{
+                       giveInput: &SetInput{
                                Username: "name",
                                Consumer: entity.Consumer{
                                        Plugins: map[string]interface{}{
@@ -295,7 +306,7 @@ func TestHandler_Update(t *testing.T) {
                },
                {
                        caseDesc: "store update failed",
-                       giveInput: &UpdateInput{
+                       giveInput: &SetInput{
                                Username: "name",
                                Consumer: entity.Consumer{
                                        Plugins: map[string]interface{}{
@@ -338,7 +349,7 @@ func TestHandler_Update(t *testing.T) {
                        ctx := droplet.NewContext()
                        ctx.SetInput(tc.giveInput)
                        ctx.SetContext(tc.giveCtx)
-                       ret, err := h.Update(ctx)
+                       ret, err := h.Set(ctx)
                        assert.Equal(t, tc.wantCalled, methodCalled)
                        assert.Equal(t, tc.wantRet, ret)
                        assert.Equal(t, tc.wantErr, err)
diff --git a/api/test/e2e/consumer_test.go b/api/test/e2e/consumer_test.go
index d607957..2edfdf3 100644
--- a/api/test/e2e/consumer_test.go
+++ b/api/test/e2e/consumer_test.go
@@ -27,6 +27,185 @@ import (
        "github.com/tidwall/gjson"
 )
 
+func TestConsumer_Create_And_Get(t *testing.T) {
+       tests := []HttpTestCase{
+               {
+                       Desc:         "check consumer is not exist",
+                       Object:       ManagerApiExpect(t),
+                       Path:         "/apisix/admin/consumers/consumer_1",
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusNotFound,
+                       ExpectBody:   "data not found",
+               },
+               {
+                       Desc:         "check consumer is not exist",
+                       Object:       ManagerApiExpect(t),
+                       Path:         "/apisix/admin/consumers/consumer_2",
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusNotFound,
+                       ExpectBody:   "data not found",
+               },
+               {
+                       Desc:   "create consumer by POST method",
+                       Object: ManagerApiExpect(t),
+                       Path:   "/apisix/admin/consumers",
+                       Method: http.MethodPost,
+                       Body: `{
+                               "username": "consumer_1",
+                               "plugins": {
+                                       "limit-count": {
+                                       "count": 2,
+                                       "time_window": 60,
+                                       "rejected_code": 503,
+                                       "key": "remote_addr"
+                                       }
+                               },
+                               "desc": "test description"
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusNotFound,
+                       ExpectBody:   "404 page not found",
+               },
+               {
+                       Desc:   "create consumer by PUT method",
+                       Object: ManagerApiExpect(t),
+                       Path:   "/apisix/admin/consumers",
+                       Method: http.MethodPut,
+                       Body: `{
+                               "username": "consumer_2",
+                               "plugins": {
+                                       "limit-count": {
+                                       "count": 2,
+                                       "time_window": 60,
+                                       "rejected_code": 503,
+                                       "key": "remote_addr"
+                                       }
+                               },
+                               "desc": "test description"
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "\"code\":0",
+                       Sleep:        sleepTime,
+               },
+               {
+                       Desc:         "get consumer",
+                       Object:       ManagerApiExpect(t),
+                       Path:         "/apisix/admin/consumers/consumer_2",
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "\"username\":\"consumer_2\"",
+               },
+               {
+                       Desc:   "create consumer without username",
+                       Object: ManagerApiExpect(t),
+                       Path:   "/apisix/admin/consumers",
+                       Method: http.MethodPut,
+                       Body: `{
+                               "plugins": {
+                                       "limit-count": {
+                                       "count": 2,
+                                       "time_window": 60,
+                                       "rejected_code": 503,
+                                       "key": "remote_addr"
+                                       }
+                               },
+                               "desc": "test description"
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusBadRequest,
+                       ExpectBody:   "\"code\":10000",
+               },
+               {
+                       Desc:         "delete consumer",
+                       Object:       ManagerApiExpect(t),
+                       Path:         "/apisix/admin/consumers/consumer_2",
+                       Method:       http.MethodDelete,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "\"code\":0",
+               },
+       }
+
+       for _, tc := range tests {
+               testCaseCheck(tc, t)
+       }
+}
+
+func TestConsumer_Update_And_Get(t *testing.T) {
+       tests := []HttpTestCase{
+               {
+                       Desc:   "create consumer by PUT",
+                       Object: ManagerApiExpect(t),
+                       Path:   "/apisix/admin/consumers",
+                       Method: http.MethodPut,
+                       Body: `{
+                               "username": "consumer_3",
+                               "plugins": {
+                                       "limit-count": {
+                                       "count": 2,
+                                       "time_window": 60,
+                                       "rejected_code": 503,
+                                       "key": "remote_addr"
+                                       }
+                               },
+                               "desc": "test description"
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "\"code\":0",
+                       Sleep:        sleepTime,
+               },
+               {
+                       Desc:   "update consumer by PUT",
+                       Object: ManagerApiExpect(t),
+                       Path:   "/apisix/admin/consumers/consumer_3",
+                       Method: http.MethodPut,
+                       Body: `{
+                               "username": "consumer_3",
+                               "plugins": {
+                                       "limit-count": {
+                                       "count": 2,
+                                       "time_window": 60,
+                                       "rejected_code": 504,
+                                       "key": "remote_addr"
+                                       }
+                               },
+                               "desc": "test description"
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "\"code\":0",
+                       Sleep:        sleepTime,
+               },
+               {
+                       Desc:         "get consumer",
+                       Object:       ManagerApiExpect(t),
+                       Path:         "/apisix/admin/consumers/consumer_3",
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "\"rejected_code\":504",
+               },
+               {
+                       Desc:         "delete consumer",
+                       Object:       ManagerApiExpect(t),
+                       Path:         "/apisix/admin/consumers/consumer_3",
+                       Method:       http.MethodDelete,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "\"code\":0",
+               },
+       }
+
+       for _, tc := range tests {
+               testCaseCheck(tc, t)
+       }
+}
+
 func TestConsumer_with_key_auth(t *testing.T) {
        tests := []HttpTestCase{
                {
diff --git a/api/test/e2e/route_online_debug_test.go 
b/api/test/e2e/route_online_debug_test.go
index 377af3f..e8fc679 100644
--- a/api/test/e2e/route_online_debug_test.go
+++ b/api/test/e2e/route_online_debug_test.go
@@ -320,7 +320,7 @@ func TestRoute_Online_Debug_Route_With_Basic_Auth(t 
*testing.T) {
                        Desc:   "create consumer",
                        Object: ManagerApiExpect(t),
                        Path:   "/apisix/admin/consumers",
-                       Method: http.MethodPost,
+                       Method: http.MethodPut,
                        Body: `{
                                "username": "jack",
                                "plugins": {
diff --git a/api/test/shell/cli_test.sh b/api/test/shell/cli_test.sh
index 411130b..da20c56 100755
--- a/api/test/shell/cli_test.sh
+++ b/api/test/shell/cli_test.sh
@@ -95,7 +95,7 @@ if [[ `grep -c "INFO" ./error.log` -eq '0' ]]; then
     exit 1
 fi
 
-# run on a different path 
+# run on a different path
 workDir=$(pwd)
 rm -rf html
 mkdir html
@@ -215,7 +215,7 @@ if [ -z "${token}" ]; then
 fi
 
 # more validation to make sure it's ok to access etcd
-resp=$(curl -ig http://127.0.0.1:9000/apisix/admin/consumers -i -H 
"Authorization: $token" -d '{"username":"etcd_basic_auth_test"}')
+resp=$(curl -ig -XPUT http://127.0.0.1:9000/apisix/admin/consumers -i -H 
"Authorization: $token" -d '{"username":"etcd_basic_auth_test"}')
 respCode=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "code" | sed 
's/:/\n/g' | sed '1d')
 respMessage=$(echo "${resp}" | sed 's/{/\n/g'| sed 's/,/\n/g' | grep "message" 
| sed 's/:/\n/g' | sed '1d')
 if [ "$respCode" != "0" ] || [ $respMessage != "\"\"" ]; then
diff --git a/web/src/pages/Consumer/service.ts 
b/web/src/pages/Consumer/service.ts
index f4289c6..f95aa31 100644
--- a/web/src/pages/Consumer/service.ts
+++ b/web/src/pages/Consumer/service.ts
@@ -33,7 +33,7 @@ export const fetchItem = (username: string) =>
 
 export const create = (data: ConsumerModule.Entity) =>
   request('/consumers', {
-    method: 'POST',
+    method: 'PUT',
     data,
   });
 

Reply via email to