Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app/lib/admin/backend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -929,4 +929,16 @@ class AdminBackend {
_logger.info('Deleting moderated user: ${user.userId}');
}
}

/// Whether the [ModerationCase] has been appealed by [email] already.
Future<bool> isModerationCaseAppealedByEmail({
required String caseId,
required String email,
}) async {
final query = dbService.query<ModerationCase>()
..filter('appealedCaseId =', caseId);
final list = await query.run().toList();
final emails = list.map((mc) => mc.reporterEmail).toSet();
return emails.contains(email);
}
}
11 changes: 11 additions & 0 deletions app/lib/frontend/handlers/report.dart
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,17 @@ Future<Message> processReportPageHandler(

final isAppeal = form.caseId != null;

if (isAppeal) {
final appealExists = await adminBackend.isModerationCaseAppealedByEmail(
caseId: form.caseId!,
email: userEmail!,
);
if (appealExists) {
throw InvalidInputException(
'You have previously appealed this incident, we are unable to accept another appeal.');
}
}

bool isSubjectOwner = false;
if (user != null) {
if (subject.isPackage) {
Expand Down
20 changes: 19 additions & 1 deletion app/test/frontend/handlers/report_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,13 @@ void main() {
);
});

testWithProfile('unauthenticated appeal success', fn: () async {
testWithProfile('unauthenticated appeal success, second appeal fails',
fn: () async {
await _prepareApplied(
logSubject: 'package-version:oxygen/1.2.0',
);

// first report: success
await withHttpPubApiClient(
fn: (client) async {
final msg = await client.postReport(ReportForm(
Expand Down Expand Up @@ -396,6 +398,22 @@ void main() {
expect(mc.isSubjectOwner, false);
},
);

// second report: rejected
await withHttpPubApiClient(fn: (client) async {
await expectApiException(
client.postReport(ReportForm(
email: '[email protected]',
subject: 'package-version:oxygen/1.2.0',
caseId: 'case/1',
message: 'Huston, we have a problem.',
)),
code: 'InvalidInput',
status: 400,
message:
'You have previously appealed this incident, we are unable to accept another appeal.',
);
});
});

testWithProfile('authenticated appeal success', fn: () async {
Expand Down
Loading