fix: when deciding that a shadow copy should be created also check that existing reports have a null shadow_copy_id

- also rename the function to better indicate the purpose

- and handle potential errors returned by Session.Exist()
This commit is contained in:
floss4good 2025-04-04 01:32:03 +03:00
parent ca0636a6fc
commit 41cc860666
No known key found for this signature in database
GPG key ID: 5B948B4F4DAF819D
4 changed files with 38 additions and 15 deletions

View file

@ -67,7 +67,12 @@ func newCommentData(comment *Comment) CommentData {
// and if found a shadow copy of relevant issue fields will be stored into DB and linked to the above report(s).
// This function should be called before a issue is deleted or updated.
func IfNeededCreateShadowCopyForIssue(ctx context.Context, issue *Issue) error {
if moderation.IsReported(ctx, moderation.ReportedContentTypeIssue, issue.ID) {
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeIssue, issue.ID)
if err != nil {
return err
}
if shadowCopyNeeded {
issueData := newIssueData(issue)
content, err := json.Marshal(issueData)
if err != nil {
@ -83,7 +88,12 @@ func IfNeededCreateShadowCopyForIssue(ctx context.Context, issue *Issue) error {
// 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 before a comment is deleted or updated.
func IfNeededCreateShadowCopyForComment(ctx context.Context, comment *Comment) error {
if moderation.IsReported(ctx, moderation.ReportedContentTypeComment, comment.ID) {
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeComment, comment.ID)
if err != nil {
return err
}
if shadowCopyNeeded {
commentData := newCommentData(comment)
content, err := json.Marshal(commentData)
if err != nil {

View file

@ -115,12 +115,12 @@ func init() {
db.RegisterModel(new(AbuseReport))
}
// IsReported reports whether one or more reports were already submitted for contentType and contentID
// (regardless the status of the reports).
func IsReported(ctx context.Context, contentType ReportedContentType, contentID int64) bool {
// TODO: only consider the reports with 'New' status (and adjust the function name)?!
reported, _ := db.GetEngine(ctx).Exist(&AbuseReport{ContentType: contentType, ContentID: contentID})
return reported
// IsShadowCopyNeeded reports whether one or more reports were already submitted
// for contentType and contentID and not yet linked to a shadow copy (regardless their status).
func IsShadowCopyNeeded(ctx context.Context, contentType ReportedContentType, contentID int64) (bool, error) {
return db.GetEngine(ctx).Cols("id").Where(builder.IsNull{"shadow_copy_id"}).Exist(
&AbuseReport{ContentType: contentType, ContentID: contentID},
)
}
// AlreadyReportedByAndOpen returns if doerID has already submitted a report for contentType and contentID that is still Open.

View file

@ -45,9 +45,13 @@ func newRepositoryData(repo *Repository) RepositoryData {
// and if found a shadow copy of relevant repository fields will be stored into DB and linked to the above report(s).
// This function should be called when a repository is deleted or updated.
func IfNeededCreateShadowCopyForRepository(ctx context.Context, repo *Repository, forUpdates bool) error {
if moderation.IsReported(ctx, moderation.ReportedContentTypeRepository, repo.ID) {
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeRepository, repo.ID)
if err != nil {
return err
}
if shadowCopyNeeded {
if forUpdates {
var err error
// get the unmodified repository fields
repo, err = GetRepositoryByID(ctx, repo.ID)
if err != nil {

View file

@ -71,7 +71,7 @@ var userDataColumnNames = sync.OnceValue(func() []string {
// IfNeededCreateShadowCopyForUser checks if for the given user there are any reports of abusive content submitted
// and if found a shadow copy of relevant user fields will be stored into DB and linked to the above report(s).
// This function should be called when a user is deleted or updated.
// This function should be called before a user is deleted or updated.
//
// For deletions alteredCols argument must be omitted.
//
@ -80,17 +80,26 @@ var userDataColumnNames = sync.OnceValue(func() []string {
func IfNeededCreateShadowCopyForUser(ctx context.Context, user *User, alteredCols ...string) error {
// TODO: this can be triggered quite often (e.g. by routers/web/repo/middlewares.go SetDiffViewStyle())
shouldCheckIfReported := len(alteredCols) == 0 // no columns being updated, therefore a deletion
if !shouldCheckIfReported {
shouldCheckIfNeeded := len(alteredCols) == 0 // no columns being updated, therefore a deletion
if !shouldCheckIfNeeded {
// for updates we need to go further only if certain column are being changed
for _, colName := range userDataColumnNames() {
if shouldCheckIfReported = slices.Contains(alteredCols, colName); shouldCheckIfReported {
if shouldCheckIfNeeded = slices.Contains(alteredCols, colName); shouldCheckIfNeeded {
break
}
}
}
if shouldCheckIfReported && moderation.IsReported(ctx, moderation.ReportedContentTypeUser, user.ID) {
if !shouldCheckIfNeeded {
return nil
}
shadowCopyNeeded, err := moderation.IsShadowCopyNeeded(ctx, moderation.ReportedContentTypeUser, user.ID)
if err != nil {
return err
}
if shadowCopyNeeded {
userData := newUserData(user)
content, err := json.Marshal(userData)
if err != nil {