250 lines
8.1 KiB
Go
250 lines
8.1 KiB
Go
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
package report
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"github.com/apache/answer/internal/service/eventqueue"
|
|
|
|
"github.com/apache/answer/internal/base/constant"
|
|
"github.com/apache/answer/internal/base/handler"
|
|
"github.com/apache/answer/internal/base/pager"
|
|
"github.com/apache/answer/internal/base/reason"
|
|
"github.com/apache/answer/internal/entity"
|
|
"github.com/apache/answer/internal/schema"
|
|
answercommon "github.com/apache/answer/internal/service/answer_common"
|
|
"github.com/apache/answer/internal/service/comment_common"
|
|
"github.com/apache/answer/internal/service/config"
|
|
"github.com/apache/answer/internal/service/object_info"
|
|
questioncommon "github.com/apache/answer/internal/service/question_common"
|
|
"github.com/apache/answer/internal/service/report_common"
|
|
"github.com/apache/answer/internal/service/report_handle"
|
|
usercommon "github.com/apache/answer/internal/service/user_common"
|
|
"github.com/apache/answer/pkg/checker"
|
|
"github.com/apache/answer/pkg/htmltext"
|
|
"github.com/apache/answer/pkg/obj"
|
|
"github.com/jinzhu/copier"
|
|
"github.com/segmentfault/pacman/errors"
|
|
"github.com/segmentfault/pacman/log"
|
|
)
|
|
|
|
// ReportService user service
|
|
type ReportService struct {
|
|
reportRepo report_common.ReportRepo
|
|
objectInfoService *object_info.ObjService
|
|
commonUser *usercommon.UserCommon
|
|
answerRepo answercommon.AnswerRepo
|
|
questionRepo questioncommon.QuestionRepo
|
|
commentCommonRepo comment_common.CommentCommonRepo
|
|
reportHandle *report_handle.ReportHandle
|
|
configService *config.ConfigService
|
|
eventQueueService eventqueue.Service
|
|
}
|
|
|
|
// NewReportService new report service
|
|
func NewReportService(
|
|
reportRepo report_common.ReportRepo,
|
|
objectInfoService *object_info.ObjService,
|
|
commonUser *usercommon.UserCommon,
|
|
answerRepo answercommon.AnswerRepo,
|
|
questionRepo questioncommon.QuestionRepo,
|
|
commentCommonRepo comment_common.CommentCommonRepo,
|
|
reportHandle *report_handle.ReportHandle,
|
|
configService *config.ConfigService,
|
|
eventQueueService eventqueue.Service,
|
|
) *ReportService {
|
|
return &ReportService{
|
|
reportRepo: reportRepo,
|
|
objectInfoService: objectInfoService,
|
|
commonUser: commonUser,
|
|
answerRepo: answerRepo,
|
|
questionRepo: questionRepo,
|
|
commentCommonRepo: commentCommonRepo,
|
|
reportHandle: reportHandle,
|
|
configService: configService,
|
|
eventQueueService: eventQueueService,
|
|
}
|
|
}
|
|
|
|
// AddReport add report
|
|
func (rs *ReportService) AddReport(ctx context.Context, req *schema.AddReportReq) (err error) {
|
|
objectTypeNumber, err := obj.GetObjectTypeNumberByObjectID(req.ObjectID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
objInfo, err := rs.objectInfoService.GetInfo(ctx, req.ObjectID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if objInfo.IsDeleted() {
|
|
return errors.BadRequest(reason.NewObjectAlreadyDeleted)
|
|
}
|
|
|
|
cf, err := rs.configService.GetConfigByID(ctx, req.ReportType)
|
|
if err != nil || cf == nil {
|
|
return errors.BadRequest(reason.ReportNotFound)
|
|
}
|
|
if cf.Key == constant.ReasonADuplicate && !checker.IsURL(req.Content) {
|
|
return errors.BadRequest(reason.InvalidURLError)
|
|
}
|
|
|
|
report := &entity.Report{
|
|
UserID: req.UserID,
|
|
ReportedUserID: objInfo.ObjectCreatorUserID,
|
|
ObjectID: req.ObjectID,
|
|
ObjectType: objectTypeNumber,
|
|
ReportType: req.ReportType,
|
|
Content: req.Content,
|
|
Status: entity.ReportStatusPending,
|
|
}
|
|
err = rs.reportRepo.AddReport(ctx, report)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rs.sendEvent(ctx, report, objInfo)
|
|
return nil
|
|
}
|
|
|
|
// GetUnreviewedReportPostPage get unreviewed report post page
|
|
func (rs *ReportService) GetUnreviewedReportPostPage(ctx context.Context, req *schema.GetUnreviewedReportPostPageReq) (
|
|
pageModel *pager.PageModel, err error) {
|
|
if !req.IsAdmin {
|
|
return pager.NewPageModel(0, make([]*schema.GetReportListPageResp, 0)), nil
|
|
}
|
|
lang := handler.GetLangByCtx(ctx)
|
|
reports, total, err := rs.reportRepo.GetReportListPage(ctx, &schema.GetReportListPageDTO{
|
|
Page: req.Page,
|
|
PageSize: 1,
|
|
Status: entity.ReportStatusPending,
|
|
})
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
resp := make([]*schema.GetReportListPageResp, 0)
|
|
for _, report := range reports {
|
|
info, err := rs.objectInfoService.GetUnreviewedRevisionInfo(ctx, report.ObjectID)
|
|
if err != nil {
|
|
log.Errorf("GetUnreviewedRevisionInfo failed, err: %v", err)
|
|
continue
|
|
}
|
|
|
|
r := &schema.GetReportListPageResp{
|
|
FlagID: report.ID,
|
|
CreatedAt: info.CreatedAt,
|
|
ObjectID: info.ObjectID,
|
|
ObjectType: info.ObjectType,
|
|
QuestionID: info.QuestionID,
|
|
AnswerID: info.AnswerID,
|
|
CommentID: info.CommentID,
|
|
Title: info.Title,
|
|
UrlTitle: htmltext.UrlTitle(info.Title),
|
|
OriginalText: info.Content,
|
|
ParsedText: info.Html,
|
|
AnswerCount: info.AnswerCount,
|
|
AnswerAccepted: info.AnswerAccepted,
|
|
Tags: info.Tags,
|
|
SubmitAt: report.CreatedAt.Unix(),
|
|
ObjectStatus: info.Status,
|
|
ObjectShowStatus: info.ShowStatus,
|
|
ReasonContent: report.Content,
|
|
}
|
|
|
|
// get user info
|
|
userInfo, exists, e := rs.commonUser.GetUserBasicInfoByID(ctx, info.ObjectCreatorUserID)
|
|
if e != nil {
|
|
log.Errorf("user not found by id: %s, err: %v", info.ObjectCreatorUserID, e)
|
|
}
|
|
if exists {
|
|
_ = copier.Copy(&r.AuthorUserInfo, userInfo)
|
|
}
|
|
|
|
// get submitter info
|
|
submitter, exists, e := rs.commonUser.GetUserBasicInfoByID(ctx, report.ReportedUserID)
|
|
if e != nil {
|
|
log.Errorf("user not found by id: %s, err: %v", info.ObjectCreatorUserID, e)
|
|
}
|
|
if exists {
|
|
_ = copier.Copy(&r.SubmitterUser, submitter)
|
|
}
|
|
|
|
if report.ReportType > 0 {
|
|
r.Reason = &schema.ReasonItem{ReasonType: report.ReportType}
|
|
cf, err := rs.configService.GetConfigByID(ctx, report.ReportType)
|
|
if err != nil {
|
|
log.Error(err)
|
|
} else {
|
|
_ = json.Unmarshal([]byte(cf.Value), r.Reason)
|
|
r.Reason.Translate(cf.Key, lang)
|
|
}
|
|
}
|
|
resp = append(resp, r)
|
|
}
|
|
return pager.NewPageModel(total, resp), nil
|
|
}
|
|
|
|
// ReviewReport review report
|
|
func (rs *ReportService) ReviewReport(ctx context.Context, req *schema.ReviewReportReq) (err error) {
|
|
report, exist, err := rs.reportRepo.GetByID(ctx, req.FlagID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exist {
|
|
return errors.NotFound(reason.ReportNotFound)
|
|
}
|
|
// check if handle or not
|
|
if report.Status != entity.ReportStatusPending {
|
|
return nil
|
|
}
|
|
|
|
// ignore this report
|
|
if req.OperationType == constant.ReportOperationIgnoreReport {
|
|
return rs.reportRepo.UpdateStatus(ctx, report.ID, entity.ReportStatusIgnore)
|
|
}
|
|
|
|
if err = rs.reportHandle.UpdateReportedObject(ctx, report, req); err != nil {
|
|
return
|
|
}
|
|
|
|
return rs.reportRepo.UpdateStatus(ctx, report.ID, entity.ReportStatusCompleted)
|
|
}
|
|
|
|
func (rs *ReportService) sendEvent(ctx context.Context,
|
|
report *entity.Report, objectInfo *schema.SimpleObjectInfo) {
|
|
var event *schema.EventMsg
|
|
switch objectInfo.ObjectType {
|
|
case constant.QuestionObjectType:
|
|
event = schema.NewEvent(constant.EventQuestionFlag, report.UserID).TID(objectInfo.QuestionID).
|
|
QID(objectInfo.QuestionID, objectInfo.ObjectCreatorUserID)
|
|
case constant.AnswerObjectType:
|
|
event = schema.NewEvent(constant.EventAnswerFlag, report.UserID).TID(objectInfo.AnswerID).
|
|
AID(objectInfo.AnswerID, objectInfo.ObjectCreatorUserID)
|
|
case constant.CommentObjectType:
|
|
event = schema.NewEvent(constant.EventCommentFlag, report.UserID).TID(objectInfo.CommentID).
|
|
CID(objectInfo.CommentID, objectInfo.ObjectCreatorUserID)
|
|
default:
|
|
return
|
|
}
|
|
rs.eventQueueService.Send(ctx, event)
|
|
}
|