✨ add comment verification
This commit is contained in:
@@ -239,12 +239,12 @@ func (CaptchaAPI) GenerateClickShapeCaptcha(c *gin.Context) {
|
||||
result.OkWithData(bt, c)
|
||||
}
|
||||
|
||||
// GenerateSlideBasicCaptData 生成点击形状基础验证码
|
||||
// @Summary 生成点击形状基础验证码
|
||||
// @Description 生成点击形状基础验证码
|
||||
// @Tags 点击形状验证码
|
||||
// GenerateSlideBasicCaptData 滑块基础验证码
|
||||
// @Summary 滑块基础验证码
|
||||
// @Description 滑块基础验证码
|
||||
// @Tags 滑块基础验证码
|
||||
// @Success 200 {string} json
|
||||
// @Router /api/captcha/shape/check [get]
|
||||
// @Router /api/captcha/slide/generate [get]
|
||||
func (CaptchaAPI) GenerateSlideBasicCaptData(c *gin.Context) {
|
||||
captData, err := global.SlideCaptcha.Generate()
|
||||
if err != nil {
|
||||
@@ -266,70 +266,27 @@ func (CaptchaAPI) GenerateSlideBasicCaptData(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
key := helper.StringToMD5(string(dotsByte))
|
||||
err = redis.Set(key, dotsByte, time.Minute).Err()
|
||||
err = redis.Set(constant.CommentSubmitCaptchaRedisKey+key, dotsByte, time.Minute).Err()
|
||||
if err != nil {
|
||||
result.FailWithNull(c)
|
||||
return
|
||||
}
|
||||
bt := map[string]interface{}{
|
||||
"key": key,
|
||||
"image": masterImageBase64,
|
||||
"tile": tileImageBase64,
|
||||
"tile_width": blockData.Width,
|
||||
"tile_height": blockData.Height,
|
||||
"tile_x": blockData.TileX,
|
||||
"tile_y": blockData.TileY,
|
||||
"key": key,
|
||||
"image": masterImageBase64,
|
||||
"thumb": tileImageBase64,
|
||||
"thumb_width": blockData.Width,
|
||||
"thumb_height": blockData.Height,
|
||||
"thumb_x": blockData.TileX,
|
||||
"thumb_y": blockData.TileY,
|
||||
}
|
||||
result.OkWithData(bt, c)
|
||||
}
|
||||
|
||||
// CheckSlideData 验证点击形状验证码
|
||||
// @Summary 验证点击形状验证码
|
||||
// @Description 验证点击形状验证码
|
||||
// @Tags 点击形状验证码
|
||||
// @Param point query string true "点击坐标"
|
||||
// @Param key query string true "验证码key"
|
||||
// @Success 200 {string} json
|
||||
// @Router /api/captcha/shape/slide/check [get]
|
||||
func (CaptchaAPI) CheckSlideData(c *gin.Context) {
|
||||
point := c.Query("point")
|
||||
key := c.Query("key")
|
||||
if point == "" || key == "" {
|
||||
result.FailWithNull(c)
|
||||
return
|
||||
}
|
||||
|
||||
cacheDataByte, err := redis.Get(key).Bytes()
|
||||
if len(cacheDataByte) == 0 || err != nil {
|
||||
result.FailWithNull(c)
|
||||
return
|
||||
}
|
||||
src := strings.Split(point, ",")
|
||||
|
||||
var dct *slide.Block
|
||||
if err := json.Unmarshal(cacheDataByte, &dct); err != nil {
|
||||
result.FailWithNull(c)
|
||||
return
|
||||
}
|
||||
|
||||
chkRet := false
|
||||
if 2 == len(src) {
|
||||
sx, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[0]), 64)
|
||||
sy, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[1]), 64)
|
||||
chkRet = slide.CheckPoint(int64(sx), int64(sy), int64(dct.X), int64(dct.Y), 4)
|
||||
}
|
||||
|
||||
if chkRet {
|
||||
result.OkWithMessage("success", c)
|
||||
return
|
||||
}
|
||||
result.FailWithMessage("fail", c)
|
||||
}
|
||||
|
||||
// GenerateSlideRegionCaptData 生成点击形状验证码
|
||||
// @Summary 生成点击形状验证码
|
||||
// @Description 生成点击形状验证码
|
||||
// @Tags 点击形状验证码
|
||||
// GenerateSlideRegionCaptData 生成滑动区域形状验证码
|
||||
// @Summary 生成滑动区域形状验证码
|
||||
// @Description 生成滑动区域形状验证码
|
||||
// @Tags 生成滑动区域形状验证码
|
||||
// @Success 200 {string} json
|
||||
// @Router /api/captcha/shape/slide/region/get [get]
|
||||
func (CaptchaAPI) GenerateSlideRegionCaptData(c *gin.Context) {
|
||||
@@ -371,3 +328,46 @@ func (CaptchaAPI) GenerateSlideRegionCaptData(c *gin.Context) {
|
||||
}
|
||||
result.OkWithData(bt, c)
|
||||
}
|
||||
|
||||
// CheckSlideData 验证滑动验证码
|
||||
// @Summary 验证滑动验证码
|
||||
// @Description 验证滑动验证码
|
||||
// @Tags 验证滑动验证码
|
||||
// @Param point query string true "点击坐标"
|
||||
// @Param key query string true "验证码key"
|
||||
// @Success 200 {string} json
|
||||
// @Router /api/captcha/shape/slide/check [get]
|
||||
func (CaptchaAPI) CheckSlideData(c *gin.Context) {
|
||||
point := c.Query("point")
|
||||
key := c.Query("key")
|
||||
if point == "" || key == "" {
|
||||
result.FailWithNull(c)
|
||||
return
|
||||
}
|
||||
|
||||
cacheDataByte, err := redis.Get(key).Bytes()
|
||||
if len(cacheDataByte) == 0 || err != nil {
|
||||
result.FailWithNull(c)
|
||||
return
|
||||
}
|
||||
src := strings.Split(point, ",")
|
||||
|
||||
var dct *slide.Block
|
||||
if err := json.Unmarshal(cacheDataByte, &dct); err != nil {
|
||||
result.FailWithNull(c)
|
||||
return
|
||||
}
|
||||
|
||||
chkRet := false
|
||||
if 2 == len(src) {
|
||||
sx, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[0]), 64)
|
||||
sy, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[1]), 64)
|
||||
chkRet = slide.CheckPoint(int64(sx), int64(sy), int64(dct.X), int64(dct.Y), 4)
|
||||
}
|
||||
|
||||
if chkRet {
|
||||
result.OkWithMessage("success", c)
|
||||
return
|
||||
}
|
||||
result.FailWithMessage("fail", c)
|
||||
}
|
||||
|
@@ -30,9 +30,15 @@ import (
|
||||
func (CommentAPI) CommentSubmit(c *gin.Context) {
|
||||
commentRequest := dto.CommentRequest{}
|
||||
if err := c.ShouldBindJSON(&commentRequest); err != nil {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
||||
return
|
||||
}
|
||||
// 验证校验
|
||||
res := utils.CheckSlideData(commentRequest.Point, commentRequest.Key)
|
||||
if !res {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaVerifyError"), c)
|
||||
return
|
||||
}
|
||||
|
||||
if len(commentRequest.Images) > 3 {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c)
|
||||
return
|
||||
@@ -148,7 +154,12 @@ func (CommentAPI) ReplySubmit(c *gin.Context) {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证校验
|
||||
res := utils.CheckSlideData(replyCommentRequest.Point, replyCommentRequest.Key)
|
||||
if !res {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaVerifyError"), c)
|
||||
return
|
||||
}
|
||||
if len(replyCommentRequest.Images) > 3 {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c)
|
||||
return
|
||||
@@ -270,7 +281,12 @@ func (CommentAPI) ReplyReplySubmit(c *gin.Context) {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证校验
|
||||
res := utils.CheckSlideData(replyReplyRequest.Point, replyReplyRequest.Key)
|
||||
if !res {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaVerifyError"), c)
|
||||
return
|
||||
}
|
||||
if len(replyReplyRequest.Images) > 3 {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c)
|
||||
return
|
||||
@@ -394,7 +410,12 @@ func (CommentAPI) CommentList(c *gin.Context) {
|
||||
// 查询评论列表
|
||||
query, u := gplus.NewQuery[model.ScaCommentReply]()
|
||||
page := gplus.NewPage[model.ScaCommentReply](commentListRequest.Page, commentListRequest.Size)
|
||||
query.Eq(&u.TopicId, commentListRequest.TopicId).Eq(&u.CommentType, enum.COMMENT).OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.ReplyCount).OrderByDesc(&u.CreatedTime)
|
||||
if commentListRequest.IsHot {
|
||||
query.OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.ReplyCount)
|
||||
} else {
|
||||
query.OrderByDesc(&u.CommentOrder).OrderByDesc(&u.CreatedTime)
|
||||
}
|
||||
query.Eq(&u.TopicId, commentListRequest.TopicId).Eq(&u.CommentType, enum.COMMENT)
|
||||
page, pageDB := gplus.SelectPage(page, query)
|
||||
if pageDB.Error != nil {
|
||||
global.LOG.Errorln(pageDB.Error)
|
||||
@@ -455,7 +476,7 @@ func (CommentAPI) CommentList(c *gin.Context) {
|
||||
// 查询评论图片信息
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // 设置超时,2秒
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) // 设置超时,2秒
|
||||
defer cancel()
|
||||
|
||||
cursor, err := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").Find(ctx, bson.M{"comment_id": bson.M{"$in": commentIds}})
|
||||
@@ -563,7 +584,7 @@ func (CommentAPI) ReplyList(c *gin.Context) {
|
||||
}
|
||||
query, u := gplus.NewQuery[model.ScaCommentReply]()
|
||||
page := gplus.NewPage[model.ScaCommentReply](replyListRequest.Page, replyListRequest.Size)
|
||||
query.Eq(&u.TopicId, replyListRequest.TopicId).Eq(&u.ReplyId, replyListRequest.CommentId).Eq(&u.CommentType, enum.REPLY).OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.CreatedTime)
|
||||
query.Eq(&u.TopicId, replyListRequest.TopicId).Eq(&u.ReplyId, replyListRequest.CommentId).Eq(&u.CommentType, enum.REPLY).OrderByDesc(&u.Likes).OrderByAsc(&u.CreatedTime)
|
||||
page, pageDB := gplus.SelectPage(page, query)
|
||||
if pageDB.Error != nil {
|
||||
global.LOG.Errorln(pageDB.Error)
|
||||
|
@@ -6,6 +6,8 @@ type CommentRequest struct {
|
||||
UserID string `json:"user_id" binding:"required"`
|
||||
TopicId string `json:"topic_id" binding:"required"`
|
||||
Author string `json:"author" binding:"required"`
|
||||
Key string `json:"key" binding:"required"`
|
||||
Point []int64 `json:"point" binding:"required"`
|
||||
}
|
||||
type ReplyCommentRequest struct {
|
||||
Content string `json:"content" binding:"required"`
|
||||
@@ -15,6 +17,8 @@ type ReplyCommentRequest struct {
|
||||
ReplyId int64 `json:"reply_id" binding:"required"`
|
||||
ReplyUser string `json:"reply_user" binding:"required"`
|
||||
Author string `json:"author" binding:"required"`
|
||||
Key string `json:"key" binding:"required"`
|
||||
Point []int64 `json:"point" binding:"required"`
|
||||
}
|
||||
|
||||
type ReplyReplyRequest struct {
|
||||
@@ -26,6 +30,8 @@ type ReplyReplyRequest struct {
|
||||
ReplyId int64 `json:"reply_id" binding:"required"`
|
||||
ReplyUser string `json:"reply_user" binding:"required"`
|
||||
Author string `json:"author" binding:"required"`
|
||||
Key string `json:"key" binding:"required"`
|
||||
Point []int64 `json:"point" binding:"required"`
|
||||
}
|
||||
|
||||
type CommentListRequest struct {
|
||||
@@ -33,6 +39,7 @@ type CommentListRequest struct {
|
||||
TopicId string `json:"topic_id" binding:"required"`
|
||||
Page int `json:"page" default:"1"`
|
||||
Size int `json:"size" default:"5"`
|
||||
IsHot bool `json:"is_hot" default:"true"`
|
||||
}
|
||||
type ReplyListRequest struct {
|
||||
UserID string `json:"user_id" binding:"required"`
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
"schisandra-cloud-album/api/user_api/dto"
|
||||
"schisandra-cloud-album/common/constant"
|
||||
"schisandra-cloud-album/common/redis"
|
||||
"schisandra-cloud-album/common/result"
|
||||
"schisandra-cloud-album/global"
|
||||
"schisandra-cloud-album/model"
|
||||
"schisandra-cloud-album/service"
|
||||
@@ -39,10 +40,11 @@ var script = `
|
||||
`
|
||||
|
||||
func HandleLoginResponse(c *gin.Context, uid string) {
|
||||
res, data := HandelUserLogin(uid)
|
||||
res, data := HandelUserLogin(uid, c)
|
||||
if !res {
|
||||
return
|
||||
}
|
||||
|
||||
tokenData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
global.LOG.Error(err)
|
||||
@@ -55,7 +57,7 @@ func HandleLoginResponse(c *gin.Context, uid string) {
|
||||
}
|
||||
|
||||
// HandelUserLogin 处理用户登录
|
||||
func HandelUserLogin(userId string) (bool, map[string]interface{}) {
|
||||
func HandelUserLogin(userId string, c *gin.Context) (bool, result.Response) {
|
||||
// 使用goroutine生成accessToken
|
||||
accessTokenChan := make(chan string)
|
||||
errChan := make(chan error)
|
||||
@@ -86,7 +88,7 @@ func HandelUserLogin(userId string) (bool, map[string]interface{}) {
|
||||
case accessToken = <-accessTokenChan:
|
||||
case err = <-errChan:
|
||||
global.LOG.Error(err)
|
||||
return false, nil
|
||||
return false, result.Response{}
|
||||
}
|
||||
select {
|
||||
case refreshToken = <-refreshTokenChan:
|
||||
@@ -99,7 +101,10 @@ func HandelUserLogin(userId string) (bool, map[string]interface{}) {
|
||||
ExpiresAt: expiresAt,
|
||||
UID: &userId,
|
||||
}
|
||||
|
||||
wrong := utils.SetSession(c, "user", data)
|
||||
if wrong != nil {
|
||||
return false, result.Response{}
|
||||
}
|
||||
// 使用goroutine将数据存入redis
|
||||
redisErrChan := make(chan error)
|
||||
go func() {
|
||||
@@ -115,13 +120,13 @@ func HandelUserLogin(userId string) (bool, map[string]interface{}) {
|
||||
redisErr := <-redisErrChan
|
||||
if redisErr != nil {
|
||||
global.LOG.Error(redisErr)
|
||||
return false, nil
|
||||
return false, result.Response{}
|
||||
}
|
||||
responseData := map[string]interface{}{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": data,
|
||||
"success": true,
|
||||
responseData := result.Response{
|
||||
Data: data,
|
||||
Message: "success",
|
||||
Code: 200,
|
||||
Success: true,
|
||||
}
|
||||
return true, responseData
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package oauth_api
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/ArtisanCloud/PowerLibs/v3/http/helper"
|
||||
@@ -47,7 +48,7 @@ func (OAuthAPI) CallbackNotify(c *gin.Context) {
|
||||
return "error"
|
||||
}
|
||||
key := strings.TrimPrefix(msg.EventKey, "qrscene_")
|
||||
res := wechatLoginHandler(msg.FromUserName, key)
|
||||
res := wechatLoginHandler(msg.FromUserName, key, c)
|
||||
if !res {
|
||||
return messages.NewText(ginI18n.MustGetMessage(c, "LoginFailed"))
|
||||
}
|
||||
@@ -69,7 +70,7 @@ func (OAuthAPI) CallbackNotify(c *gin.Context) {
|
||||
println(err.Error())
|
||||
return "error"
|
||||
}
|
||||
res := wechatLoginHandler(msg.FromUserName, msg.EventKey)
|
||||
res := wechatLoginHandler(msg.FromUserName, msg.EventKey, c)
|
||||
if !res {
|
||||
return messages.NewText(ginI18n.MustGetMessage(c, "LoginFailed"))
|
||||
}
|
||||
@@ -165,7 +166,7 @@ func (OAuthAPI) GetTempQrCode(c *gin.Context) {
|
||||
}
|
||||
|
||||
// wechatLoginHandler 微信登录处理
|
||||
func wechatLoginHandler(openId string, clientId string) bool {
|
||||
func wechatLoginHandler(openId string, clientId string, c *gin.Context) bool {
|
||||
if openId == "" {
|
||||
return false
|
||||
}
|
||||
@@ -257,7 +258,7 @@ func wechatLoginHandler(openId string, clientId string) bool {
|
||||
// 异步处理用户登录
|
||||
resChan := make(chan bool, 1)
|
||||
go func() {
|
||||
res := handelUserLogin(*addUser.UID, clientId)
|
||||
res := handelUserLogin(*addUser.UID, clientId, c)
|
||||
resChan <- res
|
||||
}()
|
||||
|
||||
@@ -271,7 +272,7 @@ func wechatLoginHandler(openId string, clientId string) bool {
|
||||
tx.Commit()
|
||||
return true
|
||||
} else {
|
||||
res := handelUserLogin(*authUserSocial.UserID, clientId)
|
||||
res := handelUserLogin(*authUserSocial.UserID, clientId, c)
|
||||
if !res {
|
||||
return false
|
||||
}
|
||||
@@ -280,7 +281,7 @@ func wechatLoginHandler(openId string, clientId string) bool {
|
||||
}
|
||||
|
||||
// handelUserLogin 处理用户登录
|
||||
func handelUserLogin(userId string, clientId string) bool {
|
||||
func handelUserLogin(userId string, clientId string, c *gin.Context) bool {
|
||||
resultChan := make(chan bool, 1)
|
||||
|
||||
go func() {
|
||||
@@ -312,6 +313,12 @@ func handelUserLogin(userId string, clientId string) bool {
|
||||
resultChan <- false
|
||||
return
|
||||
}
|
||||
gob.Register(dto.ResponseData{})
|
||||
wrong := utils.SetSession(c, "user", data)
|
||||
if wrong != nil {
|
||||
resultChan <- false
|
||||
return
|
||||
}
|
||||
// gws方式发送消息
|
||||
err = websocket_api.Handler.SendMessageToClient(clientId, tokenData)
|
||||
if err != nil {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package user_api
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
ginI18n "github.com/gin-contrib/i18n"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -332,6 +333,7 @@ func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c)
|
||||
return
|
||||
}
|
||||
gob.Register(dto.ResponseData{})
|
||||
err = utils.SetSession(c, "user", data)
|
||||
if err != nil {
|
||||
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c)
|
||||
|
Reference in New Issue
Block a user