🎨 完善部分用户相关接口
This commit is contained in:
parent
00df85c4f0
commit
44f1b5d4b5
@ -83,3 +83,50 @@ func (*APPUserApi) Login(ctx *gin.Context) {
|
|||||||
r.FailWithMessage("设置登录状态失败", ctx)
|
r.FailWithMessage("设置登录状态失败", ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WechatLogin 微信登录
|
||||||
|
func (*APPUserApi) WechatLogin(ctx *gin.Context) {
|
||||||
|
var p request.CodeLoginReq
|
||||||
|
if err := ctx.ShouldBind(&p); err != nil {
|
||||||
|
r.FailWithMessage(err.Error(), ctx)
|
||||||
|
global.GVA_LOG.Error("参数错误,登录失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//Todo 待完善微信登录
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserList 获取用户列表
|
||||||
|
func (*APPUserApi) GetUserList(ctx *gin.Context) {
|
||||||
|
var p request.GetUserListReq
|
||||||
|
if err := ctx.ShouldBind(&p); err != nil {
|
||||||
|
r.FailWithMessage(err.Error(), ctx)
|
||||||
|
global.GVA_LOG.Error("参数错误,获取用户列表失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userList, total, err := userService.GetUserList(p)
|
||||||
|
if err != nil {
|
||||||
|
r.FailWithMessage("获取用户列表失败", ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.OkWithDetailed(r.PageResult{
|
||||||
|
List: userList,
|
||||||
|
Total: total,
|
||||||
|
Page: p.Page,
|
||||||
|
PageSize: p.PageSize,
|
||||||
|
}, "获取用户列表成功", ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBalance 设置用户余额
|
||||||
|
func (*APPUserApi) SetBalance(ctx *gin.Context) {
|
||||||
|
var p request.SetBalanceReq
|
||||||
|
if err := ctx.ShouldBind(&p); err != nil {
|
||||||
|
r.FailWithMessage(err.Error(), ctx)
|
||||||
|
global.GVA_LOG.Error("参数错误,设置用户余额失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := userService.SetBalance(p); err != nil {
|
||||||
|
r.FailWithMessage("设置用户余额失败", ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.OkWithMessage("设置用户余额成功", ctx)
|
||||||
|
}
|
||||||
|
11
config.yaml
11
config.yaml
@ -241,16 +241,17 @@ zap:
|
|||||||
retention-day: -1
|
retention-day: -1
|
||||||
|
|
||||||
wechat:
|
wechat:
|
||||||
app-id:
|
app-id: wx3d21df18d7f8f9fc
|
||||||
app-secret:
|
app-secret: ffce59a9a9272c1aaee53950e96617d8
|
||||||
token:
|
token: kjeldcsdz2phfwfxnevsajnzsboho1ev
|
||||||
aes-key:
|
aes-key: PiqqlGdEblw5Gv1RJ5qcTnhKUjFw9YNkBMAX6CIw6Me
|
||||||
|
callback: https://api.gin-vue-admin.com/wechat/callback
|
||||||
pay-list:
|
pay-list:
|
||||||
- type: wxpay
|
- type: wxpay
|
||||||
alias-name: wxpay-1
|
alias-name: wxpay-1
|
||||||
app-id: 1
|
app-id: 1
|
||||||
mch-id: 1
|
mch-id: 1
|
||||||
v3-key: 1
|
v3-key: 1a3sd8561d5179Df152D4789aD38wG9s
|
||||||
cert-path: 1
|
cert-path: 1
|
||||||
key-path: 1
|
key-path: 1
|
||||||
notify-url: 1
|
notify-url: 1
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"git.echol.cn/loser/lckt/model/article"
|
"git.echol.cn/loser/lckt/model/article"
|
||||||
"git.echol.cn/loser/lckt/model/bot"
|
"git.echol.cn/loser/lckt/model/bot"
|
||||||
"git.echol.cn/loser/lckt/model/category"
|
"git.echol.cn/loser/lckt/model/category"
|
||||||
|
"git.echol.cn/loser/lckt/model/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
func bizModel() error {
|
func bizModel() error {
|
||||||
@ -13,6 +14,7 @@ func bizModel() error {
|
|||||||
category.Category{},
|
category.Category{},
|
||||||
bot.Bot{},
|
bot.Bot{},
|
||||||
article.Article{},
|
article.Article{},
|
||||||
|
user.User{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -25,4 +25,8 @@ func initBizRouter(routers ...*gin.RouterGroup) {
|
|||||||
articleRouter := router.RouterGroupApp.Article
|
articleRouter := router.RouterGroupApp.Article
|
||||||
articleRouter.InitBotRouter(privateGroup, publicGroup)
|
articleRouter.InitBotRouter(privateGroup, publicGroup)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
userRouter := router.RouterGroupApp.User
|
||||||
|
userRouter.InitUserRouter(privateGroup, publicGroup)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
64
middleware/user_jwt.go
Normal file
64
middleware/user_jwt.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"git.echol.cn/loser/lckt/global"
|
||||||
|
"git.echol.cn/loser/lckt/utils"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.echol.cn/loser/lckt/model/common/response"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UserJWTAuth() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
|
||||||
|
token := utils.GetToken(c)
|
||||||
|
if token == "" {
|
||||||
|
response.NoAuth("未登录或非法访问", c)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
j := utils.NewJWT()
|
||||||
|
// parseToken 解析token包含的信息
|
||||||
|
claims, err := j.ParseToken(token)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, utils.TokenExpired) {
|
||||||
|
response.NoAuth("授权已过期", c)
|
||||||
|
utils.ClearToken(c)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.NoAuth(err.Error(), c)
|
||||||
|
utils.ClearToken(c)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set("claims", claims)
|
||||||
|
if claims.ExpiresAt.Unix()-time.Now().Unix() < claims.BufferTime {
|
||||||
|
dr, _ := utils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)
|
||||||
|
claims.ExpiresAt = jwt.NewNumericDate(time.Now().Add(dr))
|
||||||
|
newToken, _ := j.CreateTokenByOldToken(token, *claims)
|
||||||
|
newClaims, _ := j.ParseToken(newToken)
|
||||||
|
c.Header("new-token", newToken)
|
||||||
|
c.Header("new-expires-at", strconv.FormatInt(newClaims.ExpiresAt.Unix(), 10))
|
||||||
|
utils.SetToken(c, newToken, int(dr.Seconds()))
|
||||||
|
if global.GVA_CONFIG.System.UseMultipoint {
|
||||||
|
// 记录新的活跃jwt
|
||||||
|
_ = jwtService.SetRedisJWT(newToken, newClaims.Username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Next()
|
||||||
|
|
||||||
|
if newToken, exists := c.Get("new-token"); exists {
|
||||||
|
c.Header("new-token", newToken.(string))
|
||||||
|
}
|
||||||
|
if newExpiresAt, exists := c.Get("new-expires-at"); exists {
|
||||||
|
c.Header("new-expires-at", newExpiresAt.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package request
|
package request
|
||||||
|
|
||||||
|
import "git.echol.cn/loser/lckt/model/common/request"
|
||||||
|
|
||||||
type SendCodeReq struct {
|
type SendCodeReq struct {
|
||||||
Phone string `json:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
Phone string `json:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||||
}
|
}
|
||||||
@ -32,11 +34,18 @@ type BindWechatReq struct {
|
|||||||
UnionId string `json:"unionId" gorm:"type:varchar(64);comment:用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的 unionid 是唯一的。"`
|
UnionId string `json:"unionId" gorm:"type:varchar(64);comment:用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的 unionid 是唯一的。"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BindQQReq struct {
|
|
||||||
QQ string `json:"qq" vd:"@:len($)>0; msg:'QQ号不能为空'"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BindPhoneReq struct {
|
type BindPhoneReq struct {
|
||||||
Id int `json:"id" vd:"@:len($)>0; msg:'用户ID不能为空'"`
|
Id int `json:"id" vd:"@:len($)>0; msg:'用户ID不能为空'"`
|
||||||
Phone string `json:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
Phone string `json:"phone" vd:"@:len($)>0; msg:'手机号码不能为空'"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetUserListReq struct {
|
||||||
|
request.PageInfo
|
||||||
|
Type int `json:"type"`
|
||||||
|
UserLabel string `json:"user_label" `
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetBalanceReq struct {
|
||||||
|
Id int `json:"id" vd:"@:len($)>0; msg:'用户ID不能为空'"`
|
||||||
|
Balance float32 `json:"balance" vd:"@:len($)>0; msg:'余额不能为空'"`
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"git.echol.cn/loser/lckt/router/category"
|
"git.echol.cn/loser/lckt/router/category"
|
||||||
"git.echol.cn/loser/lckt/router/example"
|
"git.echol.cn/loser/lckt/router/example"
|
||||||
"git.echol.cn/loser/lckt/router/system"
|
"git.echol.cn/loser/lckt/router/system"
|
||||||
|
"git.echol.cn/loser/lckt/router/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
var RouterGroupApp = new(RouterGroup)
|
var RouterGroupApp = new(RouterGroup)
|
||||||
@ -16,4 +17,5 @@ type RouterGroup struct {
|
|||||||
Category category.RouterGroup
|
Category category.RouterGroup
|
||||||
Bot bot.RouterGroup
|
Bot bot.RouterGroup
|
||||||
Article article.RouterGroup
|
Article article.RouterGroup
|
||||||
|
User user.UserRouter
|
||||||
}
|
}
|
||||||
|
9
router/user/enter.go
Normal file
9
router/user/enter.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
api "git.echol.cn/loser/lckt/api/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RouterGroup struct{ UserRouter }
|
||||||
|
|
||||||
|
var userApi = api.ApiGroupApp.UserApiGroup
|
23
router/user/user.go
Normal file
23
router/user/user.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.echol.cn/loser/lckt/middleware"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserRouter struct{}
|
||||||
|
|
||||||
|
// InitUserRouter 初始化 用户相关 路由信息
|
||||||
|
func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
||||||
|
userRouter := Router.Group("app_user").Use(middleware.OperationRecord())
|
||||||
|
userRouterWithoutAuth := PublicRouter.Group("app_user")
|
||||||
|
{
|
||||||
|
userRouter.GET("list", userApi.GetUserList) // 获取用户列表
|
||||||
|
userRouter.PUT("setBalance", userApi.SetBalance) // 更新用户余额
|
||||||
|
}
|
||||||
|
{
|
||||||
|
userRouterWithoutAuth.DELETE("login", userApi.Login) // 短信验证码登录
|
||||||
|
userRouterWithoutAuth.POST("sms", userApi.SendCode) // 发送短信验证码
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -78,3 +78,38 @@ func (u *UserService) Login(req request.CodeLoginReq) (users user.User, err erro
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserService) GetUserList(p request.GetUserListReq) (userList user.User, total int64, err error) {
|
||||||
|
limit := p.PageSize
|
||||||
|
offset := p.PageSize * (p.Page - 1)
|
||||||
|
// 创建db
|
||||||
|
db := global.GVA_DB.Model(&user.User{})
|
||||||
|
// 如果有条件搜索 下方会自动创建搜索语句
|
||||||
|
if p.Type != 0 {
|
||||||
|
db = db.Where("user_type = ?", p.Type)
|
||||||
|
}
|
||||||
|
if p.UserLabel != "" {
|
||||||
|
db = db.Where("user_label = ?", p.UserLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = db.Count(&total).Error
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if limit != 0 {
|
||||||
|
db = db.Limit(limit).Offset(offset)
|
||||||
|
}
|
||||||
|
err = db.Find(&userList).Error
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserService) SetBalance(p request.SetBalanceReq) (err error) {
|
||||||
|
err = global.GVA_DB.Model(&user.User{}).Where("id = ?", p.Id).Update("balance", p.Balance).Error
|
||||||
|
if err != nil {
|
||||||
|
global.GVA_LOG.Error("设置用户余额失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -19,9 +19,9 @@ func ClearToken(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if net.ParseIP(host) != nil {
|
if net.ParseIP(host) != nil {
|
||||||
c.SetCookie("x-token", "", -1, "/", "", false, false)
|
c.SetCookie("app-token", "", -1, "/", "", false, false)
|
||||||
} else {
|
} else {
|
||||||
c.SetCookie("x-token", "", -1, "/", host, false, false)
|
c.SetCookie("app-token", "", -1, "/", host, false, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,17 +33,17 @@ func SetToken(c *gin.Context, token string, maxAge int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if net.ParseIP(host) != nil {
|
if net.ParseIP(host) != nil {
|
||||||
c.SetCookie("x-token", token, maxAge, "/", "", false, false)
|
c.SetCookie("app-token", token, maxAge, "/", "", false, false)
|
||||||
} else {
|
} else {
|
||||||
c.SetCookie("x-token", token, maxAge, "/", host, false, false)
|
c.SetCookie("app-token", token, maxAge, "/", host, false, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetToken(c *gin.Context) string {
|
func GetToken(c *gin.Context) string {
|
||||||
token := c.Request.Header.Get("x-token")
|
token := c.Request.Header.Get("app-token")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
j := NewJWT()
|
j := NewJWT()
|
||||||
token, _ = c.Cookie("x-token")
|
token, _ = c.Cookie("app-token")
|
||||||
claims, err := j.ParseToken(token)
|
claims, err := j.ParseToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.GVA_LOG.Error("重新写入cookie token失败,未能成功解析token,请检查请求头是否存在x-token且claims是否为规定结构")
|
global.GVA_LOG.Error("重新写入cookie token失败,未能成功解析token,请检查请求头是否存在x-token且claims是否为规定结构")
|
||||||
|
Loading…
Reference in New Issue
Block a user