diff --git a/cmd/dashboard/controller/controller.go b/cmd/dashboard/controller/controller.go index 4d398b4..56233f5 100644 --- a/cmd/dashboard/controller/controller.go +++ b/cmd/dashboard/controller/controller.go @@ -74,6 +74,7 @@ func routers(r *gin.Engine) { auth.GET("/ws/file/:id", commonHandler(fmStream)) auth.GET("/profile", commonHandler(getProfile)) + auth.POST("/profile", commonHandler(updateProfile)) auth.GET("/user", commonHandler(listUser)) auth.POST("/user", commonHandler(createUser)) auth.POST("/batch-delete/user", commonHandler(batchDeleteUser)) diff --git a/cmd/dashboard/controller/user.go b/cmd/dashboard/controller/user.go index 395e4d1..01bee18 100644 --- a/cmd/dashboard/controller/user.go +++ b/cmd/dashboard/controller/user.go @@ -30,6 +30,46 @@ func getProfile(c *gin.Context) (*model.Profile, error) { }, nil } +// Update password for current user +// @Summary Update password for current user +// @Security BearerAuth +// @Schemes +// @Description Update password for current user +// @Tags auth required +// @Accept json +// @param request body model.ProfileForm true "password" +// @Produce json +// @Success 200 {object} model.CommonResponse[any] +// @Router /profile [post] +func updateProfile(c *gin.Context) (any, error) { + var pf model.ProfileForm + if err := c.ShouldBindJSON(&pf); err != nil { + return 0, err + } + + auth, ok := c.Get(model.CtxKeyAuthorizedUser) + if !ok { + return nil, singleton.Localizer.ErrorT("unauthorized") + } + + user := *auth.(*model.User) + if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(pf.OriginalPassword)); err != nil { + return nil, singleton.Localizer.ErrorT("incorrect password") + } + + hash, err := bcrypt.GenerateFromPassword([]byte(pf.NewPassword), bcrypt.DefaultCost) + if err != nil { + return nil, err + } + + user.Password = string(hash) + if err := singleton.DB.Save(&user).Error; err != nil { + return nil, newGormError("%v", err) + } + + return nil, nil +} + // List user // @Summary List user // @Security BearerAuth diff --git a/cmd/dashboard/controller/ws.go b/cmd/dashboard/controller/ws.go index a858ed3..2aae7f9 100644 --- a/cmd/dashboard/controller/ws.go +++ b/cmd/dashboard/controller/ws.go @@ -108,6 +108,10 @@ func getServerStat(c *gin.Context, withPublicNote bool) ([]byte, error) { servers := make([]model.StreamServer, 0, len(serverList)) for _, server := range serverList { + var countryCode string + if server.GeoIP != nil { + countryCode = server.GeoIP.CountryCode + } servers = append(servers, model.StreamServer{ ID: server.ID, Name: server.Name, @@ -115,6 +119,7 @@ func getServerStat(c *gin.Context, withPublicNote bool) ([]byte, error) { DisplayIndex: server.DisplayIndex, Host: server.Host, State: server.State, + CountryCode: countryCode, LastActive: server.LastActive, }) } diff --git a/model/server.go b/model/server.go index fc413a3..5e2fcd1 100644 --- a/model/server.go +++ b/model/server.go @@ -23,7 +23,7 @@ type Server struct { EnableDDNS bool `json:"enable_ddns,omitempty"` // 启用DDNS DDNSProfilesRaw string `gorm:"default:'[]';column:ddns_profiles_raw" json:"-"` - DDNSProfiles []uint64 `gorm:"-" json:"ddns_profiles"` // DDNS配置 + DDNSProfiles []uint64 `gorm:"-" json:"ddns_profiles,omitempty"` // DDNS配置 Host *Host `gorm:"-" json:"host,omitempty"` State *HostState `gorm:"-" json:"state,omitempty"` diff --git a/model/server_api.go b/model/server_api.go index 867bd7c..4edfa8e 100644 --- a/model/server_api.go +++ b/model/server_api.go @@ -8,9 +8,10 @@ type StreamServer struct { PublicNote string `json:"public_note,omitempty"` // 公开备注,只第一个数据包有值 DisplayIndex int `json:"display_index,omitempty"` // 展示排序,越大越靠前 - Host *Host `json:"host,omitempty"` - State *HostState `json:"state,omitempty"` - LastActive time.Time `json:"last_active,omitempty"` + Host *Host `json:"host,omitempty"` + State *HostState `json:"state,omitempty"` + CountryCode string `json:"country_code,omitempty"` + LastActive time.Time `json:"last_active,omitempty"` } type StreamServerData struct { @@ -20,12 +21,12 @@ type StreamServerData struct { type ServerForm struct { Name string `json:"name,omitempty"` - Note string `json:"note,omitempty" validate:"optional"` // 管理员可见备注 - PublicNote string `json:"public_note,omitempty" validate:"optional"` // 公开备注 - DisplayIndex int `json:"display_index,omitempty" default:"0"` // 展示排序,越大越靠前 - HideForGuest bool `json:"hide_for_guest,omitempty" validate:"optional"` // 对游客隐藏 - EnableDDNS bool `json:"enable_ddns,omitempty" validate:"optional"` // 启用DDNS - DDNSProfiles []uint64 `gorm:"-" json:"ddns_profiles,omitempty"` // DDNS配置 + Note string `json:"note,omitempty" validate:"optional"` // 管理员可见备注 + PublicNote string `json:"public_note,omitempty" validate:"optional"` // 公开备注 + DisplayIndex int `json:"display_index,omitempty" default:"0"` // 展示排序,越大越靠前 + HideForGuest bool `json:"hide_for_guest,omitempty" validate:"optional"` // 对游客隐藏 + EnableDDNS bool `json:"enable_ddns,omitempty" validate:"optional"` // 启用DDNS + DDNSProfiles []uint64 `gorm:"-" json:"ddns_profiles,omitempty" validate:"optional"` // DDNS配置 } type ForceUpdateResponse struct { diff --git a/model/user_api.go b/model/user_api.go index 135dce0..05c62e0 100644 --- a/model/user_api.go +++ b/model/user_api.go @@ -4,3 +4,8 @@ type UserForm struct { Username string `json:"username,omitempty"` Password string `json:"password,omitempty" gorm:"type:char(72)"` } + +type ProfileForm struct { + OriginalPassword string `json:"original_password,omitempty"` + NewPassword string `json:"new_password,omitempty"` +}