feat: (rbac) build in role / logout / login operation log
This commit is contained in:
parent
74ddc44ce7
commit
7e9f39cb88
|
@ -3,7 +3,10 @@ package biz
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"infini.sh/console/model/rbac"
|
||||||
|
"infini.sh/framework/core/event"
|
||||||
"infini.sh/framework/core/global"
|
"infini.sh/framework/core/global"
|
||||||
|
"infini.sh/framework/core/orm"
|
||||||
"infini.sh/framework/core/util"
|
"infini.sh/framework/core/util"
|
||||||
"src/github.com/golang-jwt/jwt"
|
"src/github.com/golang-jwt/jwt"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -17,12 +20,31 @@ type UserClaims struct {
|
||||||
type User struct {
|
type User struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
Role []string `json:"role"`
|
Roles []string `json:"roles"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const Secret = "console"
|
const Secret = "console"
|
||||||
|
|
||||||
func Login(username string, password string) (m map[string]interface{}, err error) {
|
func authenticateUser(username string, password string) (user rbac.User, err error) {
|
||||||
|
q := orm.Query{Size: 1000}
|
||||||
|
q.Conds = orm.And(orm.Eq("username", username))
|
||||||
|
|
||||||
|
err, result := orm.Search(rbac.User{}, &q)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result.Total == 0 {
|
||||||
|
err = errors.New("user not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user = result.Result[0].(rbac.User)
|
||||||
|
if util.MD5digest(password) != user.Password {
|
||||||
|
err = errors.New("password error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func authenticateAdmin(username string, password string) (user rbac.User, err error) {
|
||||||
|
|
||||||
u, _ := global.Env().GetConfig("bootstrap.username", "admin")
|
u, _ := global.Env().GetConfig("bootstrap.username", "admin")
|
||||||
p, _ := global.Env().GetConfig("bootstrap.password", "admin")
|
p, _ := global.Env().GetConfig("bootstrap.password", "admin")
|
||||||
|
@ -31,11 +53,16 @@ func Login(username string, password string) (m map[string]interface{}, err erro
|
||||||
err = errors.New("invalid username or password")
|
err = errors.New("invalid username or password")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
user.ID = username
|
||||||
|
user.Username = username
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
func authorize(user rbac.User) (m map[string]interface{}, err error) {
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaims{
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaims{
|
||||||
User: &User{
|
User: &User{
|
||||||
Username: u,
|
Username: user.Username,
|
||||||
UserId: "admin",
|
UserId: user.ID,
|
||||||
Role: []string{"admin_user"},
|
Roles: []string{"admin"},
|
||||||
},
|
},
|
||||||
RegisteredClaims: &jwt.RegisteredClaims{
|
RegisteredClaims: &jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
|
||||||
|
@ -44,17 +71,49 @@ func Login(username string, password string) (m map[string]interface{}, err erro
|
||||||
|
|
||||||
tokenString, err := token.SignedString([]byte(Secret))
|
tokenString, err := token.SignedString([]byte(Secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m = util.MapStr{
|
m = util.MapStr{
|
||||||
"access_token": tokenString,
|
"access_token": tokenString,
|
||||||
"username": u,
|
"username": user.Username,
|
||||||
"userid": "admin",
|
"userid": user.ID,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func Login(username string, password string) (m map[string]interface{}, err error) {
|
||||||
|
var user rbac.User
|
||||||
|
if username == "admin" {
|
||||||
|
user, err = authenticateAdmin(username, password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
} else {
|
||||||
|
user, err = authenticateUser(username, password)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err = authorize(user)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = orm.Save(GenerateEvent(event.ActivityMetadata{
|
||||||
|
Category: "platform",
|
||||||
|
Group: "rbac",
|
||||||
|
Name: "login",
|
||||||
|
Type: "create",
|
||||||
|
Labels: util.MapStr{
|
||||||
|
"username": username,
|
||||||
|
"password": password,
|
||||||
|
},
|
||||||
|
User: util.MapStr{
|
||||||
|
"userid": user.ID,
|
||||||
|
"username": user.Username,
|
||||||
|
},
|
||||||
|
}, nil, nil))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateLogin(authorizationHeader string) (clams *UserClaims, err error) {
|
func ValidateLogin(authorizationHeader string) (clams *UserClaims, err error) {
|
||||||
|
@ -100,14 +159,14 @@ func ValidatePermission(claims *UserClaims, permissions []string) (err error) {
|
||||||
err = errors.New("user id is empty")
|
err = errors.New("user id is empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if reqUser.Role == nil {
|
if reqUser.Roles == nil {
|
||||||
err = errors.New("api permission is empty")
|
err = errors.New("api permission is empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 权限校验
|
// 权限校验
|
||||||
userPermissionMap := make(map[string]struct{})
|
userPermissionMap := make(map[string]struct{})
|
||||||
for _, role := range reqUser.Role {
|
for _, role := range reqUser.Roles {
|
||||||
if _, ok := RolePermission[role]; ok {
|
if _, ok := RolePermission[role]; ok {
|
||||||
for _, v := range RolePermission[role] {
|
for _, v := range RolePermission[role] {
|
||||||
userPermissionMap[v] = struct{}{}
|
userPermissionMap[v] = struct{}{}
|
||||||
|
|
|
@ -1,13 +1,64 @@
|
||||||
package enum
|
package enum
|
||||||
|
|
||||||
|
import (
|
||||||
|
"infini.sh/console/model/rbac"
|
||||||
|
"infini.sh/framework/core/orm"
|
||||||
|
)
|
||||||
|
|
||||||
const CreateUser = "create_user"
|
const CreateUser = "create_user"
|
||||||
const UpdateUser = "update_user"
|
const UpdateUser = "update_user"
|
||||||
const DeleteUser = "delete_user"
|
const DeleteUser = "delete_user"
|
||||||
const GetUser = "get_user"
|
const GetUser = "get_user"
|
||||||
const ListUser = "list_user"
|
const SearchUser = "search_user"
|
||||||
|
|
||||||
const CreateRole = "create_role"
|
const CreateRole = "create_role"
|
||||||
const UpdateRole = "update_role"
|
const UpdateRole = "update_role"
|
||||||
const DeleteRole = "delete_role"
|
const DeleteRole = "delete_role"
|
||||||
const GetRole = "get_role"
|
const GetRole = "get_role"
|
||||||
const ListRole = "list_role"
|
const SearchRole = "search_role"
|
||||||
const ListPermission = "list_permission"
|
const ListPermission = "list_permission"
|
||||||
|
|
||||||
|
const CreateRule = "create_rule"
|
||||||
|
const UpdateRule = "update_rule"
|
||||||
|
const DeleteRule = "delete_rule"
|
||||||
|
const GetRule = "get_rule"
|
||||||
|
const SearchRule = "search_rule"
|
||||||
|
|
||||||
|
const CreateInstance = "create_instance"
|
||||||
|
const UpdateInstance = "update_instance"
|
||||||
|
const DeleteInstance = "delete_instance"
|
||||||
|
const GetInstance = "get_instance"
|
||||||
|
const SearchInstance = "search_instance"
|
||||||
|
const GetInstanceStatus = "get_instance_status"
|
||||||
|
const ConnectInstance = "connect_instance"
|
||||||
|
const InstanceProxy = "instance_proxy"
|
||||||
|
|
||||||
|
var Admin = []string{CreateUser, UpdateUser, DeleteUser, GetUser, SearchUser, CreateRole, UpdateRole, DeleteRole, GetRole, SearchRole, ListPermission}
|
||||||
|
var AdminUser = []string{CreateUser, UpdateUser, DeleteUser, GetUser, SearchUser}
|
||||||
|
|
||||||
|
var BuildRoles = []rbac.Role{
|
||||||
|
{
|
||||||
|
ORMObjectBase: orm.ORMObjectBase{
|
||||||
|
ID: "admin",
|
||||||
|
},
|
||||||
|
Name: "admin",
|
||||||
|
Description: "管理员",
|
||||||
|
RoleType: "console",
|
||||||
|
Permission: rbac.ConsolePermission{
|
||||||
|
ApiPermission: Admin,
|
||||||
|
},
|
||||||
|
BuiltIn: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ORMObjectBase: orm.ORMObjectBase{
|
||||||
|
ID: "admin_user",
|
||||||
|
},
|
||||||
|
Name: "admin_user",
|
||||||
|
Description: "用户模块管理员",
|
||||||
|
RoleType: "console",
|
||||||
|
Permission: rbac.ConsolePermission{
|
||||||
|
ApiPermission: AdminUser,
|
||||||
|
},
|
||||||
|
BuiltIn: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
|
@ -6,12 +6,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenerateEvent(metadata event.ActivityMetadata, fields util.MapStr) *event.Activity {
|
func GenerateEvent(metadata event.ActivityMetadata, fields util.MapStr, changeLog interface{}) *event.Activity {
|
||||||
return &event.Activity{
|
return &event.Activity{
|
||||||
ID: util.GetUUID(),
|
ID: util.GetUUID(),
|
||||||
Timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
Fields: fields,
|
Fields: fields,
|
||||||
|
Changelog: changeLog,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ func CreateRole(localUser *User, req dto.CreateRole) (id string, err error) {
|
||||||
"userid": localUser.UserId,
|
"userid": localUser.UserId,
|
||||||
"username": localUser.Username,
|
"username": localUser.Username,
|
||||||
},
|
},
|
||||||
}, nil))
|
}, nil, nil))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
@ -99,7 +99,7 @@ func DeleteRole(localUser *User, id string) (err error) {
|
||||||
"type": role.RoleType,
|
"type": role.RoleType,
|
||||||
"created": role.Created.Format("2006-01-02 15:04:05"),
|
"created": role.Created.Format("2006-01-02 15:04:05"),
|
||||||
"updated": role.Updated.Format("2006-01-02 15:04:05"),
|
"updated": role.Updated.Format("2006-01-02 15:04:05"),
|
||||||
}))
|
}, nil))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ func UpdateRole(localUser *User, id string, req dto.UpdateRole) (err error) {
|
||||||
err = ErrNotFound
|
err = ErrNotFound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
changeLog, _ := util.DiffTwoObject(role, req)
|
||||||
role.Description = req.Description
|
role.Description = req.Description
|
||||||
role.Permission = req.Permission
|
role.Permission = req.Permission
|
||||||
role.Updated = time.Now()
|
role.Updated = time.Now()
|
||||||
|
@ -134,7 +135,7 @@ func UpdateRole(localUser *User, id string, req dto.UpdateRole) (err error) {
|
||||||
"userid": localUser.UserId,
|
"userid": localUser.UserId,
|
||||||
"username": localUser.Username,
|
"username": localUser.Username,
|
||||||
},
|
},
|
||||||
}, nil))
|
}, nil, changeLog))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func GetRole(id string) (role rbac.Role, err error) {
|
func GetRole(id string) (role rbac.Role, err error) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ func DeleteUser(localUser *User, id string) (err error) {
|
||||||
"roles": user.Roles,
|
"roles": user.Roles,
|
||||||
"created": user.Created,
|
"created": user.Created,
|
||||||
"updated": user.Updated,
|
"updated": user.Updated,
|
||||||
}))
|
}, nil))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func CreateUser(localUser *User, req dto.CreateUser) (id string, err error) {
|
func CreateUser(localUser *User, req dto.CreateUser) (id string, err error) {
|
||||||
|
@ -112,7 +112,7 @@ func CreateUser(localUser *User, req dto.CreateUser) (id string, err error) {
|
||||||
"userid": localUser.UserId,
|
"userid": localUser.UserId,
|
||||||
"username": localUser.Username,
|
"username": localUser.Username,
|
||||||
},
|
},
|
||||||
}, nil))
|
}, nil, nil))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func UpdateUser(localUser *User, id string, req dto.UpdateUser) (err error) {
|
func UpdateUser(localUser *User, id string, req dto.UpdateUser) (err error) {
|
||||||
|
@ -123,6 +123,7 @@ func UpdateUser(localUser *User, id string, req dto.UpdateUser) (err error) {
|
||||||
err = ErrNotFound
|
err = ErrNotFound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
changeLog, _ := util.DiffTwoObject(user, req)
|
||||||
user.Name = req.Name
|
user.Name = req.Name
|
||||||
user.Email = req.Email
|
user.Email = req.Email
|
||||||
user.Phone = req.Phone
|
user.Phone = req.Phone
|
||||||
|
@ -149,7 +150,7 @@ func UpdateUser(localUser *User, id string, req dto.UpdateUser) (err error) {
|
||||||
"userid": localUser.UserId,
|
"userid": localUser.UserId,
|
||||||
"username": localUser.Username,
|
"username": localUser.Username,
|
||||||
},
|
},
|
||||||
}, nil))
|
}, nil, changeLog))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func UpdateUserRole(localUser *User, id string, req dto.UpdateUserRole) (err error) {
|
func UpdateUserRole(localUser *User, id string, req dto.UpdateUserRole) (err error) {
|
||||||
|
@ -160,6 +161,7 @@ func UpdateUserRole(localUser *User, id string, req dto.UpdateUserRole) (err err
|
||||||
err = ErrNotFound
|
err = ErrNotFound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
changeLog, _ := util.DiffTwoObject(user, req)
|
||||||
roles := make([]rbac.UserRole, 0)
|
roles := make([]rbac.UserRole, 0)
|
||||||
for _, v := range req.Roles {
|
for _, v := range req.Roles {
|
||||||
roles = append(roles, rbac.UserRole{
|
roles = append(roles, rbac.UserRole{
|
||||||
|
@ -187,7 +189,7 @@ func UpdateUserRole(localUser *User, id string, req dto.UpdateUserRole) (err err
|
||||||
"userid": localUser.UserId,
|
"userid": localUser.UserId,
|
||||||
"username": localUser.Username,
|
"username": localUser.Username,
|
||||||
},
|
},
|
||||||
}, nil))
|
}, nil, changeLog))
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ func PermissionRequired(h httprouter.Handle, permissions ...string) httprouter.H
|
||||||
w = handleError(w, err)
|
w = handleError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
r = r.WithContext(biz.NewUserContext(r.Context(), claims))
|
||||||
h(w, r, ps)
|
h(w, r, ps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,9 @@ type Role struct {
|
||||||
BuiltIn bool `json:"builtin" elastic_mapping:"builtin:{type:boolean}"` //是否内置
|
BuiltIn bool `json:"builtin" elastic_mapping:"builtin:{type:boolean}"` //是否内置
|
||||||
}
|
}
|
||||||
type ConsolePermission struct {
|
type ConsolePermission struct {
|
||||||
ID string `json:"id" elastic_mapping:"id:{type:keyword}"`
|
ApiPermission []string `json:"api_permission"`
|
||||||
Name string `json:"name" elastic_mapping:"name:{type:keyword}"`
|
//ID string `json:"id" elastic_mapping:"id:{type:keyword}"`
|
||||||
|
//Name string `json:"name" elastic_mapping:"name:{type:keyword}"`
|
||||||
}
|
}
|
||||||
type ElasticsearchPermission struct {
|
type ElasticsearchPermission struct {
|
||||||
Cluster []string `json:"cluster" elastic_mapping:"cluster:{type:object}"`
|
Cluster []string `json:"cluster" elastic_mapping:"cluster:{type:object}"`
|
||||||
|
|
|
@ -88,6 +88,9 @@ func (h Account) CurrentUser(w http.ResponseWriter, req *http.Request, ps httpro
|
||||||
}
|
}
|
||||||
func (h Account) Logout(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
func (h Account) Logout(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
|
||||||
|
h.WriteOKJSON(w, util.MapStr{
|
||||||
|
"status": "ok",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
func (h Account) Profile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
func (h Account) Profile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
reqUser, err := biz.FromUserContext(r.Context())
|
reqUser, err := biz.FromUserContext(r.Context())
|
||||||
|
|
|
@ -23,15 +23,14 @@ func registerRouter() {
|
||||||
api.HandleAPIMethod(api.GET, "/role/:id", m.PermissionRequired(r.GetRole, enum.GetRole))
|
api.HandleAPIMethod(api.GET, "/role/:id", m.PermissionRequired(r.GetRole, enum.GetRole))
|
||||||
api.HandleAPIMethod(api.DELETE, "/role/:id", m.PermissionRequired(r.DeleteRole, enum.DeleteRole))
|
api.HandleAPIMethod(api.DELETE, "/role/:id", m.PermissionRequired(r.DeleteRole, enum.DeleteRole))
|
||||||
api.HandleAPIMethod(api.PUT, "/role/:id", m.PermissionRequired(r.UpdateRole, enum.UpdateRole))
|
api.HandleAPIMethod(api.PUT, "/role/:id", m.PermissionRequired(r.UpdateRole, enum.UpdateRole))
|
||||||
api.HandleAPIMethod(api.GET, "/role/_search", m.PermissionRequired(r.SearchRole, enum.ListRole))
|
api.HandleAPIMethod(api.GET, "/role/_search", m.PermissionRequired(r.SearchRole, enum.SearchRole))
|
||||||
|
|
||||||
api.HandleAPIMethod(api.POST, "/user", m.PermissionRequired(r.CreateUser, enum.CreateUser))
|
api.HandleAPIMethod(api.POST, "/user", m.PermissionRequired(r.CreateUser, enum.CreateUser))
|
||||||
api.HandleAPIMethod(api.GET, "/user/:id", m.PermissionRequired(r.GetUser, enum.GetUser))
|
api.HandleAPIMethod(api.GET, "/user/:id", m.PermissionRequired(r.GetUser, enum.GetUser))
|
||||||
api.HandleAPIMethod(api.GET, "/user/search", m.PermissionRequired(r.SearchUser, enum.ListUser))
|
|
||||||
api.HandleAPIMethod(api.DELETE, "/user/:id", m.PermissionRequired(r.DeleteUser, enum.DeleteUser))
|
api.HandleAPIMethod(api.DELETE, "/user/:id", m.PermissionRequired(r.DeleteUser, enum.DeleteUser))
|
||||||
api.HandleAPIMethod(api.PUT, "/user/:id", m.PermissionRequired(r.UpdateUser, enum.UpdateUser))
|
api.HandleAPIMethod(api.PUT, "/user/:id", m.PermissionRequired(r.UpdateUser, enum.UpdateUser))
|
||||||
api.HandleAPIMethod(api.PUT, "/user/:id/role", m.PermissionRequired(r.UpdateUserRole, enum.UpdateUser))
|
api.HandleAPIMethod(api.PUT, "/user/:id/role", m.PermissionRequired(r.UpdateUserRole, enum.UpdateUser))
|
||||||
api.HandleAPIMethod(api.GET, "/user/_search", m.PermissionRequired(r.SearchUser, enum.ListUser))
|
api.HandleAPIMethod(api.GET, "/user/_search", m.PermissionRequired(r.SearchUser, enum.SearchUser))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +57,8 @@ func loadJsonConfig() {
|
||||||
}
|
}
|
||||||
func loadRolePermission() {
|
func loadRolePermission() {
|
||||||
biz.RolePermission = make(map[string][]string)
|
biz.RolePermission = make(map[string][]string)
|
||||||
biz.RolePermission["admin_user"] = []string{enum.GetUser}
|
biz.RolePermission["admin_user"] = enum.AdminUser
|
||||||
|
biz.RolePermission["admin"] = enum.Admin
|
||||||
}
|
}
|
||||||
func init() {
|
func init() {
|
||||||
registerRouter()
|
registerRouter()
|
||||||
|
|
|
@ -3,6 +3,7 @@ package rbac
|
||||||
import (
|
import (
|
||||||
log "github.com/cihub/seelog"
|
log "github.com/cihub/seelog"
|
||||||
"infini.sh/console/internal/biz"
|
"infini.sh/console/internal/biz"
|
||||||
|
"infini.sh/console/internal/biz/enum"
|
||||||
"infini.sh/console/internal/dto"
|
"infini.sh/console/internal/dto"
|
||||||
httprouter "infini.sh/framework/core/api/router"
|
httprouter "infini.sh/framework/core/api/router"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -53,8 +54,15 @@ func (h Rbac) SearchRole(w http.ResponseWriter, r *http.Request, ps httprouter.P
|
||||||
h.Error(w, err)
|
h.Error(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
roles := make([]interface{}, 0)
|
||||||
|
for _, role := range enum.BuildRoles {
|
||||||
|
roles = append(roles, role)
|
||||||
|
}
|
||||||
|
for _, v := range res.Result {
|
||||||
|
roles = append(roles, v)
|
||||||
|
}
|
||||||
|
|
||||||
h.WriteOKJSON(w, Response{Hit: res.Result, Total: res.Total})
|
h.WriteOKJSON(w, Response{Hit: roles, Total: res.Total + int64(len(enum.BuildRoles))})
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue