Skip to content

Commit c5341a0

Browse files
Merge pull request #74 from pomo-mondreganto/volga-mode
Add VolgaCTF-style attacks mode
2 parents e0536df + 1097dcb commit c5341a0

34 files changed

+91
-18
lines changed

backend/lib/helpers/exceptions.py

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ class FlagExceptionEnum:
88
FLAG_TOO_OLD = FlagSubmitException('Flag is too old')
99
FLAG_YOUR_OWN = FlagSubmitException('Flag is your own')
1010
FLAG_ALREADY_STOLEN = FlagSubmitException('Flag already stolen')
11+
SERVICE_IS_DOWN = FlagSubmitException('Cannot submit flags while service is down')

backend/lib/models/game_config.py

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class GameConfig(BaseModel):
1313
flag_lifetime: int
1414
game_hardness: float
1515
inflation: bool
16+
volga_attacks_mode: bool
17+
1618
round_time: int
1719
mode: str
1820
timezone: str
@@ -28,6 +30,7 @@ class GameConfig(BaseModel):
2830
'flag_lifetime',
2931
'game_hardness',
3032
'inflation',
33+
'volga_attacks_mode',
3134
'round_time',
3235
'mode',
3336
'timezone',

backend/lib/storage/attacks.py

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from lib import models, storage
22
from lib.helpers import exceptions
33
from lib.helpers.exceptions import FlagExceptionEnum
4+
from lib.models.types import TaskStatus
45
from lib.storage import utils, game
56
from lib.storage.keys import CacheKeys
67

@@ -47,6 +48,15 @@ def handle_attack(
4748
if current_round - flag.round > game_config.flag_lifetime:
4849
raise FlagExceptionEnum.FLAG_TOO_OLD
4950

51+
if game_config.volga_attacks_mode:
52+
teamtask = storage.tasks.get_latest_teamtask(
53+
team_id=attacker_id,
54+
task_id=flag.task_id,
55+
)
56+
# Status is a string from redis stream.
57+
if not teamtask or teamtask['status'] != str(TaskStatus.UP.value):
58+
raise FlagExceptionEnum.SERVICE_IS_DOWN
59+
5060
result.victim_id = flag.team_id
5161
result.task_id = flag.task_id
5262
success = storage.flags.try_add_stolen_flag(

backend/lib/storage/tasks.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List
1+
from typing import List, Optional
22

33
from lib import models, storage
44
from lib.helpers.cache import cache_helper
@@ -187,6 +187,20 @@ def get_teamtasks_for_team(team_id: int) -> List[dict]:
187187
return results
188188

189189

190+
def get_latest_teamtask(team_id: int, task_id: int) -> Optional[dict]:
191+
"""Fetch the latest teamtask from redis stream."""
192+
193+
with storage.utils.redis_pipeline(transaction=False) as pipe:
194+
data, = pipe.xrevrange(CacheKeys.teamtasks(team_id, task_id), count=1).execute()
195+
196+
results = []
197+
for timestamp, record in data:
198+
record['timestamp'] = timestamp
199+
results.append(record)
200+
201+
return results[0] if results else None
202+
203+
190204
def filter_teamtasks_for_participants(teamtasks: List[dict]) -> List[dict]:
191205
"""
192206
Filter sensitive data from teamtasks.

backend/scripts/create_tables.sql

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
CREATE TABLE IF NOT EXISTS GameConfig
22
(
3-
id SERIAL PRIMARY KEY,
4-
game_running BOOLEAN DEFAULT FALSE,
5-
real_round INTEGER DEFAULT 0,
6-
flag_lifetime INTEGER CHECK ( flag_lifetime > 0 ),
7-
game_hardness FLOAT CHECK ( game_hardness >= 1 ),
8-
inflation BOOLEAN,
9-
round_time INTEGER CHECK ( round_time > 0 ),
10-
mode VARCHAR(8) DEFAULT 'classic',
11-
timezone VARCHAR(32) DEFAULT 'UTC',
12-
start_time TIMESTAMP WITH TIME ZONE
3+
id SERIAL PRIMARY KEY,
4+
game_running BOOLEAN DEFAULT FALSE,
5+
real_round INTEGER DEFAULT 0,
6+
flag_lifetime INTEGER CHECK ( flag_lifetime > 0 ),
7+
game_hardness FLOAT CHECK ( game_hardness >= 1 ),
8+
inflation BOOLEAN,
9+
volga_attacks_mode BOOLEAN,
10+
round_time INTEGER CHECK ( round_time > 0 ),
11+
mode VARCHAR(8) DEFAULT 'classic',
12+
timezone VARCHAR(32) DEFAULT 'UTC',
13+
start_time TIMESTAMP WITH TIME ZONE
1314
);
1415

1516
CREATE TABLE IF NOT EXISTS Teams

backend/services/tasks/handlers.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List
1+
from typing import List, Union
22

33
from celery import shared_task
44
from celery.result import AsyncResult
@@ -52,7 +52,7 @@ def exception_callback(result: AsyncResult, exc: Exception, traceback: str) -> N
5252

5353
@shared_task(name=JobNames.result_handler)
5454
def checker_results_handler(
55-
verdicts: List[models.CheckerVerdict],
55+
verdicts: Union[List[models.CheckerVerdict], models.CheckerVerdict],
5656
team: models.Team,
5757
task: models.Task,
5858
current_round: int,
@@ -63,6 +63,12 @@ def checker_results_handler(
6363
If there were any errors, the first error is returned
6464
Otherwise, verdict of the first action's verdict is returned.
6565
"""
66+
67+
# Celery passes the one-task-group's result (e.g. a group of a single put)
68+
# as the result itself, not the list, as documented.
69+
if not isinstance(verdicts, list):
70+
verdicts = [verdicts]
71+
6672
check_verdict = None
6773
puts_verdicts = []
6874
gets_verdict = None

cli/models.py

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class GameConfig(BaseModel):
4949
mode: str = 'classic'
5050
get_period: Optional[int]
5151
inflation: bool = True
52+
volga_attacks_mode: bool = False
5253

5354
checkers_path: str = '/checkers/'
5455
env_path: str = ''

control.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env python
1+
#!/usr/bin/env python3
22

33
from cli import cli
44

front/dist/assets/AdminLogin.c88c2238.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.create-group[data-v-27ed27a5]{display:flex;flex-flow:row-reverse}.create-btn[data-v-27ed27a5]{font-size:1em;margin:1em}

front/dist/assets/AdminScoreboard.418e3b89.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/dist/assets/AdminTeamTaskLog.28ea2a2d.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/dist/assets/AdminTeamTaskLog.df0c41b4.css

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.error-message[data-v-671fbd7e]{color:red}

front/dist/assets/ErrorBox.e64f7274.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/dist/assets/FormWrapper.0c67122c.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.error-message[data-v-324400ce]{color:red}

front/dist/assets/LiveScoreboard.aff16f9d.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/dist/assets/LiveScoreboard.d846ad37.css

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/dist/assets/ScoreTable.c4b535fd.css

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)