fix(rank): Incorrect version reputation check rule

This commit is contained in:
LinkinStar 2022-11-30 19:11:28 +08:00
parent c5eecd33c3
commit 457c1cd798
11 changed files with 126 additions and 114 deletions

View File

@ -1,4 +1,5 @@
# The following fields are used for back-end
backend:
base:
success:
@ -97,7 +98,7 @@ backend:
other: "Theme not found."
revision:
review_underway:
other: "Revision review underway."
other: "Can't edit currently, there is a version in the review queue."
no_permission:
other: "No permission to Revision."
user:

View File

@ -270,39 +270,6 @@ func (qc *QuestionController) UpdateQuestion(ctx *gin.Context) {
handler.HandleResponse(ctx, err, resp)
}
// CheckCanUpdateQuestion check can update question
// @Summary check can update question
// @Description check can update question
// @Tags Revision
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id query string true "id" default(string)
// @Success 200 {object} handler.RespBody
// @Router /answer/api/v1/revisions/edit/check [get]
func (qc *QuestionController) CheckCanUpdateQuestion(ctx *gin.Context) {
req := &schema.CheckCanQuestionUpdate{}
if handler.BindAndCheck(ctx, req) {
return
}
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
req.IsAdmin = middleware.GetIsAdminFromContext(ctx)
can, err := qc.rankService.CheckOperationPermission(ctx, req.UserID, rank.QuestionEditRank, req.ID)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if !can {
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
return
}
resp, err := qc.questionService.CheckCanUpdate(ctx, req)
handler.HandleResponse(ctx, err, gin.H{
"unreviewed": resp,
})
}
// CloseMsgList close question msg list
// @Summary close question msg list
// @Description close question msg list

View File

@ -1,12 +1,14 @@
package controller
import (
"github.com/answerdev/answer/internal/base/constant"
"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/schema"
"github.com/answerdev/answer/internal/service"
"github.com/answerdev/answer/internal/service/rank"
"github.com/answerdev/answer/pkg/obj"
"github.com/gin-gonic/gin"
"github.com/segmentfault/pacman/errors"
)
@ -58,7 +60,7 @@ func (rc *RevisionController) GetRevisionList(ctx *gin.Context) {
// @Produce json
// @Security ApiKeyAuth
// @Param page query string true "page id"
// @Success 200 {object} handler.RespBody{data=[]schema.GetRevisionResp}
// @Success 200 {object} handler.RespBody{data=pager.PageModel{list=[]schema.GetUnreviewedRevisionResp}}
// @Router /answer/api/v1/revisions/unreviewed [get]
func (rc *RevisionController) GetUnreviewedRevisionList(ctx *gin.Context) {
req := &schema.RevisionSearch{}
@ -80,11 +82,8 @@ func (rc *RevisionController) GetUnreviewedRevisionList(ctx *gin.Context) {
req.CanReviewAnswer = canList[1]
req.CanReviewTag = canList[2]
resp, count, err := rc.revisionListService.GetUnreviewedRevisionList(ctx, req)
handler.HandleResponse(ctx, err, gin.H{
"list": resp,
"count": count,
})
resp, err := rc.revisionListService.GetUnreviewedRevisionPage(ctx, req)
handler.HandleResponse(ctx, err, resp)
}
// RevisionAudit godoc
@ -118,3 +117,48 @@ func (rc *RevisionController) RevisionAudit(ctx *gin.Context) {
err = rc.revisionListService.RevisionAudit(ctx, req)
handler.HandleResponse(ctx, err, gin.H{})
}
// CheckCanUpdateRevision check can update revision
// @Summary check can update revision
// @Description check can update revision
// @Tags Revision
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param id query string true "id" default(string)
// @Success 200 {object} handler.RespBody
// @Router /answer/api/v1/revisions/edit/check [get]
func (rc *RevisionController) CheckCanUpdateRevision(ctx *gin.Context) {
req := &schema.CheckCanQuestionUpdate{}
if handler.BindAndCheck(ctx, req) {
return
}
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
action := ""
objectTypeStr, _ := obj.GetObjectTypeStrByObjectID(req.ID)
switch objectTypeStr {
case constant.QuestionObjectType:
action = rank.QuestionEditRank
case constant.AnswerObjectType:
action = rank.AnswerEditRank
case constant.TagObjectType:
action = rank.TagEditRank
default:
handler.HandleResponse(ctx, errors.BadRequest(reason.ObjectNotFound), nil)
return
}
can, err := rc.rankService.CheckOperationPermission(ctx, req.UserID, action, req.ID)
if err != nil {
handler.HandleResponse(ctx, err, nil)
return
}
if !can {
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
return
}
err = rc.revisionListService.CheckCanUpdateRevision(ctx, req)
handler.HandleResponse(ctx, err, nil)
}

View File

@ -1,6 +1,8 @@
package entity
import "time"
import (
"time"
)
const (
// RevisionUnreviewedStatus this revision is unreviewed
@ -17,7 +19,7 @@ type Revision struct {
CreatedAt time.Time `xorm:"created TIMESTAMP created_at"`
UpdatedAt time.Time `xorm:"updated TIMESTAMP updated_at"`
UserID string `xorm:"not null default 0 BIGINT(20) user_id"`
ObjectType int `xorm:"not null default 0 ) INT(11) object_type"`
ObjectType int `xorm:"not null default 0 INT(11) object_type"`
ObjectID string `xorm:"not null default 0 BIGINT(20) INDEX object_id"`
Title string `xorm:"not null default '' VARCHAR(255) title"`
Content string `xorm:"not null TEXT content"`
@ -26,13 +28,6 @@ type Revision struct {
ReviewUserID int64 `xorm:"not null default 0 BIGINT(20) review_user_id"`
}
type RevisionSearch struct {
Page int `json:"page" form:"page"` // Query number of pages
CanReviewQuestion bool `json:"-"`
CanReviewAnswer bool `json:"-"`
CanReviewTag bool `json:"-"`
}
// TableName revision table name
func (Revision) TableName() string {
return "revision"

View File

@ -5,6 +5,7 @@ import (
"github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/internal/base/data"
"github.com/answerdev/answer/internal/base/pager"
"github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/service/revision"
@ -165,37 +166,21 @@ func (rr *revisionRepo) allowRecord(objectType int) (ok bool) {
}
}
func (rr *revisionRepo) SearchUnreviewedList(ctx context.Context, search *entity.RevisionSearch) ([]*entity.Revision, int64, error) {
var count int64
var err error
rows := make([]*entity.Revision, 0)
if search.Page > 0 {
search.Page = search.Page - 1
} else {
search.Page = 0
// GetUnreviewedRevisionPage get unreviewed revision page
func (rr *revisionRepo) GetUnreviewedRevisionPage(ctx context.Context, page int, pageSize int,
objectTypeList []int) (revisionList []*entity.Revision, total int64, err error) {
revisionList = make([]*entity.Revision, 0)
if len(objectTypeList) == 0 {
return revisionList, 0, nil
}
PageSize := 1
offset := search.Page * PageSize
objectType := make([]int, 0)
if search.CanReviewAnswer {
objectType = append(objectType, constant.ObjectTypeStrMapping[constant.AnswerObjectType])
}
if search.CanReviewQuestion {
objectType = append(objectType, constant.ObjectTypeStrMapping[constant.QuestionObjectType])
}
if search.CanReviewTag {
objectType = append(objectType, constant.ObjectTypeStrMapping[constant.TagObjectType])
}
session := rr.data.DB.Where("")
session = session.And("status = ?", entity.RevisionUnreviewedStatus)
session = session.In("object_type", objectType)
session := rr.data.DB.NewSession()
session = session.And("status = ?", entity.RevisionUnreviewedStatus)
session = session.In("object_type", objectTypeList)
session = session.OrderBy("created_at desc")
session = session.Limit(PageSize, offset)
count, err = session.FindAndCount(&rows)
total, err = pager.Help(page, pageSize, &revisionList, &entity.Revision{}, session)
if err != nil {
return rows, count, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return rows, count, nil
return
}

View File

@ -147,7 +147,7 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
//revisions
r.GET("/revisions/unreviewed", a.revisionController.GetUnreviewedRevisionList)
r.PUT("/revisions/audit", a.revisionController.RevisionAudit)
r.GET("/revisions/edit/check", a.questionController.CheckCanUpdateQuestion)
r.GET("/revisions/edit/check", a.revisionController.CheckCanUpdateRevision)
// comment
r.POST("/comment", a.commentController.AddComment)

View File

@ -2,6 +2,8 @@ package schema
import (
"time"
"github.com/answerdev/answer/internal/base/constant"
)
// AddRevisionDTO add revision request
@ -47,6 +49,20 @@ type RevisionSearch struct {
UserID string `json:"-"`
}
func (r RevisionSearch) GetCanReviewObjectTypes() []int {
objectType := make([]int, 0)
if r.CanReviewAnswer {
objectType = append(objectType, constant.ObjectTypeStrMapping[constant.AnswerObjectType])
}
if r.CanReviewQuestion {
objectType = append(objectType, constant.ObjectTypeStrMapping[constant.QuestionObjectType])
}
if r.CanReviewTag {
objectType = append(objectType, constant.ObjectTypeStrMapping[constant.TagObjectType])
}
return objectType
}
type GetUnreviewedRevisionResp struct {
Type string `json:"type"`
Info *UnreviewedRevisionInfoInfo `json:"info"`

View File

@ -858,16 +858,3 @@ func (qs *QuestionService) changeQuestionToRevision(ctx context.Context, questio
}
return questionRevision, nil
}
// CheckCanUpdate can check question answer
func (qs *QuestionService) CheckCanUpdate(ctx context.Context, req *schema.CheckCanQuestionUpdate) (exist bool, err error) {
_, existUnreviewed, err := qs.revisionService.ExistUnreviewedByObjectID(ctx, req.ID)
if err != nil {
return false, err
}
if existUnreviewed {
err = errors.BadRequest(reason.RevisionReviewUnderway)
return existUnreviewed, err
}
return existUnreviewed, nil
}

View File

@ -15,6 +15,6 @@ type RevisionRepo interface {
GetRevisionList(ctx context.Context, revision *entity.Revision) (revisionList []entity.Revision, err error)
UpdateObjectRevisionId(ctx context.Context, revision *entity.Revision, session *xorm.Session) (err error)
ExistUnreviewedByObjectID(ctx context.Context, objectID string) (revision *entity.Revision, exist bool, err error)
SearchUnreviewedList(ctx context.Context, search *entity.RevisionSearch) ([]*entity.Revision, int64, error)
GetUnreviewedRevisionPage(ctx context.Context, page, pageSize int, objectTypes []int) ([]*entity.Revision, int64, error)
UpdateStatus(ctx context.Context, id string, status int) (err error)
}

View File

@ -27,10 +27,10 @@ func NewRevisionService(revisionRepo revision.RevisionRepo, userRepo usercommon.
}
func (rs *RevisionService) GetUnreviewedRevisionCount(ctx context.Context, req *schema.RevisionSearch) (count int64, err error) {
search := &entity.RevisionSearch{}
search.Page = 1
_ = copier.Copy(search, req)
_, count, err = rs.revisionRepo.SearchUnreviewedList(ctx, search)
if len(req.GetCanReviewObjectTypes()) == 0 {
return 0, nil
}
_, count, err = rs.revisionRepo.GetUnreviewedRevisionPage(ctx, req.Page, 1, req.GetCanReviewObjectTypes())
return count, err
}

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/internal/base/pager"
"github.com/answerdev/answer/internal/base/reason"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/schema"
@ -48,7 +49,6 @@ func NewRevisionService(
answerRepo answercommon.AnswerRepo,
tagRepo tag_common.TagRepo,
tagCommon *tagcommon.TagCommonService,
) *RevisionService {
return &RevisionService{
revisionRepo: revisionRepo,
@ -247,43 +247,48 @@ func (rs *RevisionService) revisionAuditTag(ctx context.Context, revisionitem *s
return nil
}
// SearchUnreviewedList get unreviewed list
func (rs *RevisionService) GetUnreviewedRevisionList(ctx context.Context, req *schema.RevisionSearch) (resp []*schema.GetUnreviewedRevisionResp, count int64, err error) {
resp = []*schema.GetUnreviewedRevisionResp{}
search := &entity.RevisionSearch{}
_ = copier.Copy(search, req)
list, count, err := rs.revisionRepo.SearchUnreviewedList(ctx, search)
for _, revision := range list {
// GetUnreviewedRevisionPage get unreviewed list
func (rs *RevisionService) GetUnreviewedRevisionPage(ctx context.Context, req *schema.RevisionSearch) (
resp *pager.PageModel, err error) {
revisionResp := make([]*schema.GetUnreviewedRevisionResp, 0)
if len(req.GetCanReviewObjectTypes()) == 0 {
return pager.NewPageModel(0, revisionResp), nil
}
revisionPage, total, err := rs.revisionRepo.GetUnreviewedRevisionPage(
ctx, req.Page, 1, req.GetCanReviewObjectTypes())
if err != nil {
return nil, err
}
for _, rev := range revisionPage {
item := &schema.GetUnreviewedRevisionResp{}
_, ok := constant.ObjectTypeNumberMapping[revision.ObjectType]
_, ok := constant.ObjectTypeNumberMapping[rev.ObjectType]
if !ok {
continue
}
item.Type = constant.ObjectTypeNumberMapping[revision.ObjectType]
info, infoerr := rs.objectInfoService.GetUnreviewedRevisionInfo(ctx, revision.ObjectID)
if infoerr != nil {
return resp, 0, infoerr
item.Type = constant.ObjectTypeNumberMapping[rev.ObjectType]
info, err := rs.objectInfoService.GetUnreviewedRevisionInfo(ctx, rev.ObjectID)
if err != nil {
return nil, err
}
item.Info = info
revisionitem := &schema.GetRevisionResp{}
_ = copier.Copy(revisionitem, revision)
_ = copier.Copy(revisionitem, rev)
rs.parseItem(ctx, revisionitem)
item.UnreviewedInfo = revisionitem
// get user info
userInfo, exists, e := rs.userCommon.GetUserBasicInfoByID(ctx, revisionitem.UserID)
if e != nil {
return resp, 0, e
return nil, e
}
if exists {
var uinfo schema.UserBasicInfo
err = copier.Copy(&uinfo, userInfo)
item.UnreviewedInfo.UserInfo = uinfo
}
resp = append(resp, item)
revisionResp = append(revisionResp, item)
}
return
return pager.NewPageModel(total, revisionResp), nil
}
// GetRevisionList get revision list all
@ -377,3 +382,15 @@ func (rs *RevisionService) parseItem(ctx context.Context, item *schema.GetRevisi
}
item.CreatedAtParsed = item.CreatedAt.Unix()
}
// CheckCanUpdateRevision can check revision
func (rs *RevisionService) CheckCanUpdateRevision(ctx context.Context, req *schema.CheckCanQuestionUpdate) (err error) {
_, exist, err := rs.revisionRepo.ExistUnreviewedByObjectID(ctx, req.ID)
if err != nil {
return err
}
if exist {
return errors.BadRequest(reason.RevisionReviewUnderway)
}
return nil
}