Multi roles support (#737)
* support multi user roles * resources list support search tags and note
This commit is contained in:
parent
255b2b2320
commit
de840af331
|
@ -2,6 +2,7 @@ package http
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/didi/nightingale/v5/pkg/ierr"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -23,7 +24,17 @@ func admin() gin.HandlerFunc {
|
|||
c.Set("username", username)
|
||||
|
||||
user := loginUser(c)
|
||||
if user.Role != "Admin" {
|
||||
|
||||
roles := strings.Fields(user.RolesForDB)
|
||||
found := false
|
||||
for i := 0; i < len(roles); i++ {
|
||||
if roles[i] == "Admin" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
ierr.Bomb(http.StatusForbidden, "forbidden")
|
||||
}
|
||||
|
||||
|
|
|
@ -129,8 +129,11 @@ func alertRuleGroupFavoriteDel(c *gin.Context) {
|
|||
}
|
||||
|
||||
func alertRuleWritePermCheck(alertRuleGroup *models.AlertRuleGroup, user *models.User) {
|
||||
if user.Role == "Admin" {
|
||||
return
|
||||
roles := strings.Fields(user.RolesForDB)
|
||||
for i := 0; i < len(roles); i++ {
|
||||
if roles[i] == "Admin" {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
gids := IdsInt64(alertRuleGroup.UserGroupIds)
|
||||
|
|
|
@ -2,6 +2,7 @@ package http
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -20,7 +21,14 @@ func userGets(c *gin.Context) {
|
|||
list, err := models.UserGets(query, limit, offset(c, limit))
|
||||
dangerous(err)
|
||||
|
||||
admin := loginUser(c).Role == "Admin"
|
||||
admin := false
|
||||
roles := strings.Fields(loginUser(c).RolesForDB)
|
||||
for i := 0; i < len(roles); i++ {
|
||||
if roles[i] == "Admin" {
|
||||
admin = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
renderData(c, gin.H{
|
||||
"list": list,
|
||||
|
@ -36,7 +44,7 @@ type userAddForm struct {
|
|||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Portrait string `json:"portrait"`
|
||||
Role string `json:"role"`
|
||||
Roles []string `json:"roles"`
|
||||
Contacts json.RawMessage `json:"contacts"`
|
||||
}
|
||||
|
||||
|
@ -50,23 +58,23 @@ func userAddPost(c *gin.Context) {
|
|||
now := time.Now().Unix()
|
||||
username := loginUsername(c)
|
||||
|
||||
u := models.User{
|
||||
Username: f.Username,
|
||||
Password: password,
|
||||
Nickname: f.Nickname,
|
||||
Phone: f.Phone,
|
||||
Email: f.Email,
|
||||
Portrait: f.Portrait,
|
||||
Role: f.Role,
|
||||
Contacts: f.Contacts,
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
CreateBy: username,
|
||||
UpdateBy: username,
|
||||
if len(f.Roles) == 0 {
|
||||
bomb(200, "roles empty")
|
||||
}
|
||||
|
||||
if u.Role == "" {
|
||||
u.Role = "Standard"
|
||||
u := models.User{
|
||||
Username: f.Username,
|
||||
Password: password,
|
||||
Nickname: f.Nickname,
|
||||
Phone: f.Phone,
|
||||
Email: f.Email,
|
||||
Portrait: f.Portrait,
|
||||
RolesForDB: strings.Join(f.Roles, " "),
|
||||
Contacts: f.Contacts,
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
CreateBy: username,
|
||||
UpdateBy: username,
|
||||
}
|
||||
|
||||
renderMessage(c, u.Add())
|
||||
|
@ -81,7 +89,7 @@ type userProfileForm struct {
|
|||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Portrait string `json:"portrait"`
|
||||
Role string `json:"role"`
|
||||
Roles []string `json:"roles"`
|
||||
Status int `json:"status"`
|
||||
Contacts json.RawMessage `json:"contacts"`
|
||||
}
|
||||
|
@ -90,12 +98,16 @@ func userProfilePut(c *gin.Context) {
|
|||
var f userProfileForm
|
||||
bind(c, &f)
|
||||
|
||||
if len(f.Roles) == 0 {
|
||||
bomb(200, "roles empty")
|
||||
}
|
||||
|
||||
target := User(urlParamInt64(c, "id"))
|
||||
target.Nickname = f.Nickname
|
||||
target.Phone = f.Phone
|
||||
target.Email = f.Email
|
||||
target.Portrait = f.Portrait
|
||||
target.Role = f.Role
|
||||
target.RolesForDB = strings.Join(f.Roles, " ")
|
||||
target.Status = f.Status
|
||||
target.Contacts = f.Contacts
|
||||
target.UpdateAt = time.Now().Unix()
|
||||
|
@ -107,7 +119,7 @@ func userProfilePut(c *gin.Context) {
|
|||
"phone",
|
||||
"email",
|
||||
"portrait",
|
||||
"role",
|
||||
"roles",
|
||||
"status",
|
||||
"contacts",
|
||||
"update_at",
|
||||
|
|
|
@ -44,7 +44,7 @@ func ResourceTotalByClasspathId(classpathIds []int64, query string) (int64, erro
|
|||
}
|
||||
|
||||
q := "%" + query + "%"
|
||||
num, err := DB.Where("ident in (select res_ident from classpath_resource where classpath_id in ("+str.IdsString(classpathIds)+")) and (ident like ? or alias like ?)", q, q).Count(new(Resource))
|
||||
num, err := DB.Where("ident in (select res_ident from classpath_resource where classpath_id in ("+str.IdsString(classpathIds)+")) and (ident like ? or alias like ? or tags like ? or note like ?)", q, q, q, q).Count(new(Resource))
|
||||
if err != nil {
|
||||
logger.Errorf("mysql.error count resource in classpath(id=%v) query=%s fail: %v", classpathIds, query, err)
|
||||
return 0, internalServerError
|
||||
|
@ -60,7 +60,7 @@ func ResourceGetsByClasspathId(classpathIds []int64, query string, limit, offset
|
|||
q := "%" + query + "%"
|
||||
|
||||
var objs []Resource
|
||||
err := DB.Where("ident in (select res_ident from classpath_resource where classpath_id in ("+str.IdsString(classpathIds)+")) and (ident like ? or alias like ?)", q, q).OrderBy("ident").Limit(limit, offset).Find(&objs)
|
||||
err := DB.Where("ident in (select res_ident from classpath_resource where classpath_id in ("+str.IdsString(classpathIds)+")) and (ident like ? or alias like ? or tags like ? or note like ?)", q, q, q, q).OrderBy("ident").Limit(limit, offset).Find(&objs)
|
||||
if err != nil {
|
||||
logger.Errorf("mysql.error query resource in classpath(id=%d) query=%s fail: %v", classpathIds, query, err)
|
||||
return nil, internalServerError
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package models
|
||||
|
||||
import "github.com/toolkits/pkg/logger"
|
||||
import (
|
||||
"github.com/toolkits/pkg/logger"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
type RoleOperation struct {
|
||||
RoleName string
|
||||
|
@ -11,8 +14,11 @@ func (RoleOperation) TableName() string {
|
|||
return "role_operation"
|
||||
}
|
||||
|
||||
func RoleHasOperation(roleName, operation string) (bool, error) {
|
||||
num, err := DB.Where("role_name=? and operation=?", roleName, operation).Count(new(RoleOperation))
|
||||
func RoleHasOperation(roles []string, operation string) (bool, error) {
|
||||
cond := builder.NewCond()
|
||||
cond = cond.And(builder.In("role_name", roles))
|
||||
cond = cond.And(builder.Eq{"operation": operation})
|
||||
num, err := DB.Where(cond).Count(new(RoleOperation))
|
||||
if err != nil {
|
||||
logger.Errorf("mysql.error query role_operation fail: %v", err)
|
||||
return false, internalServerError
|
||||
|
|
|
@ -15,20 +15,21 @@ import (
|
|||
)
|
||||
|
||||
type User struct {
|
||||
Id int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Nickname string `json:"nickname"`
|
||||
Password string `json:"-"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Portrait string `json:"portrait"`
|
||||
Status int `json:"status"`
|
||||
Role string `json:"role"`
|
||||
Contacts json.RawMessage `json:"contacts"` //内容为 map[string]string 结构
|
||||
CreateAt int64 `json:"create_at"`
|
||||
CreateBy string `json:"create_by"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
Id int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Nickname string `json:"nickname"`
|
||||
Password string `json:"-"`
|
||||
Phone string `json:"phone"`
|
||||
Email string `json:"email"`
|
||||
Portrait string `json:"portrait"`
|
||||
Status int `json:"status"`
|
||||
RolesForDB string `json:"-" xorm:"'roles'"` // 这个字段写入数据库
|
||||
RolesForFE []string `json:"roles" xorm:"-"` // 这个字段和前端交互
|
||||
Contacts json.RawMessage `json:"contacts"` // 内容为 map[string]string 结构
|
||||
CreateAt int64 `json:"create_at"`
|
||||
CreateBy string `json:"create_by"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
}
|
||||
|
||||
func (u *User) TableName() string {
|
||||
|
@ -110,16 +111,16 @@ func InitRoot() {
|
|||
now := time.Now().Unix()
|
||||
|
||||
u = User{
|
||||
Username: "root",
|
||||
Password: pass,
|
||||
Nickname: "超管",
|
||||
Portrait: "",
|
||||
Role: "Admin",
|
||||
Contacts: []byte("{}"),
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
CreateBy: "system",
|
||||
UpdateBy: "system",
|
||||
Username: "root",
|
||||
Password: pass,
|
||||
Nickname: "超管",
|
||||
Portrait: "",
|
||||
RolesForDB: "Admin",
|
||||
Contacts: []byte("{}"),
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
CreateBy: "system",
|
||||
UpdateBy: "system",
|
||||
}
|
||||
|
||||
_, err = DB.Insert(u)
|
||||
|
@ -151,6 +152,8 @@ func UserGet(where string, args ...interface{}) (*User, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
obj.RolesForFE = strings.Fields(obj.RolesForDB)
|
||||
|
||||
return &obj, nil
|
||||
}
|
||||
|
||||
|
@ -188,6 +191,10 @@ func UserGets(query string, limit, offset int) ([]User, error) {
|
|||
return []User{}, nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(users); i++ {
|
||||
users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
|
@ -204,6 +211,10 @@ func UserGetAll() ([]User, error) {
|
|||
return []User{}, nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(users); i++ {
|
||||
users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
|
@ -223,23 +234,31 @@ func UserGetsByIds(ids []int64) ([]User, error) {
|
|||
return []User{}, nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(users); i++ {
|
||||
users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func UserGetsByIdsStr(ids []string) ([]User, error) {
|
||||
var objs []User
|
||||
var users []User
|
||||
|
||||
err := DB.Where("id in (" + strings.Join(ids, ",") + ")").Find(&objs)
|
||||
err := DB.Where("id in (" + strings.Join(ids, ",") + ")").Find(&users)
|
||||
if err != nil {
|
||||
logger.Errorf("mysql.error: UserGetsByIds fail: %v", err)
|
||||
return nil, internalServerError
|
||||
}
|
||||
|
||||
if len(objs) == 0 {
|
||||
if len(users) == 0 {
|
||||
return []User{}, nil
|
||||
}
|
||||
|
||||
return objs, nil
|
||||
for i := 0; i < len(users); i++ {
|
||||
users[i].RolesForFE = strings.Fields(users[i].RolesForDB)
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func PassLogin(username, pass string) (*User, error) {
|
||||
|
@ -312,7 +331,8 @@ func LdapLogin(username, pass string) (*User, error) {
|
|||
|
||||
user.Password = "******"
|
||||
user.Portrait = "/img/linux.jpeg"
|
||||
user.Role = "Standard"
|
||||
user.RolesForDB = "Standard"
|
||||
user.RolesForFE = []string{"Standard"}
|
||||
user.Contacts = []byte("{}")
|
||||
user.CreateAt = now
|
||||
user.UpdateAt = now
|
||||
|
@ -474,8 +494,11 @@ func (u *User) MyUserGroups() ([]UserGroup, error) {
|
|||
|
||||
func (u *User) CanModifyUserGroup(ug *UserGroup) (bool, error) {
|
||||
// 我是管理员,自然可以
|
||||
if u.Role == "Admin" {
|
||||
return true, nil
|
||||
roles := strings.Fields(u.RolesForDB)
|
||||
for i := 0; i < len(roles); i++ {
|
||||
if roles[i] == "Admin" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 我是创建者,自然可以
|
||||
|
@ -493,11 +516,14 @@ func (u *User) CanModifyUserGroup(ug *UserGroup) (bool, error) {
|
|||
}
|
||||
|
||||
func (u *User) CanDo(op string) (bool, error) {
|
||||
if u.Role == "Admin" {
|
||||
return true, nil
|
||||
roles := strings.Fields(u.RolesForDB)
|
||||
for i := 0; i < len(roles); i++ {
|
||||
if roles[i] == "Admin" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return RoleHasOperation(u.Role, op)
|
||||
return RoleHasOperation(roles, op)
|
||||
}
|
||||
|
||||
// MustPerm return *User for link program
|
||||
|
|
Loading…
Reference in New Issue