update captcha

This commit is contained in:
aichy 2023-07-19 17:46:14 +08:00
parent da8910951f
commit 456be4f4a8
11 changed files with 135 additions and 19 deletions

View File

@ -152,10 +152,10 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
commentController := controller.NewCommentController(commentService, rankService, captchaService) commentController := controller.NewCommentController(commentService, rankService, captchaService)
reportRepo := report.NewReportRepo(dataData, uniqueIDRepo) reportRepo := report.NewReportRepo(dataData, uniqueIDRepo)
reportService := report2.NewReportService(reportRepo, objService) reportService := report2.NewReportService(reportRepo, objService)
reportController := controller.NewReportController(reportService, rankService) reportController := controller.NewReportController(reportService, rankService, captchaService)
serviceVoteRepo := activity.NewVoteRepo(dataData, activityRepo, userRankRepo, notificationQueueService) serviceVoteRepo := activity.NewVoteRepo(dataData, activityRepo, userRankRepo, notificationQueueService)
voteService := service.NewVoteService(serviceVoteRepo, configService, questionRepo, answerRepo, commentCommonRepo, objService) voteService := service.NewVoteService(serviceVoteRepo, configService, questionRepo, answerRepo, commentCommonRepo, objService)
voteController := controller.NewVoteController(voteService, rankService) voteController := controller.NewVoteController(voteService, rankService, captchaService)
followRepo := activity_common.NewFollowRepo(dataData, uniqueIDRepo, activityRepo) followRepo := activity_common.NewFollowRepo(dataData, uniqueIDRepo, activityRepo)
tagService := tag2.NewTagService(tagRepo, tagCommonService, revisionService, followRepo, siteInfoCommonService, activityQueueService) tagService := tag2.NewTagService(tagRepo, tagCommonService, revisionService, followRepo, siteInfoCommonService, activityQueueService)
tagController := controller.NewTagController(tagService, tagCommonService, rankService) tagController := controller.NewTagController(tagService, tagCommonService, rankService)

View File

@ -56,6 +56,17 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) {
} }
req.ID = uid.DeShortID(req.ID) req.ID = uid.DeShortID(req.ID)
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
captchaPass := ac.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionDelete, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
ErrorField: "captcha_code",
ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed),
})
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields)
return
}
objectOwner := ac.rankService.CheckOperationObjectOwner(ctx, req.UserID, req.ID) objectOwner := ac.rankService.CheckOperationObjectOwner(ctx, req.UserID, req.ID)
canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
permission.AnswerDelete, permission.AnswerDelete,
@ -71,6 +82,7 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) {
} }
err = ac.answerService.RemoveAnswer(ctx, req) err = ac.answerService.RemoveAnswer(ctx, req)
ac.actionService.ActionRecordAdd(ctx, entity.CaptchaActionDelete, req.UserID)
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
} }

View File

@ -104,6 +104,15 @@ func (cc *CommentController) RemoveComment(ctx *gin.Context) {
} }
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
captchaPass := cc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionDelete, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
ErrorField: "captcha_code",
ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed),
})
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields)
return
}
can, err := cc.rankService.CheckOperationPermission(ctx, req.UserID, permission.CommentDelete, req.CommentID) can, err := cc.rankService.CheckOperationPermission(ctx, req.UserID, permission.CommentDelete, req.CommentID)
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
@ -115,6 +124,8 @@ func (cc *CommentController) RemoveComment(ctx *gin.Context) {
} }
err = cc.commentService.RemoveComment(ctx, req) err = cc.commentService.RemoveComment(ctx, req)
cc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionDelete, req.UserID)
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
} }

View File

@ -64,6 +64,17 @@ func (qc *QuestionController) RemoveQuestion(ctx *gin.Context) {
req.ID = uid.DeShortID(req.ID) req.ID = uid.DeShortID(req.ID)
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
req.IsAdmin = middleware.GetIsAdminFromContext(ctx) req.IsAdmin = middleware.GetIsAdminFromContext(ctx)
captchaPass := qc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionDelete, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
ErrorField: "captcha_code",
ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed),
})
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields)
return
}
can, err := qc.rankService.CheckOperationPermission(ctx, req.UserID, permission.QuestionDelete, req.ID) can, err := qc.rankService.CheckOperationPermission(ctx, req.UserID, permission.QuestionDelete, req.ID)
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
@ -75,6 +86,7 @@ func (qc *QuestionController) RemoveQuestion(ctx *gin.Context) {
} }
err = qc.questionService.RemoveQuestion(ctx, req) err = qc.questionService.RemoveQuestion(ctx, req)
qc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionDelete, req.UserID)
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
} }
@ -600,6 +612,16 @@ func (qc *QuestionController) UpdateQuestionInviteUser(ctx *gin.Context) {
req.ID = uid.DeShortID(req.ID) req.ID = uid.DeShortID(req.ID)
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
captchaPass := qc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionInvitationAnswer, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
ErrorField: "captcha_code",
ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed),
})
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields)
return
}
canList, err := qc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ canList, err := qc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
permission.AnswerInviteSomeoneToAnswer, permission.AnswerInviteSomeoneToAnswer,
}) })
@ -623,6 +645,7 @@ func (qc *QuestionController) UpdateQuestionInviteUser(ctx *gin.Context) {
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
return return
} }
qc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionInvitationAnswer, req.UserID)
handler.HandleResponse(ctx, nil, nil) handler.HandleResponse(ctx, nil, nil)
} }

View File

@ -4,7 +4,11 @@ import (
"github.com/answerdev/answer/internal/base/handler" "github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/base/middleware" "github.com/answerdev/answer/internal/base/middleware"
"github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/base/translator"
"github.com/answerdev/answer/internal/base/validator"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/internal/service/action"
"github.com/answerdev/answer/internal/service/permission" "github.com/answerdev/answer/internal/service/permission"
"github.com/answerdev/answer/internal/service/rank" "github.com/answerdev/answer/internal/service/rank"
"github.com/answerdev/answer/internal/service/report" "github.com/answerdev/answer/internal/service/report"
@ -17,11 +21,20 @@ import (
type ReportController struct { type ReportController struct {
reportService *report.ReportService reportService *report.ReportService
rankService *rank.RankService rankService *rank.RankService
actionService *action.CaptchaService
} }
// NewReportController new controller // NewReportController new controller
func NewReportController(reportService *report.ReportService, rankService *rank.RankService) *ReportController { func NewReportController(
return &ReportController{reportService: reportService, rankService: rankService} reportService *report.ReportService,
rankService *rank.RankService,
actionService *action.CaptchaService,
) *ReportController {
return &ReportController{
reportService: reportService,
rankService: rankService,
actionService: actionService,
}
} }
// AddReport add report // AddReport add report
@ -42,6 +55,17 @@ func (rc *ReportController) AddReport(ctx *gin.Context) {
} }
req.ObjectID = uid.DeShortID(req.ObjectID) req.ObjectID = uid.DeShortID(req.ObjectID)
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
captchaPass := rc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionReport, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
ErrorField: "captcha_code",
ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed),
})
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields)
return
}
can, err := rc.rankService.CheckOperationPermission(ctx, req.UserID, permission.ReportAdd, "") can, err := rc.rankService.CheckOperationPermission(ctx, req.UserID, permission.ReportAdd, "")
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
@ -53,5 +77,6 @@ func (rc *ReportController) AddReport(ctx *gin.Context) {
} }
err = rc.reportService.AddReport(ctx, req) err = rc.reportService.AddReport(ctx, req)
rc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionReport, req.UserID)
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
} }

View File

@ -5,8 +5,11 @@ import (
"github.com/answerdev/answer/internal/base/middleware" "github.com/answerdev/answer/internal/base/middleware"
"github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/base/translator" "github.com/answerdev/answer/internal/base/translator"
"github.com/answerdev/answer/internal/base/validator"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/internal/service" "github.com/answerdev/answer/internal/service"
"github.com/answerdev/answer/internal/service/action"
"github.com/answerdev/answer/internal/service/rank" "github.com/answerdev/answer/internal/service/rank"
"github.com/answerdev/answer/pkg/uid" "github.com/answerdev/answer/pkg/uid"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -17,11 +20,20 @@ import (
type VoteController struct { type VoteController struct {
VoteService *service.VoteService VoteService *service.VoteService
rankService *rank.RankService rankService *rank.RankService
actionService *action.CaptchaService
} }
// NewVoteController new controller // NewVoteController new controller
func NewVoteController(voteService *service.VoteService, rankService *rank.RankService) *VoteController { func NewVoteController(
return &VoteController{VoteService: voteService, rankService: rankService} voteService *service.VoteService,
rankService *rank.RankService,
actionService *action.CaptchaService,
) *VoteController {
return &VoteController{
VoteService: voteService,
rankService: rankService,
actionService: actionService,
}
} }
// VoteUp godoc // VoteUp godoc
@ -41,6 +53,17 @@ func (vc *VoteController) VoteUp(ctx *gin.Context) {
} }
req.ObjectID = uid.DeShortID(req.ObjectID) req.ObjectID = uid.DeShortID(req.ObjectID)
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
captchaPass := vc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionVote, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
ErrorField: "captcha_code",
ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed),
})
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields)
return
}
can, needRank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, true) can, needRank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, true)
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
@ -52,7 +75,7 @@ func (vc *VoteController) VoteUp(ctx *gin.Context) {
handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil)
return return
} }
vc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionVote, req.UserID)
resp, err := vc.VoteService.VoteUp(ctx, req) resp, err := vc.VoteService.VoteUp(ctx, req)
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, schema.ErrTypeToast) handler.HandleResponse(ctx, err, schema.ErrTypeToast)
@ -78,6 +101,16 @@ func (vc *VoteController) VoteDown(ctx *gin.Context) {
} }
req.ObjectID = uid.DeShortID(req.ObjectID) req.ObjectID = uid.DeShortID(req.ObjectID)
req.UserID = middleware.GetLoginUserIDFromContext(ctx) req.UserID = middleware.GetLoginUserIDFromContext(ctx)
captchaPass := vc.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionVote, req.UserID, req.CaptchaID, req.CaptchaCode)
if !captchaPass {
errFields := append([]*validator.FormErrorField{}, &validator.FormErrorField{
ErrorField: "captcha_code",
ErrorMsg: translator.Tr(handler.GetLang(ctx), reason.CaptchaVerificationFailed),
})
handler.HandleResponse(ctx, errors.BadRequest(reason.CaptchaVerificationFailed), errFields)
return
}
can, needRank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, false) can, needRank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, false)
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, nil) handler.HandleResponse(ctx, err, nil)
@ -89,7 +122,7 @@ func (vc *VoteController) VoteDown(ctx *gin.Context) {
handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil) handler.HandleResponse(ctx, errors.Forbidden(reason.NoEnoughRankToOperate).WithMsg(msg), nil)
return return
} }
vc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionVote, req.UserID)
resp, err := vc.VoteService.VoteDown(ctx, req) resp, err := vc.VoteService.VoteDown(ctx, req)
if err != nil { if err != nil {
handler.HandleResponse(ctx, err, schema.ErrTypeToast) handler.HandleResponse(ctx, err, schema.ErrTypeToast)

View File

@ -13,6 +13,8 @@ type RemoveAnswerReq struct {
UserID string `json:"-"` UserID string `json:"-"`
// whether user can delete it // whether user can delete it
CanDelete bool `json:"-"` CanDelete bool `json:"-"`
CaptchaID string `json:"captcha_id"` // captcha_id
CaptchaCode string `json:"captcha_code"`
} }
const ( const (

View File

@ -42,6 +42,8 @@ type RemoveCommentReq struct {
CommentID string `validate:"required" json:"comment_id"` CommentID string `validate:"required" json:"comment_id"`
// user id // user id
UserID string `json:"-"` UserID string `json:"-"`
CaptchaID string `json:"captcha_id"` // captcha_id
CaptchaCode string `json:"captcha_code"`
} }
// UpdateCommentReq update comment request // UpdateCommentReq update comment request

View File

@ -23,6 +23,8 @@ type RemoveQuestionReq struct {
ID string `validate:"required" json:"id"` ID string `validate:"required" json:"id"`
UserID string `json:"-" ` // user_id UserID string `json:"-" ` // user_id
IsAdmin bool `json:"-"` IsAdmin bool `json:"-"`
CaptchaID string `json:"captcha_id"` // captcha_id
CaptchaCode string `json:"captcha_code"`
} }
type CloseQuestionReq struct { type CloseQuestionReq struct {
@ -164,6 +166,8 @@ type QuestionUpdateInviteUser struct {
InviteUser []string `validate:"omitempty" json:"invite_user"` InviteUser []string `validate:"omitempty" json:"invite_user"`
UserID string `json:"-"` UserID string `json:"-"`
QuestionPermission QuestionPermission
CaptchaID string `json:"captcha_id"` // captcha_id
CaptchaCode string `json:"captcha_code"`
} }
func (req *QuestionUpdate) Check() (errFields []*validator.FormErrorField, err error) { func (req *QuestionUpdate) Check() (errFields []*validator.FormErrorField, err error) {

View File

@ -16,6 +16,8 @@ type AddReportReq struct {
Content string `validate:"omitempty,gt=0,lte=500" json:"content"` Content string `validate:"omitempty,gt=0,lte=500" json:"content"`
// user id // user id
UserID string `json:"-"` UserID string `json:"-"`
CaptchaID string `json:"captcha_id"` // captcha_id
CaptchaCode string `json:"captcha_code"`
} }
// GetReportListReq get report list all request // GetReportListReq get report list all request

View File

@ -4,6 +4,8 @@ type VoteReq struct {
ObjectID string `validate:"required" form:"object_id" json:"object_id"` // id ObjectID string `validate:"required" form:"object_id" json:"object_id"` // id
IsCancel bool `validate:"omitempty" form:"is_cancel" json:"is_cancel"` // is cancel IsCancel bool `validate:"omitempty" form:"is_cancel" json:"is_cancel"` // is cancel
UserID string `json:"-"` UserID string `json:"-"`
CaptchaID string `json:"captcha_id"` // captcha_id
CaptchaCode string `json:"captcha_code"`
} }
type VoteResp struct { type VoteResp struct {