fix26.2: полная UI-полировка peer/dashboard и завершение i18n
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -102,4 +102,3 @@ func DashboardSecurityRisks(summary vo.DashboardSummaryVo) []vo.SecurityRiskVo {
|
||||
}
|
||||
return risks
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -71,4 +71,3 @@ func TestBuildHysteria2Url_MinimalConfig(t *testing.T) {
|
||||
t.Fatalf("unexpected optional query params in minimal config: %s", parsed.RawQuery)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -82,4 +82,3 @@ func DecryptPeerSecret(stored string) (string, error) {
|
||||
}
|
||||
return util.DecryptAESGCM(stored, key)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user