Skip to content

Commit

Permalink
feat: update user info && fix some errors (#15)
Browse files Browse the repository at this point in the history
and refactor some code --
---------

Co-authored-by: ckappgit <[email protected]>
  • Loading branch information
Tohrusky and ckappgit authored Jul 14, 2024
1 parent 7352264 commit 0191f13
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 66 deletions.
16 changes: 13 additions & 3 deletions internal/common/dao/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ func CreateUser(user *model.User) (err error) {
return err
}

// SetUserPassword 修改用户密码
func SetUserPassword(user *model.User, newpass string) (err error) {
// SetUserPassword 设置用户密码
func SetUserPassword(user *model.User, newPassword string) (err error) {
u := query.User
password, err := bcrypt.GenerateFromPassword([]byte(newpass), bcrypt.DefaultCost)
password, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
if err != nil {
return err
}
Expand All @@ -27,6 +27,16 @@ func SetUserPassword(user *model.User, newpass string) (err error) {
return err
}

// UpdateUserDataByUserID 根据 map 更新用户信息,map 中的 key 为字段名
func UpdateUserDataByUserID(userID int32, maps map[string]interface{}) (err error) {
u := query.User
_, err = u.Where(u.UserID.Eq(userID)).Updates(maps)
if err != nil {
return err
}
return err
}

// GetUserByEmail 根据 email 获取用户
func GetUserByEmail(email string) (user *model.User, err error) {
q := query.User
Expand Down
13 changes: 8 additions & 5 deletions internal/router/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ func NewAPI() *gin.Engine {
jwt.RequireAuth(cache.Clients[cache.JWTBlacklist], true), // 把 token 拉黑
user_service.Logout,
)
// 修改密码
user.POST("password/reset",
jwt.RequireAuth(cache.Clients[cache.JWTBlacklist], false),
user_service.ResetPassword)
// 用户信息
user.GET("profile/me",
jwt.RequireAuth(cache.Clients[cache.JWTBlacklist], false),
Expand All @@ -51,11 +55,10 @@ func NewAPI() *gin.Engine {
middleware_cache.Response(cache.Clients[cache.RespCache], 1*time.Minute),
user_service.ProfileOthers,
)

// 修改密码
user.POST("password/reset",
jwt.RequireAuth(cache.Clients[cache.JWTBlacklist], true), // 把 token 拉黑
user_service.ResetPassword)
// 用户信息更新
user.POST("profile/update",
jwt.RequireAuth(cache.Clients[cache.JWTBlacklist], false),
user_service.ProfileUpdate)
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/service/user/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type LoginResponse struct {
func Login(c *gin.Context) {
var req LoginRequest
if err := c.ShouldBindJSON(&req); err != nil {
util.AbortWithMsg(c, "invalid request")
util.AbortWithMsg(c, "invalid request: "+err.Error())
return
}

Expand Down
8 changes: 2 additions & 6 deletions internal/service/user/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@ import (

// Logout 用户登出 (POST /logout)
func Logout(c *gin.Context) {
user, err := util.GetUserIDFromGinContext(c)
if err != nil {
util.AbortWithMsg(c, "Please login first")
return
}
userID, _ := util.GetUserIDFromGinContext(c)

util.OKWithMsg(c, "Logout success")

log.Logger.Info("Logout success: " + util.StructToString(user))
log.Logger.Info("Logout success, user ID: " + util.StructToString(userID))
}
66 changes: 28 additions & 38 deletions internal/service/user/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ type ProfileResponse struct {
Avatar string `json:"avatar"`
Background string `json:"background"`
CreatedAt string `json:"created_at"`
Email string `json:"email"`
Experience string `json:"experience"`
Inviter string `json:"inviter"`
Email *string `json:"email,omitempty"`
Experience *int32 `json:"experience,omitempty"`
Inviter *int32 `json:"inviter,omitempty"`
LastActive string `json:"last_active"`
Private bool `json:"private"`
Roles []string `json:"roles,omitempty"`
Expand All @@ -25,16 +25,12 @@ type ProfileResponse struct {
}

type ProfileOthersRequest struct {
UserId int32 `form:"user_id" binding:"required"`
UserID int32 `form:"user_id" binding:"required"`
}

// ProfileMe 获取用户自己的信息 (GET /profile/me)
func ProfileMe(c *gin.Context) {
userID, err := util.GetUserIDFromGinContext(c)
if err != nil {
util.AbortWithMsg(c, "Please login first")
return
}
userID, _ := util.GetUserIDFromGinContext(c)

user, err := dao.GetUserByID(userID)
if err != nil {
Expand All @@ -52,9 +48,9 @@ func ProfileMe(c *gin.Context) {
Avatar: user.Avatar,
Background: user.Background,
CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
Email: user.Email,
Experience: strconv.Itoa(int(user.Experience)),
Inviter: strconv.Itoa(int(user.Inviter)),
Email: &user.Email,
Experience: &user.Experience,
Inviter: &user.Inviter,
LastActive: user.LastActive.Format("2006-01-02 15:04:05"),
Private: user.Private,
Roles: roles,
Expand All @@ -71,29 +67,20 @@ func ProfileOthers(c *gin.Context) {
// 绑定参数
var req ProfileOthersRequest
if err := c.ShouldBindQuery(&req); err != nil {
util.AbortWithMsg(c, "invalid request")
return
}
// 鉴权
userID, err := util.GetUserIDFromGinContext(c)
if err != nil {
util.AbortWithMsg(c, "Please login first")
return
}
// 仅用于鉴权不使用
_, err = dao.GetUserByID(userID)
if err != nil {
util.AbortWithMsg(c, "User not found")
util.AbortWithMsg(c, "invalid request: "+err.Error())
return
}

userID, _ := util.GetUserIDFromGinContext(c)

// 获取信息
user, err := dao.GetUserByID(req.UserId)
user, err := dao.GetUserByID(req.UserID)
if err != nil {
util.AbortWithMsg(c, "User not found")
return
}

roles, err := dao.GetUserRolesByID(userID)
roles, err := dao.GetUserRolesByID(req.UserID)
if err != nil {
log.Logger.Info("Failed to get user roles: " + err.Error())
roles = []string{}
Expand All @@ -104,14 +91,14 @@ func ProfileOthers(c *gin.Context) {
util.OKWithData(c, ProfileResponse{
Avatar: user.Avatar,
Background: user.Background,
CreatedAt: "",
Email: "",
Experience: "",
Inviter: "",
LastActive: "",
Private: user.Private,
CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
Email: nil,
Experience: nil,
Inviter: nil,
LastActive: user.LastActive.Format("2006-01-02 15:04:05"),
Private: true,
Roles: nil,
Signature: "",
Signature: user.Signature,
UserID: user.UserID,
Username: user.Username,
})
Expand All @@ -121,15 +108,18 @@ func ProfileOthers(c *gin.Context) {
Avatar: user.Avatar,
Background: user.Background,
CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
Email: user.Email,
Experience: strconv.Itoa(int(user.Experience)),
Inviter: strconv.Itoa(int(user.Inviter)),
Email: &user.Email,
Experience: &user.Experience,
Inviter: &user.Inviter,
LastActive: user.LastActive.Format("2006-01-02 15:04:05"),
Private: user.Private,
Private: false,
Roles: roles,
Signature: user.Signature,
UserID: user.UserID,
Username: user.Username,
})
}

log.Logger.Info("Get user profile success: " + strconv.Itoa(int(req.UserID)) +
", by user ID: " + strconv.Itoa(int(userID)))
}
73 changes: 73 additions & 0 deletions internal/service/user/profile_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package user

import (
"strconv"

"github.com/TensoRaws/NuxBT-Backend/internal/common/dao"
"github.com/TensoRaws/NuxBT-Backend/module/log"
"github.com/TensoRaws/NuxBT-Backend/module/util"
"github.com/gin-gonic/gin"
)

type ProfileUpdateRequest struct {
Avatar *string `json:"avatar" binding:"omitempty"`
Background *string `json:"background" binding:"omitempty"`
Email *string `json:"email" binding:"omitempty,email"`
Private *bool `json:"private" binding:"omitempty"`
Signature *string `json:"signature" binding:"omitempty"`
Username *string `json:"username" binding:"omitempty"`
}

// ProfileUpdate 用户信息更新 (POST /profile/update)
func ProfileUpdate(c *gin.Context) {
// 参数绑定
var req ProfileUpdateRequest
if err := c.ShouldBindJSON(&req); err != nil {
util.AbortWithMsg(c, "invalid request: "+err.Error())
return
}

userID, _ := util.GetUserIDFromGinContext(c)

// 准备更新数据
updates := make(map[string]interface{})

if req.Private != nil {
updates["private"] = req.Private
}

if req.Username != nil && *req.Username != "" {
err := util.CheckUsername(*req.Username)
if err != nil {
util.AbortWithMsg(c, "invalid username: "+err.Error())
return
}
updates["username"] = *req.Username
}

if req.Email != nil {
updates["email"] = *req.Email
}

if req.Avatar != nil {
updates["avatar"] = *req.Avatar
}

if req.Signature != nil {
updates["signature"] = *req.Signature
}

if req.Background != nil {
updates["background"] = *req.Background
}
// 执行更新
err := dao.UpdateUserDataByUserID(userID, updates)
if err != nil {
util.AbortWithMsg(c, "update failed: "+err.Error())
return
}

util.OKWithMsg(c, "update success")

log.Logger.Info("update user profile success: " + strconv.Itoa(int(userID)))
}
16 changes: 10 additions & 6 deletions internal/service/user/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ type RegisterDataResponse struct {
func Register(c *gin.Context) {
var req RegisterRequest
if err := c.ShouldBindJSON(&req); err != nil {
util.AbortWithMsg(c, "invalid request")
util.AbortWithMsg(c, "invalid request: "+err.Error())
return
}

err := util.CheckUsername(req.Username)
if err != nil {
util.AbortWithMsg(c, "invalid username: "+err.Error())
return
}

Expand All @@ -42,10 +48,8 @@ func Register(c *gin.Context) {
return
}
} else {
// 有邀请码注册,检查邀请码是否有效
// do something
// 未实现
// OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
// TODO: 邀请码功能, 有邀请码注册,检查邀请码是否有效

log.Logger.Info("invitation code: " + *req.InvitationCode)
}
password, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
Expand All @@ -62,7 +66,7 @@ func Register(c *gin.Context) {
LastActive: time.Now(),
})
if err != nil {
util.AbortWithMsg(c, "failed to register: ")
util.AbortWithMsg(c, "failed to register: "+err.Error())
log.Logger.Error("failed to register: " + err.Error())
return
}
Expand Down
9 changes: 2 additions & 7 deletions internal/service/user/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,11 @@ func ResetPassword(c *gin.Context) {
// 绑定参数
var req ResetPasswordRequest
if err := c.ShouldBindJSON(&req); err != nil {
util.AbortWithMsg(c, "invalid request")
util.AbortWithMsg(c, "invalid request: "+err.Error())
return
}

// 鉴权
userID, err := util.GetUserIDFromGinContext(c)
if err != nil {
util.AbortWithMsg(c, "Please login first")
return
}
userID, _ := util.GetUserIDFromGinContext(c)

user, err := dao.GetUserByID(userID)
if err != nil {
Expand Down
25 changes: 25 additions & 0 deletions module/util/username.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package util

import "fmt"

func CheckUsername(username string) error {
l := len([]rune(username))
if l > 20 {
return fmt.Errorf("username too long")
}
if l < 2 {
return fmt.Errorf("username too short")
}
if username == "" {
return fmt.Errorf("username cannot be empty")
}
adminWords := []string{"admin", "root", "administrator", "管理员", "超级管理员", "版主", "站长", "moderator"}
for _, word := range adminWords {
if username == word {
return fmt.Errorf("username cannot be %s", word)
}
}
// TODO: more checks,如检查敏感词

return nil
}

0 comments on commit 0191f13

Please sign in to comment.