@@ -31,8 +31,13 @@ func IsTrustedUser(ctx context.Context, user *user_model.User) (bool, error) {
31
31
}
32
32
33
33
// 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
35
35
// 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
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
36
41
func CreateSpamReport (ctx context.Context , reporter , user * user_model.User ) error {
37
42
reporterIsTrusted , err := IsTrustedUser (ctx , reporter )
38
43
if err != nil {
@@ -54,7 +59,25 @@ func CreateSpamReport(ctx context.Context, reporter, user *user_model.User) erro
54
59
})
55
60
}
56
61
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
58
81
func ProcessSpamReports (ctx context.Context , doer * user_model.User , spamReportIDs []int64 ) error {
59
82
var spamReports []user_model.SpamReport
60
83
err := db .GetEngine (ctx ).In ("id" , spamReportIDs ).Find (& spamReports )
@@ -70,7 +93,7 @@ func ProcessSpamReports(ctx context.Context, doer *user_model.User, spamReportID
70
93
return fmt .Errorf ("failed to set SpamReport.Status to locked for id=%d: %w" , id , err )
71
94
}
72
95
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 )
74
97
continue
75
98
}
76
99
@@ -170,7 +193,7 @@ func ProcessSpamReports(ctx context.Context, doer *user_model.User, spamReportID
170
193
return nil
171
194
}
172
195
173
- // DismissSpamReports updates only reports in status "Pending" to avoid race conditions
196
+ // DismissSpamReports updates only reports in "pending" status to avoid race conditions
174
197
// with the actual processing.
175
198
func DismissSpamReports (ctx context.Context , spamReportIDs []int64 ) error {
176
199
_ , err := db .GetEngine (ctx ).In ("id" , spamReportIDs ).
0 commit comments