diff --git a/internal/db/user.go b/internal/db/user.go index f501924..2804f80 100644 --- a/internal/db/user.go +++ b/internal/db/user.go @@ -6,8 +6,6 @@ import ( "github.com/synctv-org/synctv/internal/model" "github.com/synctv-org/synctv/internal/provider" - "github.com/zijiren233/stream" - "golang.org/x/crypto/bcrypt" "gorm.io/gorm" "gorm.io/gorm/clause" ) @@ -186,43 +184,6 @@ func LoadAndDeleteUserByID(userID uint, columns ...clause.Column) (*model.User, return u, nil } -func DeleteUserByUsername(username string) error { - err := db.Unscoped().Where("username = ?", username).Delete(&model.User{}).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return errors.New("user not found") - } - return err -} - -func LoadAndDeleteUserByUsername(username string, columns ...clause.Column) (*model.User, error) { - u := &model.User{} - err := db.Unscoped().Clauses(clause.Returning{Columns: columns}).Where("username = ?", username).Delete(u).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return u, errors.New("user not found") - } - return u, err -} - -func SetUserPassword(userID uint, password string) error { - var hashedPassword []byte - if password != "" { - var err error - hashedPassword, err = bcrypt.GenerateFromPassword(stream.StringToBytes(password), bcrypt.DefaultCost) - if err != nil { - return err - } - } - return SetUserHashedPassword(userID, hashedPassword) -} - -func SetUserHashedPassword(userID uint, hashedPassword []byte) error { - err := db.Model(&model.User{}).Where("id = ?", userID).Update("hashed_password", hashedPassword).Error - if errors.Is(err, gorm.ErrRecordNotFound) { - return errors.New("user not found") - } - return err -} - func SaveUser(u *model.User) error { return db.Save(u).Error } @@ -327,3 +288,11 @@ func GetAllUserWithRoleUserCount(scopes ...func(*gorm.DB) *gorm.DB) int64 { db.Model(&model.User{}).Where("role = ?", model.RoleUser).Scopes(scopes...).Count(&count) return count } + +func SetUsernameByID(userID uint, username string) error { + err := db.Model(&model.User{}).Where("id = ?", userID).Update("username", username).Error + if errors.Is(err, gorm.ErrRecordNotFound) { + return errors.New("user not found") + } + return err +} diff --git a/internal/op/user.go b/internal/op/user.go index 2f5ace4..1e6a489 100644 --- a/internal/op/user.go +++ b/internal/op/user.go @@ -66,3 +66,11 @@ func (u *User) SetRole(role model.Role) error { u.Role = role return nil } + +func (u *User) SetUsername(username string) error { + if err := db.SetUsernameByID(u.ID, username); err != nil { + return err + } + u.Username = username + return nil +} diff --git a/server/handlers/init.go b/server/handlers/init.go index c2f4d83..68f15a4 100644 --- a/server/handlers/init.go +++ b/server/handlers/init.go @@ -128,6 +128,8 @@ func Init(e *gin.Engine) { needAuthUser.GET("/me", Me) needAuthUser.GET("/rooms", UserRooms) + + needAuthUser.POST("/username", SetUsername) } } } diff --git a/server/handlers/user.go b/server/handlers/user.go index ddb5aab..5867f3b 100644 --- a/server/handlers/user.go +++ b/server/handlers/user.go @@ -108,3 +108,21 @@ func UserRooms(ctx *gin.Context) { "list": genRoomListResp(append(scopes, db.Paginate(page, pageSize))...), })) } + +func SetUsername(ctx *gin.Context) { + user := ctx.MustGet("user").(*op.User) + + var req model.SetUsernameReq + if err := model.Decode(ctx, &req); err != nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) + return + } + + err := user.SetUsername(req.Username) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) + return + } + + ctx.Status(http.StatusNoContent) +} diff --git a/server/model/user.go b/server/model/user.go index ab36f89..5fc1ded 100644 --- a/server/model/user.go +++ b/server/model/user.go @@ -51,37 +51,28 @@ func (l *LoginUserReq) Validate() error { return nil } -type SignupUserReq struct { - Username string `json:"username"` - Password string `json:"password"` +type UserInfoResp struct { + ID uint `json:"id"` + Username string `json:"username"` + Role dbModel.Role `json:"role"` + CreatedAt int64 `json:"createdAt"` } -func (s *SignupUserReq) Decode(ctx *gin.Context) error { - return json.NewDecoder(ctx.Request.Body).Decode(s) +type SetUsernameReq struct { + Username string `json:"username"` } -func (s *SignupUserReq) Validate() error { +func (s *SetUsernameReq) Validate() error { if s.Username == "" { return errors.New("username is empty") } else if len(s.Username) > 32 { return ErrUsernameTooLong - } else if !alnumPrintHanReg.MatchString(s.Username) { + } else if !alnumPrintReg.MatchString(s.Username) { return ErrUsernameHasInvalidChar } - - if s.Password == "" { - return FormatEmptyPasswordError("user") - } else if len(s.Password) > 32 { - return ErrPasswordTooLong - } else if !alnumPrintReg.MatchString(s.Password) { - return ErrPasswordHasInvalidChar - } return nil } -type UserInfoResp struct { - ID uint `json:"id"` - Username string `json:"username"` - Role dbModel.Role `json:"role"` - CreatedAt int64 `json:"createdAt"` +func (s *SetUsernameReq) Decode(ctx *gin.Context) error { + return json.NewDecoder(ctx.Request.Body).Decode(s) }