From 456be4f4a8cb9205e3cdd22af13a02827cfac581 Mon Sep 17 00:00:00 2001 From: aichy Date: Wed, 19 Jul 2023 17:46:14 +0800 Subject: [PATCH] update captcha --- cmd/wire_gen.go | 4 +- internal/controller/answer_controller.go | 12 ++++++ internal/controller/comment_controller.go | 11 ++++++ internal/controller/question_controller.go | 23 +++++++++++ internal/controller/report_controller.go | 29 +++++++++++++- internal/controller/vote_controller.go | 45 +++++++++++++++++++--- internal/schema/answer_schema.go | 4 +- internal/schema/comment_schema.go | 4 +- internal/schema/question_schema.go | 10 +++-- internal/schema/report_schema.go | 4 +- internal/schema/vote_schema.go | 8 ++-- 11 files changed, 135 insertions(+), 19 deletions(-) diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index a3b7182c..63364974 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -152,10 +152,10 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, commentController := controller.NewCommentController(commentService, rankService, captchaService) reportRepo := report.NewReportRepo(dataData, uniqueIDRepo) reportService := report2.NewReportService(reportRepo, objService) - reportController := controller.NewReportController(reportService, rankService) + reportController := controller.NewReportController(reportService, rankService, captchaService) serviceVoteRepo := activity.NewVoteRepo(dataData, activityRepo, userRankRepo, notificationQueueService) 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) tagService := tag2.NewTagService(tagRepo, tagCommonService, revisionService, followRepo, siteInfoCommonService, activityQueueService) tagController := controller.NewTagController(tagService, tagCommonService, rankService) diff --git a/internal/controller/answer_controller.go b/internal/controller/answer_controller.go index affa9b18..6ec63afd 100644 --- a/internal/controller/answer_controller.go +++ b/internal/controller/answer_controller.go @@ -56,6 +56,17 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) { } req.ID = uid.DeShortID(req.ID) 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) canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{ permission.AnswerDelete, @@ -71,6 +82,7 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) { } err = ac.answerService.RemoveAnswer(ctx, req) + ac.actionService.ActionRecordAdd(ctx, entity.CaptchaActionDelete, req.UserID) handler.HandleResponse(ctx, err, nil) } diff --git a/internal/controller/comment_controller.go b/internal/controller/comment_controller.go index d0a97e95..9495ebf7 100644 --- a/internal/controller/comment_controller.go +++ b/internal/controller/comment_controller.go @@ -104,6 +104,15 @@ func (cc *CommentController) RemoveComment(ctx *gin.Context) { } 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) if err != nil { handler.HandleResponse(ctx, err, nil) @@ -115,6 +124,8 @@ func (cc *CommentController) RemoveComment(ctx *gin.Context) { } err = cc.commentService.RemoveComment(ctx, req) + cc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionDelete, req.UserID) + handler.HandleResponse(ctx, err, nil) } diff --git a/internal/controller/question_controller.go b/internal/controller/question_controller.go index 0cf4471d..8b69ec9a 100644 --- a/internal/controller/question_controller.go +++ b/internal/controller/question_controller.go @@ -64,6 +64,17 @@ func (qc *QuestionController) RemoveQuestion(ctx *gin.Context) { req.ID = uid.DeShortID(req.ID) req.UserID = middleware.GetLoginUserIDFromContext(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) if err != nil { handler.HandleResponse(ctx, err, nil) @@ -75,6 +86,7 @@ func (qc *QuestionController) RemoveQuestion(ctx *gin.Context) { } err = qc.questionService.RemoveQuestion(ctx, req) + qc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionDelete, req.UserID) handler.HandleResponse(ctx, err, nil) } @@ -600,6 +612,16 @@ func (qc *QuestionController) UpdateQuestionInviteUser(ctx *gin.Context) { req.ID = uid.DeShortID(req.ID) 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{ permission.AnswerInviteSomeoneToAnswer, }) @@ -623,6 +645,7 @@ func (qc *QuestionController) UpdateQuestionInviteUser(ctx *gin.Context) { handler.HandleResponse(ctx, err, nil) return } + qc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionInvitationAnswer, req.UserID) handler.HandleResponse(ctx, nil, nil) } diff --git a/internal/controller/report_controller.go b/internal/controller/report_controller.go index a8196c13..7f76f166 100644 --- a/internal/controller/report_controller.go +++ b/internal/controller/report_controller.go @@ -4,7 +4,11 @@ import ( "github.com/answerdev/answer/internal/base/handler" "github.com/answerdev/answer/internal/base/middleware" "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/service/action" "github.com/answerdev/answer/internal/service/permission" "github.com/answerdev/answer/internal/service/rank" "github.com/answerdev/answer/internal/service/report" @@ -17,11 +21,20 @@ import ( type ReportController struct { reportService *report.ReportService rankService *rank.RankService + actionService *action.CaptchaService } // NewReportController new controller -func NewReportController(reportService *report.ReportService, rankService *rank.RankService) *ReportController { - return &ReportController{reportService: reportService, rankService: rankService} +func NewReportController( + reportService *report.ReportService, + rankService *rank.RankService, + actionService *action.CaptchaService, +) *ReportController { + return &ReportController{ + reportService: reportService, + rankService: rankService, + actionService: actionService, + } } // AddReport add report @@ -42,6 +55,17 @@ func (rc *ReportController) AddReport(ctx *gin.Context) { } req.ObjectID = uid.DeShortID(req.ObjectID) 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, "") if err != nil { handler.HandleResponse(ctx, err, nil) @@ -53,5 +77,6 @@ func (rc *ReportController) AddReport(ctx *gin.Context) { } err = rc.reportService.AddReport(ctx, req) + rc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionReport, req.UserID) handler.HandleResponse(ctx, err, nil) } diff --git a/internal/controller/vote_controller.go b/internal/controller/vote_controller.go index 3548e053..b0b59d41 100644 --- a/internal/controller/vote_controller.go +++ b/internal/controller/vote_controller.go @@ -5,8 +5,11 @@ import ( "github.com/answerdev/answer/internal/base/middleware" "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/service" + "github.com/answerdev/answer/internal/service/action" "github.com/answerdev/answer/internal/service/rank" "github.com/answerdev/answer/pkg/uid" "github.com/gin-gonic/gin" @@ -15,13 +18,22 @@ import ( // VoteController activity controller type VoteController struct { - VoteService *service.VoteService - rankService *rank.RankService + VoteService *service.VoteService + rankService *rank.RankService + actionService *action.CaptchaService } // NewVoteController new controller -func NewVoteController(voteService *service.VoteService, rankService *rank.RankService) *VoteController { - return &VoteController{VoteService: voteService, rankService: rankService} +func NewVoteController( + voteService *service.VoteService, + rankService *rank.RankService, + actionService *action.CaptchaService, +) *VoteController { + return &VoteController{ + VoteService: voteService, + rankService: rankService, + actionService: actionService, + } } // VoteUp godoc @@ -41,6 +53,17 @@ func (vc *VoteController) VoteUp(ctx *gin.Context) { } req.ObjectID = uid.DeShortID(req.ObjectID) 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) if 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) return } - + vc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionVote, req.UserID) resp, err := vc.VoteService.VoteUp(ctx, req) if err != nil { handler.HandleResponse(ctx, err, schema.ErrTypeToast) @@ -78,6 +101,16 @@ func (vc *VoteController) VoteDown(ctx *gin.Context) { } req.ObjectID = uid.DeShortID(req.ObjectID) 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) if 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) return } - + vc.actionService.ActionRecordAdd(ctx, entity.CaptchaActionVote, req.UserID) resp, err := vc.VoteService.VoteDown(ctx, req) if err != nil { handler.HandleResponse(ctx, err, schema.ErrTypeToast) diff --git a/internal/schema/answer_schema.go b/internal/schema/answer_schema.go index 0a0905c8..81465d65 100644 --- a/internal/schema/answer_schema.go +++ b/internal/schema/answer_schema.go @@ -12,7 +12,9 @@ type RemoveAnswerReq struct { // user id UserID string `json:"-"` // whether user can delete it - CanDelete bool `json:"-"` + CanDelete bool `json:"-"` + CaptchaID string `json:"captcha_id"` // captcha_id + CaptchaCode string `json:"captcha_code"` } const ( diff --git a/internal/schema/comment_schema.go b/internal/schema/comment_schema.go index e1d85004..caba2cea 100644 --- a/internal/schema/comment_schema.go +++ b/internal/schema/comment_schema.go @@ -41,7 +41,9 @@ type RemoveCommentReq struct { // comment id CommentID string `validate:"required" json:"comment_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 diff --git a/internal/schema/question_schema.go b/internal/schema/question_schema.go index bee5ec90..e023699d 100644 --- a/internal/schema/question_schema.go +++ b/internal/schema/question_schema.go @@ -20,9 +20,11 @@ const ( // RemoveQuestionReq delete question request type RemoveQuestionReq struct { // question id - ID string `validate:"required" json:"id"` - UserID string `json:"-" ` // user_id - IsAdmin bool `json:"-"` + ID string `validate:"required" json:"id"` + UserID string `json:"-" ` // user_id + IsAdmin bool `json:"-"` + CaptchaID string `json:"captcha_id"` // captcha_id + CaptchaCode string `json:"captcha_code"` } type CloseQuestionReq struct { @@ -164,6 +166,8 @@ type QuestionUpdateInviteUser struct { InviteUser []string `validate:"omitempty" json:"invite_user"` UserID string `json:"-"` QuestionPermission + CaptchaID string `json:"captcha_id"` // captcha_id + CaptchaCode string `json:"captcha_code"` } func (req *QuestionUpdate) Check() (errFields []*validator.FormErrorField, err error) { diff --git a/internal/schema/report_schema.go b/internal/schema/report_schema.go index b4534f82..579aba75 100644 --- a/internal/schema/report_schema.go +++ b/internal/schema/report_schema.go @@ -15,7 +15,9 @@ type AddReportReq struct { // report content Content string `validate:"omitempty,gt=0,lte=500" json:"content"` // 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 diff --git a/internal/schema/vote_schema.go b/internal/schema/vote_schema.go index e41f542f..b9d17acd 100644 --- a/internal/schema/vote_schema.go +++ b/internal/schema/vote_schema.go @@ -1,9 +1,11 @@ package schema type VoteReq struct { - ObjectID string `validate:"required" form:"object_id" json:"object_id"` // id - IsCancel bool `validate:"omitempty" form:"is_cancel" json:"is_cancel"` // is cancel - UserID string `json:"-"` + ObjectID string `validate:"required" form:"object_id" json:"object_id"` // id + IsCancel bool `validate:"omitempty" form:"is_cancel" json:"is_cancel"` // is cancel + UserID string `json:"-"` + CaptchaID string `json:"captcha_id"` // captcha_id + CaptchaCode string `json:"captcha_code"` } type VoteResp struct {