feat(user):基本完成用户重设密码,待测。

This commit is contained in:
徐涛 2022-08-12 13:20:23 +08:00
parent 8dd9654d82
commit cd18170ee6
5 changed files with 174 additions and 23 deletions

31
cache/repository.go vendored Normal file
View File

@ -0,0 +1,31 @@
package cache
import "time"
func CacheData[T interface{}](instance T, category string, key ...string) error {
var keys = make([]string, 0)
keys = append(keys, category)
keys = append(keys, key...)
cacheKey := CacheKey("cache", keys...)
if exists, _ := Exists(cacheKey); exists {
Delete(cacheKey)
}
return Cache(cacheKey, &instance, 5*time.Minute)
}
func RetreiveData[T interface{}](category string, key ...string) (*T, error) {
var keys = make([]string, 0)
keys = append(keys, category)
keys = append(keys, key...)
return Retreive[T](CacheKey("cache", keys...))
}
func AbolishCacheData(category string, key ...string) {
var keys = make([]string, 0)
keys = append(keys, category)
keys = append(keys, key...)
cacheKey := CacheKey("cache", keys...)
if exists, _ := Exists(cacheKey); exists {
Delete(cacheKey)
}
}

View File

@ -25,6 +25,8 @@ func InitializeUserController(router *gin.Engine) {
} }
UserController.Router.POST("/login", UserController.Login) UserController.Router.POST("/login", UserController.Login)
UserController.Router.DELETE("/logout", security.MustAuthenticated, UserController.Logout) UserController.Router.DELETE("/logout", security.MustAuthenticated, UserController.Logout)
UserController.Router.DELETE("/password/:uid", security.OPSAuthorize, UserController.InvalidUserPassword)
UserController.Router.PUT("/password", UserController.ResetUserPassword)
} }
type LoginFormData struct { type LoginFormData struct {
@ -77,3 +79,53 @@ func (_UserController) Logout(c *gin.Context) {
} }
result.Success("用户已成功登出系统。") result.Success("用户已成功登出系统。")
} }
func (_UserController) InvalidUserPassword(c *gin.Context) {
result := response.NewResult(c)
targetUserId := c.Param("uid")
verifyCode, err := service.UserService.InvalidUserPassword(targetUserId)
if errors.Is(err, &exceptions.NotFoundError{}) {
result.NotFound("未找到指定用户。")
return
}
if errors.Is(err, &exceptions.UnsuccessfulOperationError{}) {
result.Error(500, "未能成功更新用户的密码。")
return
}
if err != nil {
result.Error(500, err.Error())
return
}
result.QuickJson(http.StatusOK, http.StatusAccepted, "用户密码已经失效", gin.H{"verify": verifyCode})
}
type ResetPasswordFormData struct {
VerifyCode string `json:"verifyCode"`
Username string `json:"uname"`
NewPassword string `json:"newPass"`
}
func (_UserController) ResetUserPassword(c *gin.Context) {
result := response.NewResult(c)
resetForm := new(ResetPasswordFormData)
c.BindJSON(resetForm)
verified, err := service.UserService.VerifyUserPassword(resetForm.Username, resetForm.VerifyCode)
if !verified {
result.Error(http.StatusUnauthorized, "验证码不正确。")
return
}
if err != nil {
result.Error(http.StatusInternalServerError, err.Error())
return
}
completed, err := service.UserService.ResetUserPassword(resetForm.Username, resetForm.NewPassword)
if err != nil {
result.Error(http.StatusInternalServerError, err.Error())
return
}
if completed {
result.Success("用户凭据已更新。")
return
}
result.Error(http.StatusNotAcceptable, "用户凭据未能成功更新。")
}

View File

@ -1,10 +1,5 @@
package repository package repository
import (
"electricity_bill_calc/cache"
"time"
)
func _postProcessSingle[T interface{}](instance *T, has bool, err error) (*T, error) { func _postProcessSingle[T interface{}](instance *T, has bool, err error) (*T, error) {
if err != nil { if err != nil {
return nil, err return nil, err
@ -26,21 +21,3 @@ func _postProcessList[T interface{}](instance []*T, has bool, err error) ([]*T,
return nil, nil return nil, nil
} }
} }
func cacheData[T interface{}](instance T, category string, key ...string) error {
var keys = make([]string, 0)
keys = append(keys, category)
keys = append(keys, key...)
cacheKey := cache.CacheKey("cache", keys...)
if exists, _ := cache.Exists(cacheKey); exists {
cache.Delete(cacheKey)
}
return cache.Cache(cacheKey, &instance, 5*time.Minute)
}
func retreiveData[T interface{}](category string, key ...string) (*T, error) {
var keys = make([]string, 0)
keys = append(keys, category)
keys = append(keys, key...)
return cache.Retreive[T](cache.CacheKey("cache", keys...))
}

View File

@ -1,6 +1,7 @@
package repository package repository
import ( import (
"electricity_bill_calc/cache"
"electricity_bill_calc/global" "electricity_bill_calc/global"
"electricity_bill_calc/model" "electricity_bill_calc/model"
) )
@ -10,13 +11,40 @@ type _UserRepository struct{}
var UserRepo _UserRepository var UserRepo _UserRepository
func (_UserRepository) FindUserByUsername(username string) (*model.User, error) { func (_UserRepository) FindUserByUsername(username string) (*model.User, error) {
cachedUser, _ := cache.RetreiveData[model.User]("user", username)
if cachedUser != nil {
return cachedUser, nil
}
user := new(model.User) user := new(model.User)
has, err := global.DBConn.Where("username=?", username).Get(user) has, err := global.DBConn.Where("username=?", username).Get(user)
if has {
cache.CacheData(user, "user", username)
}
return _postProcessSingle(user, has, err) return _postProcessSingle(user, has, err)
} }
func (_UserRepository) RetreiveUserDetail(uid string) (*model.UserDetail, error) { func (_UserRepository) RetreiveUserDetail(uid string) (*model.UserDetail, error) {
cachedUser, _ := cache.RetreiveData[model.UserDetail]("user", uid)
if cachedUser != nil {
return cachedUser, nil
}
user := new(model.UserDetail) user := new(model.UserDetail)
has, err := global.DBConn.Where("id=?", uid).Get(user) has, err := global.DBConn.Where("id=?", uid).Get(user)
if has {
cache.CacheData(user, "user_detail", uid)
}
return _postProcessSingle(user, has, err)
}
func (_UserRepository) FindUserByID(uid string) (*model.User, error) {
cachedUser, _ := cache.RetreiveData[model.User]("user", uid)
if cachedUser != nil {
return cachedUser, nil
}
user := new(model.User)
has, err := global.DBConn.ID(uid).Get(user)
if has {
cache.CacheData(user, "user", uid)
}
return _postProcessSingle(user, has, err) return _postProcessSingle(user, has, err)
} }

View File

@ -5,8 +5,10 @@ import (
"electricity_bill_calc/cache" "electricity_bill_calc/cache"
"electricity_bill_calc/config" "electricity_bill_calc/config"
"electricity_bill_calc/exceptions" "electricity_bill_calc/exceptions"
"electricity_bill_calc/global"
"electricity_bill_calc/model" "electricity_bill_calc/model"
"electricity_bill_calc/repository" "electricity_bill_calc/repository"
"electricity_bill_calc/utils"
"fmt" "fmt"
"time" "time"
@ -92,3 +94,64 @@ func (_UserService) ProcessManagementUserLogin(username, password string) (*mode
cache.CacheSession(session) cache.CacheSession(session)
return session, nil return session, nil
} }
func (_UserService) InvalidUserPassword(uid string) (string, error) {
user, err := repository.UserRepo.FindUserByID(uid)
if user == nil && err != nil {
return "", exceptions.NewNotFoundError("指定的用户不存在。")
}
verifyCode := utils.RandStr(10)
hash := sha512.New512_256()
hash.Write([]byte(verifyCode))
user.Password = string(hash.Sum(nil))
user.ResetNeeded = true
affected, err := global.DBConn.ID(uid).Cols("password", "reset_needed").Update(user)
if err != nil {
return "", err
}
if affected > 0 {
// ! 同一个用户在缓存中有两个键。
cache.AbolishCacheData("user", user.Id)
cache.AbolishCacheData("user", user.Username)
return verifyCode, nil
} else {
return "", exceptions.NewUnsuccessfulOperationError()
}
}
func (_UserService) VerifyUserPassword(username, verifyCode string) (bool, error) {
user, err := repository.UserRepo.FindUserByUsername(username)
if user == nil || err != nil {
return false, exceptions.NewNotFoundError("指定的用户不存在。")
}
hash := sha512.New512_256()
hash.Write([]byte(verifyCode))
hashedVerifyCode := string(hash.Sum(nil))
if hashedVerifyCode != user.Password {
return false, nil
} else {
return true, nil
}
}
func (_UserService) ResetUserPassword(username, password string) (bool, error) {
user, err := repository.UserRepo.FindUserByUsername(username)
if user == nil || err != nil {
return false, exceptions.NewNotFoundError("指定的用户不存在。")
}
hash := sha512.New512_256()
hash.Write([]byte(password))
user.Password = string(hash.Sum(nil))
user.ResetNeeded = false
affected, err := global.DBConn.ID(user.Id).Cols("password", "reset_needed").Update(user)
if err != nil {
return false, err
}
if affected > 0 {
cache.AbolishCacheData("user", user.Id)
cache.AbolishCacheData("user", user.Username)
return true, nil
} else {
return false, nil
}
}