Skip to content

Commit 9b7ec78

Browse files
author
Oleg Komarov
committed
update comments
1 parent 6a2c2be commit 9b7ec78

File tree

6 files changed

+41
-9
lines changed

6 files changed

+41
-9
lines changed

models/user/spamreport.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2025 The Gitea Authors. All rights reserved.
22
// SPDX-License-Identifier: MIT
33

4+
// BLENDER: spam reporting
5+
46
package user
57

68
import (
@@ -13,10 +15,10 @@ import (
1315

1416
// SpamReportStatusType is used to support a spam report lifecycle:
1517
//
16-
// Pending -> Processing
17-
// Processing -> Processed|Dismissed
18+
// pending -> locked
19+
// locked -> processed | dismissed
1820
//
19-
// "Processing" status works as a lock for a record that is being processed.
21+
// "locked" status works as a lock for a record that is being processed.
2022
type SpamReportStatusType int
2123

2224
const (

routers/web/admin/spamreports.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const (
2222
tplSpamReports base.TplName = "admin/spamreports/list"
2323
)
2424

25-
// SpamReports show spam reports
25+
// SpamReports shows spam reports
2626
func SpamReports(ctx *context.Context) {
2727
ctx.Data["Title"] = ctx.Tr("admin.spamreports")
2828
ctx.Data["PageIsSpamReports"] = true
@@ -33,7 +33,7 @@ func SpamReports(ctx *context.Context) {
3333
filterStatus user_model.SpamReportStatusType
3434
)
3535

36-
// When no value is specified Pending (status=0) reports are shown,
36+
// When no value is specified reports are filtered by status=pending (=0),
3737
// which luckily makes sense as a default view.
3838
filterStatus = user_model.SpamReportStatusType(ctx.FormInt("status"))
3939
ctx.Data["FilterStatus"] = filterStatus
@@ -74,6 +74,8 @@ func SpamReports(ctx *context.Context) {
7474
ctx.HTML(http.StatusOK, tplSpamReports)
7575
}
7676

77+
// SpamReportsPost handles "process" and "dismiss" actions for pending reports.
78+
// The processing is done synchronously.
7779
func SpamReportsPost(ctx *context.Context) {
7880
action := ctx.FormString("action")
7981
// ctx.Req.PostForm is now parsed due to the call to FormString above

routers/web/user/setting/spamreport.go

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
user_service "code.gitea.io/gitea/services/user"
1515
)
1616

17+
// SpamReportUserPost creates a spam report for a given user.
1718
func SpamReportUserPost(ctx *context.Context) {
1819
canReportSpam, err := user_service.IsTrustedUser(ctx, ctx.Doer)
1920
if err != nil {

routers/web/web.go

+2
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@ func registerRoutes(m *web.Router) {
677677
m.Post("", web.Bind(forms.BlockUserForm{}), user_setting.BlockedUsersPost)
678678
})
679679

680+
// BLENDER: spam reporting
680681
m.Post("/spamreport", user_setting.SpamReportUserPost)
681682
}, reqSignIn, ctxDataSet("PageIsUserSettings", true, "EnablePackages", setting.Packages.Enabled))
682683

@@ -750,6 +751,7 @@ func registerRoutes(m *web.Router) {
750751
m.Post("/delete", admin.DeleteEmail)
751752
})
752753

754+
// BLENDER: spam reporting
753755
m.Group("/spamreports", func() {
754756
m.Get("", admin.SpamReports)
755757
m.Post("", admin.SpamReportsPost)

services/cron/tasks_spamreport.go

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ func registerProcessSpamReports() {
1919
RunAtStart: true,
2020
Schedule: "@every 5m",
2121
}, func(ctx context.Context, doer *user_model.User, _ Config) error {
22+
// This code assumes that all reports may be processed.
23+
// If we start accepting reports from non-trusted users, we need to add a check here.
2224
ids, err := user_model.GetPendingSpamReportIDs(ctx)
2325
if err != nil {
2426
return fmt.Errorf("failed to GetPendingSpamReportIDs: %w", err)

services/user/spamreport.go

+27-4
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,13 @@ func IsTrustedUser(ctx context.Context, user *user_model.User) (bool, error) {
3131
}
3232

3333
// CreateSpamReport checks that a reporter can report a user,
34-
// and inserts a new record in default status=Pending
34+
// and inserts a new record in default status=pending
3535
// for further processing, either manual or automatical.
36+
//
37+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
38+
// !!! If you change this code to accept reports from non-trusted users, !!!
39+
// !!! make sure to update process_spam_reports cron task. !!!
40+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3641
func CreateSpamReport(ctx context.Context, reporter, user *user_model.User) error {
3742
reporterIsTrusted, err := IsTrustedUser(ctx, reporter)
3843
if err != nil {
@@ -54,7 +59,25 @@ func CreateSpamReport(ctx context.Context, reporter, user *user_model.User) erro
5459
})
5560
}
5661

57-
// ProcessSpamReports updates only reports in status "Pending" to avoid race conditions.
62+
// ProcessSpamReports performs the cleanup of a reported user account and the content it created.
63+
// Only the reports in "pending" status are processed to avoid race conditions.
64+
// A processed user account becomes inactive, restricted, login prohibited, profile fields erased,
65+
// and the following objects that were created by the user are deleted:
66+
// - issues and pulls
67+
// - comments
68+
// - personal repositories
69+
// - personal projects
70+
//
71+
// If the processing code fails it leaves the SpamReport record that was being processed in "locked" status.
72+
// It would need to be handled manually, as the error is assumed to be unrecoverable
73+
// (which may not always be true, e.g. during transient db downtime).
74+
//
75+
// We will have to revisit this approach if it actually causes problems.
76+
// E.g. we could
77+
// - either try to unlock the record on failure (this may not always be possible),
78+
// or unlock after some timeout (according to the record's UpdatedUnix)
79+
// - add a new field to keep track of an attempt count per record
80+
// - retry on subsequent runs, until the attempt budget is exhausted
5881
func ProcessSpamReports(ctx context.Context, doer *user_model.User, spamReportIDs []int64) error {
5982
var spamReports []user_model.SpamReport
6083
err := db.GetEngine(ctx).In("id", spamReportIDs).Find(&spamReports)
@@ -70,7 +93,7 @@ func ProcessSpamReports(ctx context.Context, doer *user_model.User, spamReportID
7093
return fmt.Errorf("failed to set SpamReport.Status to locked for id=%d: %w", id, err)
7194
}
7295
if count < 1 {
73-
log.Info("Skipping SpamReport id=%d, status wasn't Pending", id)
96+
log.Info("Skipping SpamReport id=%d, status wasn't pending", id)
7497
continue
7598
}
7699

@@ -170,7 +193,7 @@ func ProcessSpamReports(ctx context.Context, doer *user_model.User, spamReportID
170193
return nil
171194
}
172195

173-
// DismissSpamReports updates only reports in status "Pending" to avoid race conditions
196+
// DismissSpamReports updates only reports in "pending" status to avoid race conditions
174197
// with the actual processing.
175198
func DismissSpamReports(ctx context.Context, spamReportIDs []int64) error {
176199
_, err := db.GetEngine(ctx).In("id", spamReportIDs).

0 commit comments

Comments
 (0)