Skip to content

Commit 1276d00

Browse files
committed
perf(checker): use db queries to search for cheating
1 parent bff4289 commit 1276d00

File tree

3 files changed

+79
-75
lines changed

3 files changed

+79
-75
lines changed

cliff.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,13 @@ commit_parsers = [
6161
{ message = "^[fF]eat", group = "<!-- 0 -->⛰️ Features" },
6262
{ message = "^[fF]ix", group = "<!-- 1 -->🐛 Bug Fixes" },
6363
{ message = "^[sS]tyle", group = "<!-- 2 -->🎨 Styling" },
64+
{ message = "^[pP]erf", group = "<!-- 3 -->🚀 Performances" },
6465
{ message = "^[dD]oc", skip = true },
6566
{ message = "^[rR]elease", skip = true },
6667
{ message = "^[rR]evert", skip = true },
6768
{ message = "^[wW]ip", skip = true },
6869
{ message = "^[dD]eps", skip = true },
6970
{ message = "^[cC]hore", skip = true },
70-
{ body = ".*security", group = "<!-- 4 -->🛡️ Security" },
71+
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
7172
{ message = ".*", group = "<!-- 9 -->📦 Other Changes"}
7273
]

src/GZCTF/Repositories/GameInstanceRepository.cs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -227,29 +227,27 @@ public async Task<CheatCheckInfo> CheckCheat(Submission submission, Cancellation
227227
{
228228
CheatCheckInfo checkInfo = new();
229229

230-
GameInstance[] instances = await Context.GameInstances.Where(i => i.ChallengeId == submission.ChallengeId &&
231-
i.ParticipationId !=
232-
submission.ParticipationId)
233-
.Include(i => i.FlagContext).Include(i => i.Participation)
234-
.ThenInclude(i => i.Team).ToArrayAsync(token);
235-
236-
foreach (GameInstance instance in instances)
237-
{
238-
if (instance.FlagContext?.Flag != submission.Answer)
239-
continue;
230+
GameInstance? instance = await Context.GameInstances
231+
.Include(i => i.Participation)
232+
.ThenInclude(i => i.Team)
233+
.Include(i => i.FlagContext)
234+
.Where(i => i.ChallengeId == submission.ChallengeId &&
235+
i.ParticipationId != submission.ParticipationId &&
236+
i.FlagContext != null && i.FlagContext.Flag == submission.Answer)
237+
.FirstOrDefaultAsync(token);
240238

241-
Submission updateSub = await Context.Submissions.Where(s => s.Id == submission.Id).SingleAsync(token);
239+
if (instance is null)
240+
return checkInfo;
242241

243-
CheatInfo cheatInfo = await cheatInfoRepository.CreateCheatInfo(updateSub, instance, token);
242+
Submission updateSub = await Context.Submissions.Where(s => s.Id == submission.Id).SingleAsync(token);
244243

245-
checkInfo = CheatCheckInfo.FromCheatInfo(cheatInfo);
244+
CheatInfo cheatInfo = await cheatInfoRepository.CreateCheatInfo(updateSub, instance, token);
246245

247-
updateSub.Status = AnswerResult.CheatDetected;
246+
checkInfo = CheatCheckInfo.FromCheatInfo(cheatInfo);
248247

249-
await SaveAsync(token);
248+
updateSub.Status = AnswerResult.CheatDetected;
250249

251-
return checkInfo;
252-
}
250+
await SaveAsync(token);
253251

254252
return checkInfo;
255253
}
@@ -260,7 +258,8 @@ public async Task<VerifyResult> VerifyAnswer(Submission submission, Cancellation
260258

261259
try
262260
{
263-
GameInstance? instance = await Context.GameInstances.IgnoreAutoIncludes().Include(i => i.FlagContext)
261+
GameInstance? instance = await Context.GameInstances.IgnoreAutoIncludes()
262+
.Include(i => i.FlagContext)
264263
.SingleOrDefaultAsync(i => i.ChallengeId == submission.ChallengeId &&
265264
i.ParticipationId == submission.ParticipationId, token);
266265

src/GZCTF/Services/FlagChecker.cs

Lines changed: 60 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -79,66 +79,70 @@ async Task Checker(int id, CancellationToken token = default)
7979
{
8080
(SubmissionType type, AnswerResult ans) = await instanceRepository.VerifyAnswer(item, token);
8181

82-
if (ans == AnswerResult.NotFound)
82+
switch (ans)
8383
{
84-
logger.Log(
85-
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_UnknownInstance),
86-
item.Team.Name,
87-
item.GameChallenge.Title],
88-
item.User,
89-
TaskStatus.NotFound, LogLevel.Warning);
90-
}
91-
else if (ans == AnswerResult.Accepted)
92-
{
93-
logger.Log(
94-
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_AnswerAccepted),
95-
item.Team.Name,
96-
item.GameChallenge.Title,
97-
item.Answer],
98-
item.User, TaskStatus.Success, LogLevel.Information);
99-
100-
await eventRepository.AddEvent(
101-
GameEvent.FromSubmission(item, type, ans, Program.StaticLocalizer), token);
102-
103-
// only flush the scoreboard if the contest is not ended and the submission is accepted
104-
if (item.Game.EndTimeUtc > item.SubmitTimeUtc)
105-
await cacheHelper.FlushScoreboardCache(item.GameId, token);
106-
}
107-
else
108-
{
109-
logger.Log(
110-
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_AnswerRejected),
111-
item.Team.Name,
112-
item.GameChallenge.Title,
113-
item.Answer],
114-
item.User, TaskStatus.Failed, LogLevel.Information);
115-
116-
await eventRepository.AddEvent(
117-
GameEvent.FromSubmission(item, type, ans, Program.StaticLocalizer), token);
118-
119-
CheatCheckInfo result = await instanceRepository.CheckCheat(item, token);
120-
ans = result.AnswerResult;
121-
122-
if (ans == AnswerResult.CheatDetected)
123-
{
84+
case AnswerResult.NotFound:
12485
logger.Log(
125-
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_CheatDetected),
86+
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_UnknownInstance),
12687
item.Team.Name,
127-
item.GameChallenge.Title,
128-
result.SourceTeamName ?? ""],
129-
item.User, TaskStatus.Success, LogLevel.Information);
130-
131-
await eventRepository.AddEvent(
132-
new()
88+
item.GameChallenge.Title],
89+
item.User,
90+
TaskStatus.NotFound, LogLevel.Warning);
91+
break;
92+
case AnswerResult.Accepted:
93+
{
94+
logger.Log(
95+
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_AnswerAccepted),
96+
item.Team.Name,
97+
item.GameChallenge.Title,
98+
item.Answer],
99+
item.User, TaskStatus.Success, LogLevel.Information);
100+
101+
await eventRepository.AddEvent(
102+
GameEvent.FromSubmission(item, type, ans, Program.StaticLocalizer), token);
103+
104+
// only flush the scoreboard if the contest is not ended and the submission is accepted
105+
if (item.Game.EndTimeUtc > item.SubmitTimeUtc)
106+
await cacheHelper.FlushScoreboardCache(item.GameId, token);
107+
break;
108+
}
109+
default:
110+
{
111+
logger.Log(
112+
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_AnswerRejected),
113+
item.Team.Name,
114+
item.GameChallenge.Title,
115+
item.Answer],
116+
item.User, TaskStatus.Failed, LogLevel.Information);
117+
118+
await eventRepository.AddEvent(
119+
GameEvent.FromSubmission(item, type, ans, Program.StaticLocalizer), token);
120+
121+
CheatCheckInfo result = await instanceRepository.CheckCheat(item, token);
122+
ans = result.AnswerResult;
123+
124+
if (ans == AnswerResult.CheatDetected)
133125
{
134-
Type = EventType.CheatDetected,
135-
Values =
136-
[item.GameChallenge.Title, item.Team.Name, result.SourceTeamName ?? ""],
137-
TeamId = item.TeamId,
138-
UserId = item.UserId,
139-
GameId = item.GameId
140-
}, token);
141-
}
126+
logger.Log(
127+
Program.StaticLocalizer[nameof(Resources.Program.FlagChecker_CheatDetected),
128+
item.Team.Name,
129+
item.GameChallenge.Title,
130+
result.SourceTeamName ?? ""],
131+
item.User, TaskStatus.Success, LogLevel.Information);
132+
133+
await eventRepository.AddEvent(
134+
new()
135+
{
136+
Type = EventType.CheatDetected,
137+
Values =
138+
[item.GameChallenge.Title, item.Team.Name, result.SourceTeamName ?? ""],
139+
TeamId = item.TeamId,
140+
UserId = item.UserId,
141+
GameId = item.GameId
142+
}, token);
143+
}
144+
break;
145+
}
142146
}
143147

144148
if (item.Game.EndTimeUtc > DateTimeOffset.UtcNow

0 commit comments

Comments
 (0)