From 48c8ebc1e1dd01fea38f07007e9eb5e416b6fc2f Mon Sep 17 00:00:00 2001 From: uubulb Date: Sat, 21 Dec 2024 22:22:07 +0800 Subject: [PATCH] update permission checks --- cmd/dashboard/controller/alertrule.go | 31 +++++++++++++++-- cmd/dashboard/controller/cron.go | 22 +++++++++++++ cmd/dashboard/controller/nat.go | 18 ++++++++++ .../controller/notification_group.go | 23 +++++++++++++ cmd/dashboard/controller/server.go | 11 +++++++ cmd/dashboard/controller/server_group.go | 22 +++++++++++++ cmd/dashboard/controller/service.go | 33 +++++++++++++++++++ 7 files changed, 157 insertions(+), 3 deletions(-) diff --git a/cmd/dashboard/controller/alertrule.go b/cmd/dashboard/controller/alertrule.go index d67f56e..42842b2 100644 --- a/cmd/dashboard/controller/alertrule.go +++ b/cmd/dashboard/controller/alertrule.go @@ -62,7 +62,7 @@ func createAlertRule(c *gin.Context) (uint64, error) { r.TriggerMode = arf.TriggerMode r.Enable = &enable - if err := validateRule(&r); err != nil { + if err := validateRule(c, &r); err != nil { return 0, err } @@ -116,7 +116,7 @@ func updateAlertRule(c *gin.Context) (any, error) { r.TriggerMode = arf.TriggerMode r.Enable = &enable - if err := validateRule(&r); err != nil { + if err := validateRule(c, &r); err != nil { return 0, err } @@ -164,9 +164,34 @@ func batchDeleteAlertRule(c *gin.Context) (any, error) { return nil, nil } -func validateRule(r *model.AlertRule) error { +func validateRule(c *gin.Context, r *model.AlertRule) error { if len(r.Rules) > 0 { for _, rule := range r.Rules { + singleton.ServerLock.RLock() + isCoverAll := rule.Cover == model.RuleCoverAll + isCoverIgnoreAll := rule.Cover == model.RuleCoverIgnoreAll + for s, enabled := range rule.Ignore { + if isCoverAll { + for id, server := range singleton.ServerList { + if enabled && id == s { + continue + } + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return singleton.Localizer.ErrorT("permission denied") + } + } + } else if isCoverIgnoreAll && enabled { + if server, ok := singleton.ServerList[s]; ok { + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return singleton.Localizer.ErrorT("permission denied") + } + } + } + } + singleton.ServerLock.RUnlock() + if !rule.IsTransferDurationRule() { if rule.Duration < 3 { return singleton.Localizer.ErrorT("duration need to be at least 3") diff --git a/cmd/dashboard/controller/cron.go b/cmd/dashboard/controller/cron.go index 6167cfc..4c54541 100644 --- a/cmd/dashboard/controller/cron.go +++ b/cmd/dashboard/controller/cron.go @@ -49,6 +49,17 @@ func createCron(c *gin.Context) (uint64, error) { return 0, err } + singleton.ServerLock.RLock() + for _, sid := range cf.Servers { + if server, ok := singleton.ServerList[sid]; ok { + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return 0, singleton.Localizer.ErrorT("permission denied") + } + } + } + singleton.ServerLock.RUnlock() + cr.UserID = getUid(c) cr.TaskType = cf.TaskType cr.Name = cf.Name @@ -104,6 +115,17 @@ func updateCron(c *gin.Context) (any, error) { return 0, err } + singleton.ServerLock.RLock() + for _, sid := range cf.Servers { + if server, ok := singleton.ServerList[sid]; ok { + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return nil, singleton.Localizer.ErrorT("permission denied") + } + } + } + singleton.ServerLock.RUnlock() + var cr model.Cron if err := singleton.DB.First(&cr, id).Error; err != nil { return nil, singleton.Localizer.ErrorT("task id %d does not exist", id) diff --git a/cmd/dashboard/controller/nat.go b/cmd/dashboard/controller/nat.go index 731eb37..20260ad 100644 --- a/cmd/dashboard/controller/nat.go +++ b/cmd/dashboard/controller/nat.go @@ -51,6 +51,15 @@ func createNAT(c *gin.Context) (uint64, error) { return 0, err } + singleton.ServerLock.RLock() + if server, ok := singleton.ServerList[nf.ServerID]; ok { + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return 0, singleton.Localizer.ErrorT("permission denied") + } + } + singleton.ServerLock.RUnlock() + uid := getUid(c) n.UserID = uid @@ -93,6 +102,15 @@ func updateNAT(c *gin.Context) (any, error) { return nil, err } + singleton.ServerLock.RLock() + if server, ok := singleton.ServerList[nf.ServerID]; ok { + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return nil, singleton.Localizer.ErrorT("permission denied") + } + } + singleton.ServerLock.RUnlock() + var n model.NAT if err = singleton.DB.First(&n, id).Error; err != nil { return nil, singleton.Localizer.ErrorT("profile id %d does not exist", id) diff --git a/cmd/dashboard/controller/notification_group.go b/cmd/dashboard/controller/notification_group.go index e202de3..8f5eef6 100644 --- a/cmd/dashboard/controller/notification_group.go +++ b/cmd/dashboard/controller/notification_group.go @@ -68,6 +68,17 @@ func createNotificationGroup(c *gin.Context) (uint64, error) { } ngf.Notifications = slices.Compact(ngf.Notifications) + singleton.NotificationsLock.RLock() + for _, nid := range ngf.Notifications { + if n, ok := singleton.NotificationMap[nid]; ok { + if !n.HasPermission(c) { + singleton.NotificationsLock.RUnlock() + return 0, singleton.Localizer.ErrorT("permission denied") + } + } + } + singleton.NotificationsLock.RUnlock() + uid := getUid(c) var ng model.NotificationGroup @@ -132,6 +143,18 @@ func updateNotificationGroup(c *gin.Context) (any, error) { if err := c.ShouldBindJSON(&ngf); err != nil { return nil, err } + + singleton.NotificationsLock.RLock() + for _, nid := range ngf.Notifications { + if n, ok := singleton.NotificationMap[nid]; ok { + if !n.HasPermission(c) { + singleton.NotificationsLock.RUnlock() + return nil, singleton.Localizer.ErrorT("permission denied") + } + } + } + singleton.NotificationsLock.RUnlock() + var ngDB model.NotificationGroup if err := singleton.DB.First(&ngDB, id).Error; err != nil { return nil, singleton.Localizer.ErrorT("group id %d does not exist", id) diff --git a/cmd/dashboard/controller/server.go b/cmd/dashboard/controller/server.go index 36bfa7e..85d9fb7 100644 --- a/cmd/dashboard/controller/server.go +++ b/cmd/dashboard/controller/server.go @@ -56,6 +56,17 @@ func updateServer(c *gin.Context) (any, error) { return nil, err } + singleton.DDNSCacheLock.RLock() + for _, pid := range sf.DDNSProfiles { + if p, ok := singleton.DDNSCache[pid]; ok { + if !p.HasPermission(c) { + singleton.DDNSCacheLock.RUnlock() + return nil, singleton.Localizer.ErrorT("permission denied") + } + } + } + singleton.DDNSCacheLock.RUnlock() + var s model.Server if err := singleton.DB.First(&s, id).Error; err != nil { return nil, singleton.Localizer.ErrorT("server id %d does not exist", id) diff --git a/cmd/dashboard/controller/server_group.go b/cmd/dashboard/controller/server_group.go index 0373b57..7655a9b 100644 --- a/cmd/dashboard/controller/server_group.go +++ b/cmd/dashboard/controller/server_group.go @@ -67,6 +67,17 @@ func createServerGroup(c *gin.Context) (uint64, error) { } sgf.Servers = slices.Compact(sgf.Servers) + singleton.ServerLock.RLock() + for _, sid := range sgf.Servers { + if server, ok := singleton.ServerList[sid]; ok { + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return 0, singleton.Localizer.ErrorT("permission denied") + } + } + } + singleton.ServerLock.RUnlock() + uid := getUid(c) var sg model.ServerGroup @@ -131,6 +142,17 @@ func updateServerGroup(c *gin.Context) (any, error) { } sg.Servers = slices.Compact(sg.Servers) + singleton.ServerLock.RLock() + for _, sid := range sg.Servers { + if server, ok := singleton.ServerList[sid]; ok { + if !server.HasPermission(c) { + singleton.ServerLock.RUnlock() + return nil, singleton.Localizer.ErrorT("permission denied") + } + } + } + singleton.ServerLock.RUnlock() + var sgDB model.ServerGroup if err := singleton.DB.First(&sgDB, id).Error; err != nil { return nil, singleton.Localizer.ErrorT("group id %d does not exist", id) diff --git a/cmd/dashboard/controller/service.go b/cmd/dashboard/controller/service.go index e28e761..70f4d2a 100644 --- a/cmd/dashboard/controller/service.go +++ b/cmd/dashboard/controller/service.go @@ -210,6 +210,10 @@ func createService(c *gin.Context) (uint64, error) { m.RecoverTriggerTasks = mf.RecoverTriggerTasks m.FailTriggerTasks = mf.FailTriggerTasks + if err := validateServers(c, &m); err != nil { + return 0, err + } + if err := singleton.DB.Create(&m).Error; err != nil { return 0, newGormError("%v", err) } @@ -351,3 +355,32 @@ func batchDeleteService(c *gin.Context) (any, error) { singleton.ServiceSentinelShared.UpdateServiceList() return nil, nil } + +func validateServers(c *gin.Context, ss *model.Service) error { + singleton.ServerLock.RLock() + defer singleton.ServerLock.RUnlock() + + isCoverAll := ss.Cover == model.ServiceCoverAll + isCoverIgnoreAll := ss.Cover == model.ServiceCoverIgnoreAll + + for s, enabled := range ss.SkipServers { + if isCoverAll { + for id, server := range singleton.ServerList { + if enabled && id == s { + continue + } + if !server.HasPermission(c) { + return singleton.Localizer.ErrorT("permission denied") + } + } + } else if isCoverIgnoreAll && enabled { + if server, ok := singleton.ServerList[s]; ok { + if !server.HasPermission(c) { + return singleton.Localizer.ErrorT("permission denied") + } + } + } + } + + return nil +}