in internal/controller/answer_controller.go [193:293]
func (ac *AnswerController) Add(ctx *gin.Context) {
req := &schema.AnswerAddReq{}
if handler.BindAndCheck(ctx, req) {
return
}
reject, rejectKey := ac.rateLimitMiddleware.DuplicateRequestRejection(ctx, req)
if reject {
return
}
defer func() {
// If status is not 200 means that the bad request has been returned, so the record should be cleared
if ctx.Writer.Status() != http.StatusOK {
ac.rateLimitMiddleware.DuplicateRequestClear(ctx, rejectKey)
}
}()
req.QuestionID = uid.DeShortID(req.QuestionID)
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
permission.AnswerEdit,
permission.AnswerDelete,
permission.LinkUrlLimit,
})
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
linkUrlLimitUser := canList[2]
isAdmin := middleware.GetUserIsAdminModerator(ctx)
if !isAdmin || !linkUrlLimitUser {
captchaPass := ac.actionService.ActionRecordVerifyCaptcha(ctx, entity.CaptchaActionAnswer, 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 := ac.rankService.CheckOperationPermission(ctx, req.UserID, permission.AnswerAdd, "")
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if !can {
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
return
}
write, err := ac.siteInfoCommonService.GetSiteWrite(ctx)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if write.RestrictAnswer {
// check if there's already an answer by this user
ids, err := ac.answerService.GetCountByUserIDQuestionID(ctx, req.UserID, req.QuestionID)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if len(ids) >= 1 {
handler.HandleResponse(ctx, errors.Forbidden(reason.AnswerRestrictAnswer), nil)
return
}
}
req.UserAgent = ctx.GetHeader("User-Agent")
req.IP = ctx.ClientIP()
answerID, err := ac.answerService.Insert(ctx, req)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if !isAdmin || !linkUrlLimitUser {
ac.actionService.ActionRecordAdd(ctx, entity.CaptchaActionAnswer, req.UserID)
}
info, questionInfo, has, err := ac.answerService.Get(ctx, answerID, req.UserID)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if !has {
handler.HandleResponse(ctx, nil, nil)
return
}
objectOwner := ac.rankService.CheckOperationObjectOwner(ctx, req.UserID, info.ID)
req.CanEdit = canList[0] || objectOwner
req.CanDelete = canList[1] || objectOwner
info.MemberActions = permission.GetAnswerPermission(ctx, req.UserID, info.UserID,
0, req.CanEdit, req.CanDelete, false)
handler.HandleResponse(ctx, nil, gin.H{
"info": info,
"question": questionInfo,
})
}