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))
|
serviceSentinel, err := singleton.NewServiceSentinel(make(chan *model.Service, 2))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
singleton.ServiceSentinelShared = serviceSentinel
|
singleton.ServiceSentinelShared = serviceSentinel
|
||||||
t.Cleanup(func() { singleton.ServiceSentinelShared = originalServiceSentinel })
|
t.Cleanup(func() {
|
||||||
|
serviceSentinel.Close()
|
||||||
|
singleton.ServiceSentinelShared = originalServiceSentinel
|
||||||
|
})
|
||||||
|
|
||||||
singleton.AlertsLock.Lock()
|
singleton.AlertsLock.Lock()
|
||||||
originalCycleTransferStats := singleton.AlertsCycleTransferStatsStore
|
originalCycleTransferStats := singleton.AlertsCycleTransferStatsStore
|
||||||
@@ -288,23 +291,27 @@ func TestShowServiceFiltersCycleTransferStatsLikeServerList(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
viewer *model.User
|
viewer *model.User
|
||||||
wantNames map[uint64]string
|
wantServices []uint64
|
||||||
|
wantNames map[uint64]string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "guest sees public servers only",
|
name: "guest sees public servers only",
|
||||||
wantNames: map[uint64]string{1: "public server"},
|
wantServices: []uint64{10},
|
||||||
|
wantNames: map[uint64]string{1: "public server"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "member sees public and owned hidden servers",
|
name: "member sees public and owned hidden servers",
|
||||||
viewer: &model.User{Common: model.Common{ID: 200}, Role: model.RoleMember},
|
viewer: &model.User{Common: model.Common{ID: 200}, Role: model.RoleMember},
|
||||||
wantNames: map[uint64]string{1: "public server", 3: "hidden member server"},
|
wantServices: []uint64{10},
|
||||||
|
wantNames: map[uint64]string{1: "public server", 3: "hidden member server"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "admin sees every server",
|
name: "admin sees every server",
|
||||||
viewer: &model.User{Common: model.Common{ID: 1}, Role: model.RoleAdmin},
|
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"},
|
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)
|
got, err := showService(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Contains(t, got.Services, uint64(10))
|
assert.ElementsMatch(t, tc.wantServices, serviceResponseIDs(got.Services))
|
||||||
assert.NotContains(t, got.Services, uint64(11))
|
|
||||||
if assert.Contains(t, got.CycleTransferStats, uint64(7)) {
|
if assert.Contains(t, got.CycleTransferStats, uint64(7)) {
|
||||||
cycleStats := got.CycleTransferStats[7]
|
cycleStats := got.CycleTransferStats[7]
|
||||||
assert.Equal(t, tc.wantNames, cycleStats.ServerName)
|
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 {
|
func decodeIDs[T ~uint64](t *testing.T, body []byte) []T {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
var resp struct {
|
var resp struct {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func showService(c *gin.Context) (*model.ServiceResponse, error) {
|
|||||||
res, err, _ := requestGroup.Do(serviceResponseCacheKey(c), func() (any, error) {
|
res, err, _ := requestGroup.Do(serviceResponseCacheKey(c), func() (any, error) {
|
||||||
singleton.AlertsLock.RLock()
|
singleton.AlertsLock.RLock()
|
||||||
defer singleton.AlertsLock.RUnlock()
|
defer singleton.AlertsLock.RUnlock()
|
||||||
stats := singleton.ServiceSentinelShared.CopyStats()
|
stats := filterServiceStatsForViewer(c, singleton.ServiceSentinelShared.CopyStats())
|
||||||
var cycleTransferStats map[uint64]model.CycleTransferStats
|
var cycleTransferStats map[uint64]model.CycleTransferStats
|
||||||
copier.Copy(&cycleTransferStats, singleton.AlertsCycleTransferStatsStore)
|
copier.Copy(&cycleTransferStats, singleton.AlertsCycleTransferStatsStore)
|
||||||
return []any{
|
return []any{
|
||||||
@@ -46,6 +46,22 @@ func showService(c *gin.Context) (*model.ServiceResponse, error) {
|
|||||||
}, nil
|
}, 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 {
|
func serviceResponseCacheKey(c *gin.Context) string {
|
||||||
auth, ok := c.Get(model.CtxKeyAuthorizedUser)
|
auth, ok := c.Get(model.CtxKeyAuthorizedUser)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -438,11 +438,6 @@ func (ss *ServiceSentinel) CopyStats() map[uint64]model.ServiceResponseItem {
|
|||||||
|
|
||||||
sri := make(map[uint64]model.ServiceResponseItem)
|
sri := make(map[uint64]model.ServiceResponseItem)
|
||||||
for k, service := range stats {
|
for k, service := range stats {
|
||||||
if service.service.HideForGuest {
|
|
||||||
delete(stats, k)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
service.ServiceName = service.service.Name
|
service.ServiceName = service.service.Name
|
||||||
sri[k] = service.ServiceResponseItem
|
sri[k] = service.ServiceResponseItem
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user