fix26.2: полная UI-полировка peer/dashboard и завершение i18n

This commit is contained in:
2026-05-09 01:38:57 +05:00
parent c13841b61a
commit db3c88c58a
42 changed files with 421 additions and 198 deletions
+21 -6
View File
@@ -13,6 +13,18 @@ import (
"hy2xs-admin/util"
)
func adminClaimsFromContext(c *gin.Context) (bo.AccountBo, bool) {
if c == nil {
return bo.AccountBo{}, false
}
v, ok := c.Get("adminClaims")
if !ok {
return bo.AccountBo{}, false
}
claims, castOK := v.(bo.AccountBo)
return claims, castOK
}
func Login(username string, plainPassword string) (string, bool, error) {
admin, err := dao.GetAdminUser("username = ? and status = 1", username)
if err != nil {
@@ -45,11 +57,15 @@ func Login(username string, plainPassword string) (string, bool, error) {
}
func GetAdminInfo(c *gin.Context) (vo.AdminInfoVo, error) {
myClaims, err := ParseToken(GetToken(c))
if err != nil {
return vo.AdminInfoVo{}, err
claims, ok := adminClaimsFromContext(c)
if !ok {
myClaims, err := ParseToken(GetToken(c))
if err != nil {
return vo.AdminInfoVo{}, err
}
claims = myClaims.Admin
}
admin, err := dao.GetAdminUser("id = ?", myClaims.Admin.Id)
admin, err := dao.GetAdminUser("id = ?", claims.Id)
if err != nil {
return vo.AdminInfoVo{}, err
}
@@ -57,7 +73,7 @@ func GetAdminInfo(c *gin.Context) (vo.AdminInfoVo, error) {
return vo.AdminInfoVo{}, errors.New("this account has been disabled")
}
force := admin.ForcePasswordChange != nil && *admin.ForcePasswordChange != 0
return vo.AdminInfoVo{Id: myClaims.Admin.Id, Username: myClaims.Admin.Username, Roles: myClaims.Admin.Roles, ForcePasswordChange: force}, nil
return vo.AdminInfoVo{Id: claims.Id, Username: claims.Username, Roles: claims.Roles, ForcePasswordChange: force}, nil
}
func UpdateAdminLastLoginAt(id int64, loginAt int64) error {
@@ -100,4 +116,3 @@ func ChangeAdminPassword(c *gin.Context, oldPassword string, newPassword string)
func GetAdminForTokenValidation(id int64) (entity.AdminUser, error) {
return dao.GetAdminUser("id = ?", id)
}
-1
View File
@@ -102,4 +102,3 @@ func DashboardSecurityRisks(summary vo.DashboardSummaryVo) []vo.SecurityRiskVo {
}
return risks
}
+3 -1
View File
@@ -2,6 +2,7 @@ package service
import (
"errors"
"github.com/sirupsen/logrus"
"hy2xs-admin/dao"
"hy2xs-admin/model/constant"
"hy2xs-admin/proxy"
@@ -51,7 +52,8 @@ func Hysteria2Auth(conPass string) (int64, string, error) {
// Ограничение количества устройств
onlineUsers, err := Hysteria2Online()
if err != nil {
return 0, "", err
logrus.WithError(err).Warn("hysteria2 online users unavailable; skip device-limit check")
return *peer.Id, *peer.AuthId, nil
}
device, exist := onlineUsers[*peer.AuthId]
if exist && *peer.MaxDevices <= device {
-1
View File
@@ -71,4 +71,3 @@ func TestBuildHysteria2Url_MinimalConfig(t *testing.T) {
t.Fatalf("unexpected optional query params in minimal config: %s", parsed.RawQuery)
}
}
+36 -6
View File
@@ -9,6 +9,8 @@ import (
"time"
)
const hysteriaVersionCacheTTL = 15 * time.Minute
type metricsSnapshot struct {
CollectedAt int64
System vo.DashboardSystemVo
@@ -23,12 +25,41 @@ var metricsStore = struct {
sync.RWMutex
snapshot metricsSnapshot
lastSuccessAt int64
version string
versionAt time.Time
}{}
func getCachedHysteriaVersion(now time.Time) string {
metricsStore.RLock()
if metricsStore.version != "" && now.Sub(metricsStore.versionAt) < hysteriaVersionCacheTTL {
v := metricsStore.version
metricsStore.RUnlock()
return v
}
metricsStore.RUnlock()
content, err := util.Exec(util.GetHysteria2BinPath() + " version")
if err != nil {
metricsStore.RLock()
v := metricsStore.version
metricsStore.RUnlock()
if v != "" {
return v
}
return "-"
}
metricsStore.Lock()
metricsStore.version = content
metricsStore.versionAt = now
metricsStore.Unlock()
return content
}
func CollectMetricsSnapshot() {
nowMs := time.Now().UnixMilli()
s := metricsSnapshot{
CollectedAt: nowMs,
CollectedAt: nowMs,
CollectorState: vo.DataHealthVo{Status: "ok", LastSuccessAt: nowMs},
HysteriaState: vo.DataHealthVo{Status: "ok", LastSuccessAt: nowMs},
}
@@ -52,10 +83,7 @@ func CollectMetricsSnapshot() {
}
s.Hysteria.Running = Hysteria2IsRunning()
s.Hysteria.Version = "-"
if content, err := util.Exec(util.GetHysteria2BinPath() + " version"); err == nil {
s.Hysteria.Version = content
}
s.Hysteria.Version = getCachedHysteriaVersion(time.Now())
if onlineMap, err := Hysteria2Online(); err == nil {
s.Hysteria.ApiReachable = true
@@ -80,6 +108,9 @@ func CollectMetricsSnapshot() {
running = 1
}
diskPath := "/"
if configured := util.GetEnvDiskPath(); configured != "" {
diskPath = configured
}
metric := entity.MetricSample{
SampledAt: &nowMs,
CpuPercent: &s.System.CpuPercent,
@@ -108,4 +139,3 @@ func DashboardSnapshot() metricsSnapshot {
defer metricsStore.RUnlock()
return metricsStore.snapshot
}
+20 -7
View File
@@ -24,7 +24,7 @@ func PagePeer(peerPageDto dto.PeerPageDto) ([]vo.PeerVo, int64, error) {
result := make([]vo.PeerVo, 0, len(peers))
for _, p := range peers {
item := vo.PeerVo{
BaseVo: vo.BaseVo{Id: *p.Id, CreateTime: *p.CreateTime},
BaseVo: vo.BaseVo{Id: *p.Id, CreateTime: *p.CreateTime},
Name: strVal(p.Name),
Remark: strVal(p.Remark),
AuthId: strVal(p.AuthId),
@@ -137,7 +137,7 @@ func GetPeerVo(id int64) (vo.PeerVo, error) {
return vo.PeerVo{}, err
}
return vo.PeerVo{
BaseVo: vo.BaseVo{Id: *p.Id, CreateTime: *p.CreateTime},
BaseVo: vo.BaseVo{Id: *p.Id, CreateTime: *p.CreateTime},
Name: strVal(p.Name),
Remark: strVal(p.Remark),
AuthId: strVal(p.AuthId),
@@ -152,8 +152,12 @@ func GetPeerVo(id int64) (vo.PeerVo, error) {
}, nil
}
func ResetPeerTraffic(id int64) error { return dao.UpdatePeer([]int64{id}, map[string]interface{}{"download_bytes": 0, "upload_bytes": 0}) }
func ReleaseKickPeer(id int64) error { return dao.UpdatePeer([]int64{id}, map[string]interface{}{"banned_until": 0}) }
func ResetPeerTraffic(id int64) error {
return dao.UpdatePeer([]int64{id}, map[string]interface{}{"download_bytes": 0, "upload_bytes": 0})
}
func ReleaseKickPeer(id int64) error {
return dao.UpdatePeer([]int64{id}, map[string]interface{}{"banned_until": 0})
}
func KickPeer(id int64, bannedUntil int64) error {
if err := dao.UpdatePeer([]int64{id}, map[string]interface{}{"banned_until": bannedUntil}); err != nil {
@@ -324,6 +328,15 @@ func UpdatePeerLastConnectionAt(id int64, conAt int64) error {
return dao.UpdatePeer([]int64{id}, map[string]interface{}{"last_connection_at": conAt})
}
func strVal(v *string) string { if v == nil { return "" }; return *v }
func int64Val(v *int64) int64 { if v == nil { return 0 }; return *v }
func strVal(v *string) string {
if v == nil {
return ""
}
return *v
}
func int64Val(v *int64) int64 {
if v == nil {
return 0
}
return *v
}
-1
View File
@@ -82,4 +82,3 @@ func DecryptPeerSecret(stored string) (string, error) {
}
return util.DecryptAESGCM(stored, key)
}