Add CommentData struct for shadow copies of comments.

This commit is contained in:
floss4good 2025-02-22 13:49:38 +02:00
parent 8ef30b81c2
commit 4dc1db8730
No known key found for this signature in database
GPG key ID: 5B948B4F4DAF819D
2 changed files with 68 additions and 0 deletions

View file

@ -1,5 +1,6 @@
// Copyright 2018 The Gitea Authors.
// Copyright 2016 The Gogs Authors.
// Copyright 2025 The Forgejo Authors. All rights reserved.
// All rights reserved.
// SPDX-License-Identifier: MIT
@ -326,6 +327,9 @@ type Comment struct {
NewCommit string `xorm:"-"`
CommitsNum int64 `xorm:"-"`
IsForcePush bool `xorm:"-"`
// If you add new fields that might be used to store abusive content (mainly string fields),
// please also add them in the CommentData struct and the corresponding constructor.
}
func init() {
@ -1151,6 +1155,11 @@ func UpdateComment(ctx context.Context, c *Comment, contentVersion int, doer *us
}
defer committer.Close()
// If the comment was reported as abusive, a shadow copy should be created before first update.
if err := IfNeededCreateShadowCopyForComment(ctx, c); err != nil {
return err
}
if err := c.LoadIssue(ctx); err != nil {
return err
}
@ -1186,6 +1195,12 @@ func UpdateComment(ctx context.Context, c *Comment, contentVersion int, doer *us
// DeleteComment deletes the comment
func DeleteComment(ctx context.Context, comment *Comment) error {
e := db.GetEngine(ctx)
// If the comment was reported as abusive, a shadow copy should be created before deletion.
if err := IfNeededCreateShadowCopyForComment(ctx, comment); err != nil {
return err
}
if _, err := e.ID(comment.ID).NoAutoCondition().Delete(comment); err != nil {
return err
}

View file

@ -0,0 +1,53 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package issues
import (
"context"
"code.gitea.io/gitea/models/moderation"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/timeutil"
)
// CommentData represents a trimmed down comment that is used for preserving
// only the fields needed for abusive content reports (mainly string fields).
type CommentData struct {
OriginalAuthor string // TODO: decide if this is needed
TreePath string // TODO: decide if this is needed
Content string
ContentVersion int
CreatedUnix timeutil.TimeStamp
UpdatedUnix timeutil.TimeStamp
}
// newCommentData creates a trimmed down comment to be used just to create a JSON structure
// (keeping only the fields relevant for moderation purposes)
func newCommentData(comment *Comment) CommentData {
return CommentData{
OriginalAuthor: comment.OriginalAuthor,
TreePath: comment.TreePath,
Content: comment.Content,
ContentVersion: comment.ContentVersion,
CreatedUnix: comment.CreatedUnix,
UpdatedUnix: comment.UpdatedUnix,
}
}
// IfNeededCreateShadowCopyForComment checks if for the given comment there are any reports of abusive content submitted
// and if found a shadow copy of relevant comment fields will be stored into DB and linked to the above report(s).
// This function should be called when a comment is deleted or updated.
func IfNeededCreateShadowCopyForComment(ctx context.Context, comment *Comment) error {
// TODO check comment.Type?
if moderation.IsReported(ctx, moderation.ReportedContentTypeComment, comment.ID) {
commentData := newCommentData(comment)
content, err := json.Marshal(commentData)
if err != nil {
return err
}
return moderation.CreateShadowCopyForComment(ctx, comment.ID, string(content))
}
return nil
}