fix: member-created services shouldn't be applied to admin resources (#1113)

This commit is contained in:
UUBulb
2025-08-28 22:37:44 +08:00
committed by GitHub
parent 61b8411d06
commit b6fed87d61
8 changed files with 27 additions and 21 deletions

View File

@@ -223,7 +223,7 @@ func adminHandler[T any](handler handlerFunc[T]) func(*gin.Context) {
} }
user := *auth.(*model.User) user := *auth.(*model.User)
if user.Role != model.RoleAdmin { if !user.Role.IsAdmin() {
c.JSON(http.StatusOK, newErrorResponse(singleton.Localizer.ErrorT("permission denied"))) c.JSON(http.StatusOK, newErrorResponse(singleton.Localizer.ErrorT("permission denied")))
return return
} }

View File

@@ -24,11 +24,11 @@ func listConfig(c *gin.Context) (*model.SettingResponse, error) {
var isAdmin bool var isAdmin bool
if authorized { if authorized {
user := u.(*model.User) user := u.(*model.User)
isAdmin = user.Role == model.RoleAdmin isAdmin = user.Role.IsAdmin()
} }
config := *singleton.Conf config := *singleton.Conf
config.Language = strings.Replace(config.Language, "_", "-", -1) config.Language = strings.ReplaceAll(config.Language, "_", "-")
conf := model.SettingResponse{ conf := model.SettingResponse{
Config: model.Setting{ Config: model.Setting{
@@ -89,7 +89,7 @@ func updateConfig(c *gin.Context) (any, error) {
return nil, errors.New("invalid user template") return nil, errors.New("invalid user template")
} }
singleton.Conf.Language = strings.Replace(sf.Language, "-", "_", -1) singleton.Conf.Language = strings.ReplaceAll(sf.Language, "-", "_")
singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification singleton.Conf.EnableIPChangeNotification = sf.EnableIPChangeNotification
singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification singleton.Conf.EnablePlainIPInNotification = sf.EnablePlainIPInNotification

View File

@@ -133,7 +133,7 @@ func createUser(c *gin.Context) (uint64, error) {
if uf.Username == "" { if uf.Username == "" {
return 0, singleton.Localizer.ErrorT("username can't be empty") return 0, singleton.Localizer.ErrorT("username can't be empty")
} }
if uf.Role != model.RoleAdmin && uf.Role != model.RoleMember { if uf.Role > model.RoleMember {
return 0, singleton.Localizer.ErrorT("invalid role") return 0, singleton.Localizer.ErrorT("invalid role")
} }
@@ -195,7 +195,7 @@ func listOnlineUser(c *gin.Context) (*model.Value[[]*model.OnlineUser], error) {
var isAdmin bool var isAdmin bool
u, ok := c.Get(model.CtxKeyAuthorizedUser) u, ok := c.Get(model.CtxKeyAuthorizedUser)
if ok { if ok {
isAdmin = u.(*model.User).Role == model.RoleAdmin isAdmin = u.(*model.User).Role.IsAdmin()
} }
limit, err := strconv.Atoi(c.Query("limit")) limit, err := strconv.Atoi(c.Query("limit"))
if err != nil || limit < 1 { if err != nil || limit < 1 {

View File

@@ -177,14 +177,14 @@ func ServeNAT(w http.ResponseWriter, r *http.Request, natConfig *model.NAT) {
} }
func canSendTaskToServer(task *model.Service, server *model.Server) bool { func canSendTaskToServer(task *model.Service, server *model.Server) bool {
var role uint8 var role model.Role
singleton.UserLock.RLock() singleton.UserLock.RLock()
if u, ok := singleton.UserInfoMap[server.UserID]; !ok { if u, ok := singleton.UserInfoMap[task.UserID]; !ok {
role = model.RoleMember role = model.RoleMember
} else { } else {
role = u.Role role = u.Role
} }
singleton.UserLock.RUnlock() singleton.UserLock.RUnlock()
return task.UserID == server.UserID || role == model.RoleAdmin return task.UserID == server.UserID || role.IsAdmin()
} }

View File

@@ -32,10 +32,10 @@ type ConfigDashboard struct {
InstallHost string `koanf:"install_host" json:"install_host,omitempty"` InstallHost string `koanf:"install_host" json:"install_host,omitempty"`
AgentTLS bool `koanf:"tls" json:"tls,omitempty"` // 用于前端判断生成的安装命令是否启用 TLS AgentTLS bool `koanf:"tls" json:"tls,omitempty"` // 用于前端判断生成的安装命令是否启用 TLS
WebRealIPHeader string `koanf:"web_real_ip_header" json:"web_real_ip_header,omitempty"` // 前端真实IP WebRealIPHeader string `koanf:"web_real_ip_header" json:"web_real_ip_header,omitempty"` // 前端真实IP
AgentRealIPHeader string `koanf:"agent_real_ip_header" json:"agent_real_ip_header,omitempty"` // Agent真实IP AgentRealIPHeader string `koanf:"agent_real_ip_header" json:"agent_real_ip_header,omitempty"` // Agent真实IP
UserTemplate string `koanf:"user_template" json:"user_template,omitempty"` UserTemplate string `koanf:"user_template" json:"user_template,omitempty"`
AdminTemplate string `koanf:"admin_template" json:"admin_template,omitempty"` AdminTemplate string `koanf:"admin_template" json:"admin_template,omitempty"`
EnablePlainIPInNotification bool `koanf:"enable_plain_ip_in_notification" json:"enable_plain_ip_in_notification,omitempty"` // 通知信息IP不打码 EnablePlainIPInNotification bool `koanf:"enable_plain_ip_in_notification" json:"enable_plain_ip_in_notification,omitempty"` // 通知信息IP不打码
@@ -87,7 +87,7 @@ func (c *Config) Read(path string, frontendTemplates []FrontendTemplate) error {
c.filePath = path c.filePath = path
err := c.k.Load(env.Provider("NZ_", ".", func(s string) string { err := c.k.Load(env.Provider("NZ_", ".", func(s string) string {
return strings.Replace(strings.ToLower(strings.TrimPrefix(s, "NZ_")), "_", ".", -1) return strings.ReplaceAll(strings.ToLower(strings.TrimPrefix(s, "NZ_")), "_", ".")
}), nil) }), nil)
if err != nil { if err != nil {
return err return err

View File

@@ -8,8 +8,14 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
) )
type Role uint8
func (r Role) IsAdmin() bool {
return r == RoleAdmin
}
const ( const (
RoleAdmin uint8 = iota RoleAdmin Role = iota
RoleMember RoleMember
) )
@@ -19,13 +25,13 @@ type User struct {
Common Common
Username string `json:"username,omitempty" gorm:"uniqueIndex"` Username string `json:"username,omitempty" gorm:"uniqueIndex"`
Password string `json:"password,omitempty" gorm:"type:char(72)"` Password string `json:"password,omitempty" gorm:"type:char(72)"`
Role uint8 `json:"role,omitempty"` Role Role `json:"role,omitempty"`
AgentSecret string `json:"agent_secret,omitempty" gorm:"type:char(32)"` AgentSecret string `json:"agent_secret,omitempty" gorm:"type:char(32)"`
RejectPassword bool `json:"reject_password,omitempty"` RejectPassword bool `json:"reject_password,omitempty"`
} }
type UserInfo struct { type UserInfo struct {
Role uint8 Role Role
AgentSecret string AgentSecret string
} }

View File

@@ -1,7 +1,7 @@
package model package model
type UserForm struct { type UserForm struct {
Role uint8 `json:"role,omitempty"` Role Role `json:"role,omitempty"`
Username string `json:"username,omitempty"` Username string `json:"username,omitempty"`
Password string `json:"password,omitempty" gorm:"type:char(72)"` Password string `json:"password,omitempty" gorm:"type:char(72)"`
} }

View File

@@ -142,14 +142,14 @@ func checkStatus() {
for _, server := range m { for _, server := range m {
// 监测点 // 监测点
UserLock.RLock() UserLock.RLock()
var role uint8 var role model.Role
if u, ok := UserInfoMap[server.UserID]; !ok { if u, ok := UserInfoMap[alert.UserID]; !ok {
role = model.RoleMember role = model.RoleMember
} else { } else {
role = u.Role role = u.Role
} }
UserLock.RUnlock() UserLock.RUnlock()
if alert.UserID != server.UserID && role != model.RoleAdmin { if alert.UserID != server.UserID && !role.IsAdmin() {
continue continue
} }
alertsStore[alert.ID][server.ID] = append(alertsStore[alert. alertsStore[alert.ID][server.ID] = append(alertsStore[alert.