Marco-Zheng opened a new issue #2100:
URL: https://github.com/apache/apisix-dashboard/issues/2100


   ### Issue description
   
   It's not bug for that case, but i have a question for add new menu for 
apisix dashboard, i intend to add authority realm, 
   then add role module under handler
   
![image](https://user-images.githubusercontent.com/52538259/130950261-7e311613-efc9-46c0-86ec-c086ec5e29a6.png)
   secondly, i add role.NewHandler under `route.go`
   ```
   factories := []handler.RegisterFactory{
                route.NewHandler,
                ssl.NewHandler,
                ...,
                role.NewHandler,
        }
   ```
   add below role relevant code under storehub.go
   ```
   const (
        HubKeyConsumer     HubKey = "consumer"
        HubKeyRoute        HubKey = "route"
        HubKeyService      HubKey = "service"
        HubKeySsl          HubKey = "ssl"
        HubKeyUpstream     HubKey = "upstream"
        HubKeyScript       HubKey = "script"
        HubKeyGlobalRule   HubKey = "global_rule"
        HubKeyServerInfo   HubKey = "server_info"
        HubKeyPluginConfig HubKey = "plugin_config"
        HubKeyRole         HubKey = "role"
   )
   
   var (
        storeHub = map[HubKey]*GenericStore{}
   )
   
   func InitStore(key HubKey, opt GenericStoreOption) error {
        hubsNeedCheck := map[HubKey]bool{
                HubKeyConsumer:   true,
                HubKeyRoute:      true,
                HubKeySsl:        true,
                HubKeyService:    true,
                HubKeyUpstream:   true,
                HubKeyGlobalRule: true,
                HubKeyRole:       true,
        }
     ....
   }
   ```
   but when i run main.go, the error occured
   ```
   panic: no store with key: role
   
   goroutine 1 [running]:
   github.com/apisix/manager-api/internal/core/store.GetStore(0x1fdc57e, 0x4, 
0x0)
        
/Users/marco/Downloads/workspace/apisix-dashboard/api/internal/core/store/storehub.go:84
 +0x1e5
   github.com/apisix/manager-api/internal/handler/system/role.NewHandler(0x0, 
0x0, 0x0, 0x0)
        
/Users/marco/Downloads/workspace/apisix-dashboard/api/internal/handler/system/role/role.go:40
 +0x4a
   github.com/apisix/manager-api/internal.SetUpRouter(0x0)
        
/Users/marco/Downloads/workspace/apisix-dashboard/api/internal/route.go:86 
+0x867
   github.com/apisix/manager-api/cmd.manageAPI(0x0, 0x0)
        /Users/marco/Downloads/workspace/apisix-dashboard/api/cmd/root.go:133 
+0x648
   github.com/apisix/manager-api/cmd.glob..func1(0x25ed9a0, 0x262d5d0, 0x0, 
0x0, 0x0, 0x0)
        /Users/marco/Downloads/workspace/apisix-dashboard/api/cmd/root.go:52 
+0x2a
   github.com/spf13/cobra.(*Command).execute(0x25ed9a0, 0xc0000321d0, 0x0, 0x0, 
0x0, 0x0)
        /Users/marco/go/pkg/mod/github.com/spf13/[email protected]/command.go:762 
+0xb70
   github.com/spf13/cobra.(*Command).ExecuteC(0x25ed9a0, 0x25ed9a0, 0x0, 0x0)
        /Users/marco/go/pkg/mod/github.com/spf13/[email protected]/command.go:852 
+0x6d2
   github.com/spf13/cobra.(*Command).Execute(0x25ed9a0, 0x0, 0x0)
        /Users/marco/go/pkg/mod/github.com/spf13/[email protected]/command.go:800 
+0x3b
   github.com/apisix/manager-api/cmd.Execute()
        /Users/marco/Downloads/workspace/apisix-dashboard/api/cmd/root.go:80 
+0x3f
   main.main()
        /Users/marco/Downloads/workspace/apisix-dashboard/api/main.go:24 +0x25
   Process exiting with code: 0
   ```
   
   ### Expected behavior
   
   program can run successfully and expose  `/apisix/admin/roles` interface
   
   ### How to Reproduce
   
   1、add below code under handler
   ```
   /*
    * 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 role
   
   import (
        "reflect"
        "strings"
        "time"
   
        "github.com/gin-gonic/gin"
        "github.com/shiningrush/droplet"
        "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"
   )
   
   type Handler struct {
        roleStore store.Interface
   }
   
   func NewHandler() (handler.RouteRegister, error) {
        return &Handler{
                roleStore: store.GetStore(store.HubKeyRole),
        }, nil
   }
   
   func (h *Handler) ApplyRoute(r *gin.Engine) {
        r.GET("/apisix/admin/roles/:role_name", wgin.Wraps(h.Get,
                wrapper.InputType(reflect.TypeOf(GetInput{}))))
        r.GET("/apisix/admin/roles", wgin.Wraps(h.List,
                wrapper.InputType(reflect.TypeOf(ListInput{}))))
        r.PUT("/apisix/admin/roles/:role_name", wgin.Wraps(h.Set,
                wrapper.InputType(reflect.TypeOf(SetInput{}))))
        r.PUT("/apisix/admin/roles", wgin.Wraps(h.Set,
                wrapper.InputType(reflect.TypeOf(SetInput{}))))
        r.DELETE("/apisix/admin/roles/:role_names", wgin.Wraps(h.BatchDelete,
                wrapper.InputType(reflect.TypeOf(BatchDeleteInput{}))))
   }
   
   type GetInput struct {
        RoleName string `auto_read:"role_name,path" validate:"required"`
   }
   
   func (h *Handler) Get(c droplet.Context) (interface{}, error) {
        input := c.Input().(*GetInput)
   
        r, err := h.roleStore.Get(c.Context(), input.RoleName)
        if err != nil {
                return handler.SpecCodeResponse(err), err
        }
        return r, nil
   }
   
   type ListInput struct {
        RoleName string `auto_read:"role_name,query"`
        store.Pagination
   }
   
   func (h *Handler) List(c droplet.Context) (interface{}, error) {
        input := c.Input().(*ListInput)
   
        ret, err := h.roleStore.List(c.Context(), store.ListInput{
                Predicate: func(obj interface{}) bool {
                        if input.RoleName != "" {
                                return 
strings.Contains(obj.(*entity.Role).RoleName, input.RoleName)
                        }
                        return true
                },
                Less: func(i, j interface{}) bool {
                        iBase := i.(*entity.Role)
                        jBase := j.(*entity.Role)
                        if iBase.CreateTime != jBase.CreateTime {
                                return iBase.CreateTime < jBase.CreateTime
                        }
                        if iBase.UpdateTime != jBase.UpdateTime {
                                return iBase.UpdateTime < jBase.UpdateTime
                        }
                        return iBase.RoleName < jBase.RoleName
                },
                PageSize:   input.PageSize,
                PageNumber: input.PageNumber,
        })
        if err != nil {
                return nil, err
        }
   
        return ret, nil
   }
   
   type SetInput struct {
        entity.Role
        RoleName string `auto_read:"role_name,path"`
   }
   
   func (h *Handler) Set(c droplet.Context) (interface{}, error) {
        input := c.Input().(*SetInput)
        if input.RoleName != "" {
                input.Role.RoleName = input.RoleName
        }
   
        // Because the ID of role has been removed,
        // `BaseInfo` is no longer embedded in role's struct,
        // So we need to maintain create_time and update_time separately for 
role
        savedRole, _ := h.roleStore.Get(c.Context(), input.Role.RoleName)
        input.Role.CreateTime = time.Now().Unix()
        input.Role.UpdateTime = time.Now().Unix()
        if savedRole != nil {
                input.Role.CreateTime = savedRole.(*entity.Role).CreateTime
        }
   
        ret, err := h.roleStore.Update(c.Context(), &input.Role, true)
        if err != nil {
                return handler.SpecCodeResponse(err), err
        }
   
        return ret, nil
   }
   
   type BatchDeleteInput struct {
        UserNames string `auto_read:"role_names,path"`
   }
   
   func (h *Handler) BatchDelete(c droplet.Context) (interface{}, error) {
        input := c.Input().(*BatchDeleteInput)
   
        if err := h.roleStore.BatchDelete(c.Context(), 
strings.Split(input.UserNames, ",")); err != nil {
                return handler.SpecCodeResponse(err), err
        }
   
        return nil, nil
   }
   ```
   2、 i add role.NewHandler under `route.go`
   3、add below role relevant code under storehub.go
   ```
   const (
        HubKeyConsumer     HubKey = "consumer"
        HubKeyRoute        HubKey = "route"
        HubKeyService      HubKey = "service"
        HubKeySsl          HubKey = "ssl"
        HubKeyUpstream     HubKey = "upstream"
        HubKeyScript       HubKey = "script"
        HubKeyGlobalRule   HubKey = "global_rule"
        HubKeyServerInfo   HubKey = "server_info"
        HubKeyPluginConfig HubKey = "plugin_config"
        HubKeyRole         HubKey = "role"
   )
   
   var (
        storeHub = map[HubKey]*GenericStore{}
   )
   
   func InitStore(key HubKey, opt GenericStoreOption) error {
        hubsNeedCheck := map[HubKey]bool{
                HubKeyConsumer:   true,
                HubKeyRoute:      true,
                HubKeySsl:        true,
                HubKeyService:    true,
                HubKeyUpstream:   true,
                HubKeyGlobalRule: true,
                HubKeyRole:       true,
        }
     ....
   }
   ```
   
   ### Screenshots
   
   
![image](https://user-images.githubusercontent.com/52538259/130951266-93687445-397c-4b7e-8a60-aafe2f8effb8.png)
   
   
   ### Environment
   
   - apisix-dashboard version, if have: 2.7
   
   
   
   ### Additional context
   
   _No response_


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to