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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"infini.sh/console/model/rbac"
|
||||
"infini.sh/framework/core/event"
|
||||
"infini.sh/framework/core/global"
|
||||
"infini.sh/framework/core/orm"
|
||||
"infini.sh/framework/core/util"
|
||||
"src/github.com/golang-jwt/jwt"
|
||||
"strings"
|
||||
|
@ -17,12 +20,31 @@ type UserClaims struct {
|
|||
type User struct {
|
||||
Username string `json:"username"`
|
||||
UserId string `json:"user_id"`
|
||||
Role []string `json:"role"`
|
||||
Roles []string `json:"roles"`
|
||||
}
|
||||
|
||||
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")
|
||||
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")
|
||||
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{
|
||||
User: &User{
|
||||
Username: u,
|
||||
UserId: "admin",
|
||||
Role: []string{"admin_user"},
|
||||
Username: user.Username,
|
||||
UserId: user.ID,
|
||||
Roles: []string{"admin"},
|
||||
},
|
||||
RegisteredClaims: &jwt.RegisteredClaims{
|
||||
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))
|
||||
if err != nil {
|
||||
|
||||
return
|
||||
}
|
||||
m = util.MapStr{
|
||||
"access_token": tokenString,
|
||||
"username": u,
|
||||
"userid": "admin",
|
||||
"username": user.Username,
|
||||
"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
|
||||
}
|
||||
|
||||
} 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) {
|
||||
|
@ -100,14 +159,14 @@ func ValidatePermission(claims *UserClaims, permissions []string) (err error) {
|
|||
err = errors.New("user id is empty")
|
||||
return
|
||||
}
|
||||
if reqUser.Role == nil {
|
||||
if reqUser.Roles == nil {
|
||||
err = errors.New("api permission is empty")
|
||||
return
|
||||
}
|
||||
|
||||
// 权限校验
|
||||
userPermissionMap := make(map[string]struct{})
|
||||
for _, role := range reqUser.Role {
|
||||
for _, role := range reqUser.Roles {
|
||||
if _, ok := RolePermission[role]; ok {
|
||||
for _, v := range RolePermission[role] {
|
||||
userPermissionMap[v] = struct{}{}
|
||||
|
|
|
@ -1,13 +1,64 @@
|
|||
package enum
|
||||
|
||||
import (
|
||||
"infini.sh/console/model/rbac"
|
||||
"infini.sh/framework/core/orm"
|
||||
)
|
||||
|
||||
const CreateUser = "create_user"
|
||||
const UpdateUser = "update_user"
|
||||
const DeleteUser = "delete_user"
|
||||
const GetUser = "get_user"
|
||||
const ListUser = "list_user"
|
||||
const SearchUser = "search_user"
|
||||
|
||||
const CreateRole = "create_role"
|
||||
const UpdateRole = "update_role"
|
||||
const DeleteRole = "delete_role"
|
||||
const GetRole = "get_role"
|
||||
const ListRole = "list_role"
|
||||
const SearchRole = "search_role"
|
||||
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"
|
||||
)
|
||||
|
||||
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{
|
||||
ID: util.GetUUID(),
|
||||
Timestamp: time.Now(),
|
||||
Metadata: metadata,
|
||||
Fields: fields,
|
||||
Changelog: changeLog,
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ func CreateRole(localUser *User, req dto.CreateRole) (id string, err error) {
|
|||
"userid": localUser.UserId,
|
||||
"username": localUser.Username,
|
||||
},
|
||||
}, nil))
|
||||
}, nil, nil))
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
|
@ -99,7 +99,7 @@ func DeleteRole(localUser *User, id string) (err error) {
|
|||
"type": role.RoleType,
|
||||
"created": role.Created.Format("2006-01-02 15:04:05"),
|
||||
"updated": role.Updated.Format("2006-01-02 15:04:05"),
|
||||
}))
|
||||
}, nil))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ func UpdateRole(localUser *User, id string, req dto.UpdateRole) (err error) {
|
|||
err = ErrNotFound
|
||||
return
|
||||
}
|
||||
changeLog, _ := util.DiffTwoObject(role, req)
|
||||
role.Description = req.Description
|
||||
role.Permission = req.Permission
|
||||
role.Updated = time.Now()
|
||||
|
@ -134,7 +135,7 @@ func UpdateRole(localUser *User, id string, req dto.UpdateRole) (err error) {
|
|||
"userid": localUser.UserId,
|
||||
"username": localUser.Username,
|
||||
},
|
||||
}, nil))
|
||||
}, nil, changeLog))
|
||||
return
|
||||
}
|
||||
func GetRole(id string) (role rbac.Role, err error) {
|
||||
|
|
|
@ -50,7 +50,7 @@ func DeleteUser(localUser *User, id string) (err error) {
|
|||
"roles": user.Roles,
|
||||
"created": user.Created,
|
||||
"updated": user.Updated,
|
||||
}))
|
||||
}, nil))
|
||||
return
|
||||
}
|
||||
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,
|
||||
"username": localUser.Username,
|
||||
},
|
||||
}, nil))
|
||||
}, nil, nil))
|
||||
return
|
||||
}
|
||||
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
|
||||
return
|
||||
}
|
||||
changeLog, _ := util.DiffTwoObject(user, req)
|
||||
user.Name = req.Name
|
||||
user.Email = req.Email
|
||||
user.Phone = req.Phone
|
||||
|
@ -149,7 +150,7 @@ func UpdateUser(localUser *User, id string, req dto.UpdateUser) (err error) {
|
|||
"userid": localUser.UserId,
|
||||
"username": localUser.Username,
|
||||
},
|
||||
}, nil))
|
||||
}, nil, changeLog))
|
||||
return
|
||||
}
|
||||
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
|
||||
return
|
||||
}
|
||||
changeLog, _ := util.DiffTwoObject(user, req)
|
||||
roles := make([]rbac.UserRole, 0)
|
||||
for _, v := range req.Roles {
|
||||
roles = append(roles, rbac.UserRole{
|
||||
|
@ -187,7 +189,7 @@ func UpdateUserRole(localUser *User, id string, req dto.UpdateUserRole) (err err
|
|||
"userid": localUser.UserId,
|
||||
"username": localUser.Username,
|
||||
},
|
||||
}, nil))
|
||||
}, nil, changeLog))
|
||||
return
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ func PermissionRequired(h httprouter.Handle, permissions ...string) httprouter.H
|
|||
w = handleError(w, err)
|
||||
return
|
||||
}
|
||||
r = r.WithContext(biz.NewUserContext(r.Context(), claims))
|
||||
h(w, r, ps)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ type Role struct {
|
|||
BuiltIn bool `json:"builtin" elastic_mapping:"builtin:{type:boolean}"` //是否内置
|
||||
}
|
||||
type ConsolePermission struct {
|
||||
ID string `json:"id" elastic_mapping:"id:{type:keyword}"`
|
||||
Name string `json:"name" elastic_mapping:"name:{type:keyword}"`
|
||||
ApiPermission []string `json:"api_permission"`
|
||||
//ID string `json:"id" elastic_mapping:"id:{type:keyword}"`
|
||||
//Name string `json:"name" elastic_mapping:"name:{type:keyword}"`
|
||||
}
|
||||
type ElasticsearchPermission struct {
|
||||
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) {
|
||||
|
||||
h.WriteOKJSON(w, util.MapStr{
|
||||
"status": "ok",
|
||||
})
|
||||
}
|
||||
func (h Account) Profile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
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.DELETE, "/role/:id", m.PermissionRequired(r.DeleteRole, enum.DeleteRole))
|
||||
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.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.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.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() {
|
||||
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() {
|
||||
registerRouter()
|
||||
|
|
|
@ -3,6 +3,7 @@ package rbac
|
|||
import (
|
||||
log "github.com/cihub/seelog"
|
||||
"infini.sh/console/internal/biz"
|
||||
"infini.sh/console/internal/biz/enum"
|
||||
"infini.sh/console/internal/dto"
|
||||
httprouter "infini.sh/framework/core/api/router"
|
||||
"net/http"
|
||||
|
@ -53,8 +54,15 @@ func (h Rbac) SearchRole(w http.ResponseWriter, r *http.Request, ps httprouter.P
|
|||
h.Error(w, err)
|
||||
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
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue