mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
fix(service): filter service stats based on user permissions
This commit is contained in:
@@ -268,7 +268,10 @@ func TestShowServiceFiltersCycleTransferStatsLikeServerList(t *testing.T) {
|
||||
serviceSentinel, err := singleton.NewServiceSentinel(make(chan *model.Service, 2))
|
||||
assert.NoError(t, err)
|
||||
singleton.ServiceSentinelShared = serviceSentinel
|
||||
t.Cleanup(func() { singleton.ServiceSentinelShared = originalServiceSentinel })
|
||||
t.Cleanup(func() {
|
||||
serviceSentinel.Close()
|
||||
singleton.ServiceSentinelShared = originalServiceSentinel
|
||||
})
|
||||
|
||||
singleton.AlertsLock.Lock()
|
||||
originalCycleTransferStats := singleton.AlertsCycleTransferStatsStore
|
||||
@@ -288,23 +291,27 @@ func TestShowServiceFiltersCycleTransferStatsLikeServerList(t *testing.T) {
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
viewer *model.User
|
||||
wantNames map[uint64]string
|
||||
name string
|
||||
viewer *model.User
|
||||
wantServices []uint64
|
||||
wantNames map[uint64]string
|
||||
}{
|
||||
{
|
||||
name: "guest sees public servers only",
|
||||
wantNames: map[uint64]string{1: "public server"},
|
||||
name: "guest sees public servers only",
|
||||
wantServices: []uint64{10},
|
||||
wantNames: map[uint64]string{1: "public server"},
|
||||
},
|
||||
{
|
||||
name: "member sees public and owned hidden servers",
|
||||
viewer: &model.User{Common: model.Common{ID: 200}, Role: model.RoleMember},
|
||||
wantNames: map[uint64]string{1: "public server", 3: "hidden member server"},
|
||||
name: "member sees public and owned hidden servers",
|
||||
viewer: &model.User{Common: model.Common{ID: 200}, Role: model.RoleMember},
|
||||
wantServices: []uint64{10},
|
||||
wantNames: map[uint64]string{1: "public server", 3: "hidden member server"},
|
||||
},
|
||||
{
|
||||
name: "admin sees every server",
|
||||
viewer: &model.User{Common: model.Common{ID: 1}, Role: model.RoleAdmin},
|
||||
wantNames: map[uint64]string{1: "public server", 2: "hidden admin server", 3: "hidden member server"},
|
||||
name: "admin sees every server",
|
||||
viewer: &model.User{Common: model.Common{ID: 1}, Role: model.RoleAdmin},
|
||||
wantServices: []uint64{10, 11},
|
||||
wantNames: map[uint64]string{1: "public server", 2: "hidden admin server", 3: "hidden member server"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -317,8 +324,7 @@ func TestShowServiceFiltersCycleTransferStatsLikeServerList(t *testing.T) {
|
||||
|
||||
got, err := showService(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, got.Services, uint64(10))
|
||||
assert.NotContains(t, got.Services, uint64(11))
|
||||
assert.ElementsMatch(t, tc.wantServices, serviceResponseIDs(got.Services))
|
||||
if assert.Contains(t, got.CycleTransferStats, uint64(7)) {
|
||||
cycleStats := got.CycleTransferStats[7]
|
||||
assert.Equal(t, tc.wantNames, cycleStats.ServerName)
|
||||
@@ -335,6 +341,14 @@ func TestShowServiceFiltersCycleTransferStatsLikeServerList(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func serviceResponseIDs(stats map[uint64]model.ServiceResponseItem) []uint64 {
|
||||
ids := make([]uint64, 0, len(stats))
|
||||
for id := range stats {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func decodeIDs[T ~uint64](t *testing.T, body []byte) []T {
|
||||
t.Helper()
|
||||
var resp struct {
|
||||
|
||||
@@ -29,7 +29,7 @@ func showService(c *gin.Context) (*model.ServiceResponse, error) {
|
||||
res, err, _ := requestGroup.Do(serviceResponseCacheKey(c), func() (any, error) {
|
||||
singleton.AlertsLock.RLock()
|
||||
defer singleton.AlertsLock.RUnlock()
|
||||
stats := singleton.ServiceSentinelShared.CopyStats()
|
||||
stats := filterServiceStatsForViewer(c, singleton.ServiceSentinelShared.CopyStats())
|
||||
var cycleTransferStats map[uint64]model.CycleTransferStats
|
||||
copier.Copy(&cycleTransferStats, singleton.AlertsCycleTransferStatsStore)
|
||||
return []any{
|
||||
@@ -46,6 +46,22 @@ func showService(c *gin.Context) (*model.ServiceResponse, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func filterServiceStatsForViewer(c *gin.Context, stats map[uint64]model.ServiceResponseItem) map[uint64]model.ServiceResponseItem {
|
||||
if len(stats) == 0 {
|
||||
return stats
|
||||
}
|
||||
services := singleton.ServiceSentinelShared.GetList()
|
||||
filteredStats := make(map[uint64]model.ServiceResponseItem, len(stats))
|
||||
for serviceID, stat := range stats {
|
||||
service, ok := services[serviceID]
|
||||
if !ok || !userCanViewService(c, service) {
|
||||
continue
|
||||
}
|
||||
filteredStats[serviceID] = stat
|
||||
}
|
||||
return filteredStats
|
||||
}
|
||||
|
||||
func serviceResponseCacheKey(c *gin.Context) string {
|
||||
auth, ok := c.Get(model.CtxKeyAuthorizedUser)
|
||||
if !ok {
|
||||
|
||||
@@ -438,11 +438,6 @@ func (ss *ServiceSentinel) CopyStats() map[uint64]model.ServiceResponseItem {
|
||||
|
||||
sri := make(map[uint64]model.ServiceResponseItem)
|
||||
for k, service := range stats {
|
||||
if service.service.HideForGuest {
|
||||
delete(stats, k)
|
||||
continue
|
||||
}
|
||||
|
||||
service.ServiceName = service.service.Name
|
||||
sri[k] = service.ServiceResponseItem
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user