update validate
This commit is contained in:
parent
abe934cef3
commit
e5d119885e
|
@ -1,7 +1,6 @@
|
|||
package biz
|
||||
|
||||
import (
|
||||
"infini.sh/console/internal/core"
|
||||
"infini.sh/console/model/rbac"
|
||||
)
|
||||
|
||||
|
@ -18,8 +17,6 @@ type Token struct {
|
|||
|
||||
var TokenMap = make(map[string]Token)
|
||||
|
||||
var EsApiRoutes = core.NewRouter()
|
||||
|
||||
|
||||
type RolePermission struct {
|
||||
Platform []string `json:"platform,omitempty"`
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"infini.sh/console/internal/biz/enum"
|
||||
"infini.sh/console/model/rbac"
|
||||
httprouter "infini.sh/framework/core/api/router"
|
||||
"infini.sh/framework/core/util"
|
||||
"src/github.com/golang-jwt/jwt"
|
||||
|
@ -44,6 +45,11 @@ func NewClusterRequest(ps httprouter.Params, privilege []string) ClusterRequest
|
|||
}
|
||||
}
|
||||
|
||||
func ValidateElasticsearch(req rbac.ElasticsearchPrivilege, roleNames []string) (err error) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) {
|
||||
|
||||
userClusterMap := make(map[string]struct{})
|
||||
|
@ -60,7 +66,7 @@ func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) {
|
|||
for _, val := range req.Privilege {
|
||||
position := strings.Index(val, ".")
|
||||
if position == -1 {
|
||||
err = errors.New("invalid privilege parmeter")
|
||||
err = errors.New("invalid privilege parameter")
|
||||
return err
|
||||
}
|
||||
prefix := val[:position]
|
||||
|
@ -71,42 +77,43 @@ func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) {
|
|||
return err
|
||||
}
|
||||
if util.StringInArray(privilege, prefix+".*") {
|
||||
return nil
|
||||
continue
|
||||
}
|
||||
if util.StringInArray(privilege, val) {
|
||||
return nil
|
||||
continue
|
||||
}
|
||||
|
||||
return fmt.Errorf("no index api permission: %s", val)
|
||||
}
|
||||
}
|
||||
|
||||
return errors.New("no index api permission")
|
||||
return nil
|
||||
}
|
||||
func ValidateCluster(req ClusterRequest, userRole RolePermission) (err error) {
|
||||
userClusterMap := make(map[string]struct{})
|
||||
for _, v := range userRole.Cluster {
|
||||
userClusterMap[v] = struct{}{}
|
||||
}
|
||||
func ValidateCluster(req ClusterRequest, roleNames []string) (err error) {
|
||||
userClusterMap := GetRoleClusterMap(roleNames)
|
||||
for _, v := range req.Cluster {
|
||||
if _, ok := userClusterMap[v]; !ok {
|
||||
err = errors.New("no cluster permission")
|
||||
userClusterPermissions, ok := userClusterMap[v]
|
||||
if !ok && userClusterMap["*"] == nil{
|
||||
err = fmt.Errorf("no cluster[%s] permission", v)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// if include api.* for example: cat.* , return nil
|
||||
for _, privilege := range req.Privilege {
|
||||
prefix := privilege[:strings.Index(privilege, ".")]
|
||||
|
||||
if util.StringInArray(userRole.ClusterPrivilege, prefix+".*") {
|
||||
return nil
|
||||
if util.StringInArray(userClusterPermissions, "*") {
|
||||
continue
|
||||
}
|
||||
if util.StringInArray(userRole.ClusterPrivilege, privilege) {
|
||||
return nil
|
||||
// if include api.* for example: cat.* , return nil
|
||||
for _, privilege := range req.Privilege {
|
||||
prefix := privilege[:strings.Index(privilege, ".")]
|
||||
|
||||
if util.StringInArray(userClusterPermissions, prefix+".*") {
|
||||
continue
|
||||
}
|
||||
if util.StringInArray(userClusterPermissions, privilege) {
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("no cluster api permission: %s", privilege)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
return errors.New("no cluster api permission")
|
||||
}
|
||||
|
||||
func CombineUserRoles(roleNames []string) RolePermission {
|
||||
|
@ -139,26 +146,43 @@ func CombineUserRoles(roleNames []string) RolePermission {
|
|||
newRole.IndexPrivilege = m
|
||||
return newRole
|
||||
}
|
||||
func FilterCluster(roles []string, cluster []string) []string {
|
||||
newRole := CombineUserRoles(roles)
|
||||
userClusterMap := make(map[string]struct{}, 0)
|
||||
for _, v := range newRole.Cluster {
|
||||
userClusterMap[v] = struct{}{}
|
||||
}
|
||||
realCluster := make([]string, 0)
|
||||
for _, v := range cluster {
|
||||
if _, ok := userClusterMap[v]; ok {
|
||||
realCluster = append(realCluster, v)
|
||||
func GetRoleClusterMap(roles []string) map[string][]string {
|
||||
userClusterMap := make(map[string][]string, 0)
|
||||
for _, roleName := range roles {
|
||||
role, ok := RoleMap[roleName]
|
||||
if ok {
|
||||
for _, ic := range role.Privilege.Elasticsearch.Cluster.Resources {
|
||||
userClusterMap[ic.ID] = append(userClusterMap[ic.ID], role.Privilege.Elasticsearch.Cluster.Permissions...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return userClusterMap
|
||||
}
|
||||
func GetRoleCluster(roles []string) []string {
|
||||
userClusterMap := GetRoleClusterMap(roles)
|
||||
realCluster := make([]string, 0, len(userClusterMap))
|
||||
for k, _ := range userClusterMap {
|
||||
realCluster = append(realCluster, k)
|
||||
}
|
||||
return realCluster
|
||||
}
|
||||
func FilterIndex(roles []string, index []string) []string {
|
||||
realIndex := make([]string, 0)
|
||||
newRole := CombineUserRoles(roles)
|
||||
for _, v := range index {
|
||||
if _, ok := newRole.IndexPrivilege[v]; ok {
|
||||
realIndex = append(realIndex, v)
|
||||
func GetRoleIndex(roles, clusterIDs []string) map[string][]string {
|
||||
userClusterMap := make(map[string]struct{}, len(clusterIDs))
|
||||
for _, clusterID := range clusterIDs {
|
||||
userClusterMap[clusterID] = struct{}{}
|
||||
}
|
||||
realIndex := map[string][]string{}
|
||||
for _, roleName := range roles {
|
||||
role, ok := RoleMap[roleName]
|
||||
if ok {
|
||||
for _, ic := range role.Privilege.Elasticsearch.Cluster.Resources {
|
||||
if _, ok = userClusterMap[ic.ID]; !ok {
|
||||
continue
|
||||
}
|
||||
for _, ip := range role.Privilege.Elasticsearch.Index {
|
||||
realIndex[ic.ID] = append(realIndex[ic.ID], ip.Name...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return realIndex
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
roots map[string]*node
|
||||
handlers map[string]string
|
||||
}
|
||||
|
||||
func NewRouter() *Router {
|
||||
return &Router{
|
||||
roots: make(map[string]*node),
|
||||
handlers: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// Only one * is allowed
|
||||
func parsePattern(pattern string) []string {
|
||||
vs := strings.Split(pattern, "/")
|
||||
|
||||
parts := make([]string, 0)
|
||||
for _, item := range vs {
|
||||
if item != "" {
|
||||
parts = append(parts, item)
|
||||
if item[0] == '*' {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
func (r *Router) AddRoute(method string, pattern string, handler string) {
|
||||
parts := parsePattern(pattern)
|
||||
|
||||
key := method + "-" + pattern
|
||||
_, ok := r.roots[method]
|
||||
if !ok {
|
||||
r.roots[method] = &node{}
|
||||
}
|
||||
r.roots[method].insert(pattern, parts, 0)
|
||||
r.handlers[key] = handler
|
||||
}
|
||||
|
||||
func (r *Router) GetRoute(method string, path string) (*node, map[string]string) {
|
||||
searchParts := parsePattern(path)
|
||||
params := make(map[string]string)
|
||||
root, ok := r.roots[method]
|
||||
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
n := root.search(searchParts, 0)
|
||||
|
||||
if n != nil {
|
||||
parts := parsePattern(n.pattern)
|
||||
for index, part := range parts {
|
||||
if part[0] == ':' {
|
||||
params[part[1:]] = searchParts[index]
|
||||
}
|
||||
//if part[0] == '*' && len(part) > 1 {
|
||||
// params[part[1:]] = strings.Join(searchParts[index:], "/")
|
||||
// break
|
||||
//}
|
||||
}
|
||||
return n, params
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *Router) getRoutes(method string) []*node {
|
||||
root, ok := r.roots[method]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
nodes := make([]*node, 0)
|
||||
root.travel(&nodes)
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (r *Router) Handle(method string, path string) (handle string, err error) {
|
||||
n, _ := r.GetRoute(method, path)
|
||||
if n == nil {
|
||||
err = errors.New("router not match")
|
||||
return
|
||||
|
||||
}
|
||||
return r.handlers[method+"-"+n.pattern], nil
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newTestRouter() *Router {
|
||||
r := NewRouter()
|
||||
//GET "GET/_mapping/:index": "indices.get_mapping",
|
||||
r.AddRoute("GET", "/:index/_mappings", "indices.get_mapping")
|
||||
r.AddRoute("GET", "/hello/:name", "gethello")
|
||||
r.AddRoute("GET", "/hello/b/c", "hellobc")
|
||||
r.AddRoute("GET", "/hi/:name", "getHi")
|
||||
r.AddRoute("GET", "/role/xushuhui", "getRole")
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func TestParsePattern(t *testing.T) {
|
||||
ok := reflect.DeepEqual(parsePattern("/p/:name"), []string{"p", ":name"})
|
||||
ok = ok && reflect.DeepEqual(parsePattern("/p/*"), []string{"p", "*"})
|
||||
ok = ok && reflect.DeepEqual(parsePattern("/p/*name/*"), []string{"p", "*name"})
|
||||
if !ok {
|
||||
t.Fatal("test parsePattern failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRoute(t *testing.T) {
|
||||
//r := newTestRouter()
|
||||
//path := "/elasticsearch/c6dgjtgvi076f32oibj0/index/test/_mappings"
|
||||
//paths := strings.Split(path, "/")
|
||||
//newPath := "/" + strings.Join(paths[4:], "/")
|
||||
//t.Log(newPath)
|
||||
|
||||
//if n == nil {
|
||||
// t.Fatal("nil shouldn't be returned")
|
||||
//}
|
||||
|
||||
//if n.pattern != "/hello/:name" {
|
||||
// t.Fatal("should match /hello/:name")
|
||||
//}
|
||||
//
|
||||
//if ps["name"] != "geektutu" {
|
||||
// t.Fatal("name should be equal to 'geektutu'")
|
||||
//}
|
||||
|
||||
//fmt.Printf("matched path: %s, params['name']: %s\n", n.pattern, ps["name"])
|
||||
|
||||
}
|
||||
|
||||
func TestGetRoute2(t *testing.T) {
|
||||
r := newTestRouter()
|
||||
n1, ps1 := r.GetRoute("GET", "/assets/file1.txt")
|
||||
ok1 := n1.pattern == "/assets/*filepath" && ps1["filepath"] == "file1.txt"
|
||||
if !ok1 {
|
||||
t.Fatal("pattern shoule be /assets/*filepath & filepath shoule be file1.txt")
|
||||
}
|
||||
|
||||
n2, ps2 := r.GetRoute("GET", "/assets/css/test.css")
|
||||
ok2 := n2.pattern == "/assets/*filepath" && ps2["filepath"] == "css/test.css"
|
||||
if !ok2 {
|
||||
t.Fatal("pattern shoule be /assets/*filepath & filepath shoule be css/test.css")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetRoutes(t *testing.T) {
|
||||
r := newTestRouter()
|
||||
nodes := r.getRoutes("GET")
|
||||
for i, n := range nodes {
|
||||
fmt.Println(i+1, n)
|
||||
}
|
||||
|
||||
if len(nodes) != 5 {
|
||||
t.Fatal("the number of routes shoule be 4")
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type node struct {
|
||||
pattern string // 待匹配路由,例如 /p/:lang
|
||||
part string // 路由中的一部分,例如 :lang
|
||||
children []*node // 子节点,例如 [doc, tutorial, intro]
|
||||
isWild bool // 是否精确匹配,part 含有 : 或 * 时为true
|
||||
}
|
||||
|
||||
func (n *node) String() string {
|
||||
return fmt.Sprintf("node{pattern=%s, part=%s, isWild=%t}", n.pattern, n.part, n.isWild)
|
||||
}
|
||||
|
||||
func (n *node) insert(pattern string, parts []string, height int) {
|
||||
if len(parts) == height {
|
||||
n.pattern = pattern
|
||||
return
|
||||
}
|
||||
|
||||
part := parts[height]
|
||||
child := n.matchChild(part)
|
||||
if child == nil {
|
||||
child = &node{part: part, isWild: part[0] == ':' || part[0] == '*'}
|
||||
n.children = append(n.children, child)
|
||||
}
|
||||
child.insert(pattern, parts, height+1)
|
||||
}
|
||||
|
||||
func (n *node) search(parts []string, height int) *node {
|
||||
if len(parts) == height || strings.HasPrefix(n.part, "*") {
|
||||
if n.pattern == "" {
|
||||
return nil
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
part := parts[height]
|
||||
children := n.matchChildren(part)
|
||||
|
||||
for _, child := range children {
|
||||
result := child.search(parts, height+1)
|
||||
if result != nil {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *node) travel(list *[]*node) {
|
||||
if n.pattern != "" {
|
||||
*list = append(*list, n)
|
||||
}
|
||||
for _, child := range n.children {
|
||||
child.travel(list)
|
||||
}
|
||||
}
|
||||
|
||||
// 第一个匹配成功的节点,用于插入
|
||||
func (n *node) matchChild(part string) *node {
|
||||
for _, child := range n.children {
|
||||
if child.part == part || child.isWild {
|
||||
return child
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 所有匹配成功的节点,用于查找
|
||||
func (n *node) matchChildren(part string) []*node {
|
||||
nodes := make([]*node, 0)
|
||||
for _, child := range n.children {
|
||||
if child.part == part || child.isWild {
|
||||
nodes = append(nodes, child)
|
||||
}
|
||||
}
|
||||
return nodes
|
||||
}
|
|
@ -1,20 +1,5 @@
|
|||
package dto
|
||||
|
||||
type UpdateRole struct {
|
||||
Description string `json:"description" `
|
||||
Platform []string `json:"platform"`
|
||||
Cluster []string `json:"cluster" `
|
||||
Index []string `json:"index" `
|
||||
ClusterPrivilege []string `json:"cluster_privilege" `
|
||||
IndexPrivilege []string `json:"index_privilege" `
|
||||
}
|
||||
|
||||
type ElasticsearchPermission struct {
|
||||
Cluster []string `json:"cluster" `
|
||||
Index []string `json:"index" `
|
||||
ClusterPrivilege []string `json:"cluster_privilege" `
|
||||
IndexPrivilege []string `json:"index_privilege" `
|
||||
}
|
||||
type CreateUser struct {
|
||||
NickName string `json:"nick_name"`
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ func ClusterRequired(h httprouter.Handle, route ...string) httprouter.Handle {
|
|||
w = handleError(w, http.StatusUnauthorized, err)
|
||||
return
|
||||
}
|
||||
newRole := biz.CombineUserRoles(claims.Roles)
|
||||
//newRole := biz.CombineUserRoles(claims.Roles)
|
||||
clusterReq := biz.NewClusterRequest(ps, route)
|
||||
|
||||
err = biz.ValidateCluster(clusterReq, newRole)
|
||||
err = biz.ValidateCluster(clusterReq, claims.Roles)
|
||||
if err != nil {
|
||||
w = handleError(w, http.StatusForbidden, err)
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue