Merge branch 'feat/1.0.4/comment' into test
This commit is contained in:
@@ -6716,6 +6716,9 @@ const docTemplate = `{
|
||||
"collection_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -6704,6 +6704,9 @@
|
||||
"collection_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -1041,6 +1041,8 @@ definitions:
|
||||
type: integer
|
||||
collection_count:
|
||||
type: integer
|
||||
created_at:
|
||||
type: integer
|
||||
description:
|
||||
type: string
|
||||
follow_count:
|
||||
|
||||
@@ -52,6 +52,8 @@ backend:
|
||||
other: "Comment are not allowed to edit."
|
||||
not_found:
|
||||
other: "Comment not found."
|
||||
cannot_edit_after_deadline:
|
||||
other: "The comment time has been too long to modify."
|
||||
email:
|
||||
duplicate:
|
||||
other: "Email already exists."
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package constant
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
CommentEditDeadline = time.Minute * 5
|
||||
)
|
||||
@@ -16,6 +16,7 @@ const (
|
||||
const (
|
||||
EmailOrPasswordWrong = "error.object.email_or_password_incorrect"
|
||||
CommentNotFound = "error.comment.not_found"
|
||||
CommentCannotEditAfterDeadline = "error.comment.cannot_edit_after_deadline"
|
||||
QuestionNotFound = "error.question.not_found"
|
||||
QuestionCannotDeleted = "error.question.cannot_deleted"
|
||||
QuestionCannotClose = "error.question.cannot_close"
|
||||
|
||||
@@ -111,6 +111,7 @@ func (cc *CommentController) UpdateComment(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||
req.IsAdmin = middleware.GetIsAdminFromContext(ctx)
|
||||
can, err := cc.rankService.CheckOperationPermission(ctx, req.UserID, permission.CommentEdit, req.CommentID)
|
||||
if err != nil {
|
||||
handler.HandleResponse(ctx, err, nil)
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
type TemplateController struct {
|
||||
scriptPath string
|
||||
cssPath string
|
||||
Version string
|
||||
templateRenderController *templaterender.TemplateRenderController
|
||||
siteInfoService *siteinfo_common.SiteInfoCommonService
|
||||
}
|
||||
@@ -38,6 +39,7 @@ func NewTemplateController(
|
||||
return &TemplateController{
|
||||
scriptPath: script,
|
||||
cssPath: css,
|
||||
Version: constant.Version,
|
||||
templateRenderController: templateRenderController,
|
||||
siteInfoService: siteInfoService,
|
||||
}
|
||||
@@ -437,6 +439,7 @@ func (tc *TemplateController) html(ctx *gin.Context, code int, tpl string, siteI
|
||||
data["HeadCode"] = siteInfo.CustomCssHtml.CustomHead
|
||||
data["HeaderCode"] = siteInfo.CustomCssHtml.CustomHeader
|
||||
data["FooterCode"] = siteInfo.CustomCssHtml.CustomFooter
|
||||
data["Version"] = tc.Version
|
||||
_, ok := data["path"]
|
||||
if !ok {
|
||||
data["path"] = ""
|
||||
|
||||
@@ -51,7 +51,8 @@ type UpdateCommentReq struct {
|
||||
// parsed comment content
|
||||
ParsedText string `validate:"omitempty" json:"parsed_text"`
|
||||
// user id
|
||||
UserID string `json:"-"`
|
||||
UserID string `json:"-"`
|
||||
IsAdmin bool `json:"-"`
|
||||
}
|
||||
|
||||
func (req *UpdateCommentReq) Check() (errFields []*validator.FormErrorField, err error) {
|
||||
|
||||
@@ -219,7 +219,7 @@ type UserQuestionInfo struct {
|
||||
ViewCount int `json:"view_count"`
|
||||
AnswerCount int `json:"answer_count"`
|
||||
CollectionCount int `json:"collection_count"`
|
||||
CreateTime int `json:"create_time"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
AcceptedAnswerID string `json:"accepted_answer_id"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
@@ -253,6 +253,7 @@ const (
|
||||
|
||||
type QuestionPageResp struct {
|
||||
ID string `json:"id" `
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Title string `json:"title"`
|
||||
UrlTitle string `json:"url_title"`
|
||||
Description string `json:"description"`
|
||||
|
||||
@@ -134,7 +134,8 @@ func (cs *CommentService) AddComment(ctx context.Context, req *schema.AddComment
|
||||
|
||||
resp = &schema.GetCommentResp{}
|
||||
resp.SetFromComment(comment)
|
||||
resp.MemberActions = permission.GetCommentPermission(ctx, req.UserID, resp.UserID, req.CanEdit, req.CanDelete)
|
||||
resp.MemberActions = permission.GetCommentPermission(ctx, req.UserID, resp.UserID,
|
||||
time.Now(), req.CanEdit, req.CanDelete)
|
||||
|
||||
// get reply user info
|
||||
if len(resp.ReplyUserID) > 0 {
|
||||
@@ -185,6 +186,19 @@ func (cs *CommentService) RemoveComment(ctx context.Context, req *schema.RemoveC
|
||||
|
||||
// UpdateComment update comment
|
||||
func (cs *CommentService) UpdateComment(ctx context.Context, req *schema.UpdateCommentReq) (err error) {
|
||||
old, exist, err := cs.commentCommonRepo.GetComment(ctx, req.CommentID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !exist {
|
||||
return errors.BadRequest(reason.CommentNotFound)
|
||||
}
|
||||
|
||||
// user can edit the comment that was posted by himself before deadline.
|
||||
if !req.IsAdmin && (time.Now().After(old.CreatedAt.Add(constant.CommentEditDeadline))) {
|
||||
return errors.BadRequest(reason.CommentCannotEditAfterDeadline)
|
||||
}
|
||||
|
||||
comment := &entity.Comment{}
|
||||
_ = copier.Copy(comment, req)
|
||||
comment.ID = req.CommentID
|
||||
@@ -198,7 +212,7 @@ func (cs *CommentService) GetComment(ctx context.Context, req *schema.GetComment
|
||||
return
|
||||
}
|
||||
if !exist {
|
||||
return nil, errors.BadRequest(reason.UnknownError)
|
||||
return nil, errors.BadRequest(reason.CommentNotFound)
|
||||
}
|
||||
|
||||
resp = &schema.GetCommentResp{
|
||||
@@ -243,7 +257,8 @@ func (cs *CommentService) GetComment(ctx context.Context, req *schema.GetComment
|
||||
// check if current user vote this comment
|
||||
resp.IsVote = cs.checkIsVote(ctx, req.UserID, resp.CommentID)
|
||||
|
||||
resp.MemberActions = permission.GetCommentPermission(ctx, req.UserID, resp.UserID, req.CanEdit, req.CanDelete)
|
||||
resp.MemberActions = permission.GetCommentPermission(ctx, req.UserID, resp.UserID,
|
||||
comment.CreatedAt, req.CanEdit, req.CanDelete)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -339,7 +354,7 @@ func (cs *CommentService) convertCommentEntity2Resp(ctx context.Context, req *sc
|
||||
commentResp.IsVote = cs.checkIsVote(ctx, req.UserID, commentResp.CommentID)
|
||||
|
||||
commentResp.MemberActions = permission.GetCommentPermission(ctx,
|
||||
req.UserID, commentResp.UserID, req.CanEdit, req.CanDelete)
|
||||
req.UserID, commentResp.UserID, comment.CreatedAt, req.CanEdit, req.CanDelete)
|
||||
return commentResp, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,15 @@ package permission
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/answerdev/answer/internal/base/constant"
|
||||
"github.com/answerdev/answer/internal/schema"
|
||||
)
|
||||
|
||||
// GetCommentPermission get comment permission
|
||||
func GetCommentPermission(ctx context.Context, userID string, creatorUserID string, canEdit, canDelete bool) (
|
||||
actions []*schema.PermissionMemberAction) {
|
||||
func GetCommentPermission(ctx context.Context, userID string, creatorUserID string,
|
||||
createdAt time.Time, canEdit, canDelete bool) (actions []*schema.PermissionMemberAction) {
|
||||
actions = make([]*schema.PermissionMemberAction, 0)
|
||||
if len(userID) > 0 {
|
||||
actions = append(actions, &schema.PermissionMemberAction{
|
||||
@@ -17,7 +19,8 @@ func GetCommentPermission(ctx context.Context, userID string, creatorUserID stri
|
||||
Type: "reason",
|
||||
})
|
||||
}
|
||||
if canEdit || userID == creatorUserID {
|
||||
deadline := createdAt.Add(constant.CommentEditDeadline)
|
||||
if canEdit || (userID == creatorUserID && time.Now().Before(deadline)) {
|
||||
actions = append(actions, &schema.PermissionMemberAction{
|
||||
Action: "edit",
|
||||
Name: "Edit",
|
||||
|
||||
@@ -254,6 +254,7 @@ func (qs *QuestionCommon) FormatQuestionsPage(
|
||||
for _, questionInfo := range questionList {
|
||||
t := &schema.QuestionPageResp{
|
||||
ID: questionInfo.ID,
|
||||
CreatedAt: questionInfo.CreatedAt.Unix(),
|
||||
Title: questionInfo.Title,
|
||||
UrlTitle: htmltext.UrlTitle(questionInfo.Title),
|
||||
Description: htmltext.FetchExcerpt(questionInfo.ParsedText, "...", 240),
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>{{.title}}</title>
|
||||
<meta name="description" content="{{.description}}" data-rh="true" />
|
||||
{{if .keywords }}
|
||||
<meta name="keywords" content="{{.keywords}}" data-rh="true" />
|
||||
{{end}}
|
||||
<meta name="generator" content="Answer {{.Version}} - https://github.com/answerdev/answer">
|
||||
{{if .keywords }}<meta name="keywords" content="{{.keywords}}" data-rh="true" />{{end}}
|
||||
|
||||
<link rel="canonical" href="{{.siteinfo.Canonical}}" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link href="{{.cssPath}}" rel="stylesheet" />
|
||||
|
||||
Reference in New Issue
Block a user