Skip to content

Commit 49ad8e3

Browse files
committed
Last fix before deployment
1 parent 2f6a7c9 commit 49ad8e3

File tree

2 files changed

+46
-57
lines changed

2 files changed

+46
-57
lines changed

checker/src/admin_simulator.py

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
import base64
88
import os
99
import re
10-
import os
11-
from playwright.async_api import async_playwright, Playwright, Browser, BrowserContext
12-
13-
_browsers: dict[int, dict[str, any]] = {}
1410

11+
try:
12+
from playwright.async_api import async_playwright
13+
PLAYWRIGHT_AVAILABLE = True
14+
except ImportError:
15+
PLAYWRIGHT_AVAILABLE = False
1516

1617
try:
1718
from cryptography.hazmat.primitives import serialization
@@ -29,14 +30,21 @@ def __init__(self, client: AsyncClient, logger: LoggerAdapter):
2930
self.admin_username = "admin"
3031
self.service_url = str(client.base_url)
3132

33+
def validate(self) -> None:
34+
if not PLAYWRIGHT_AVAILABLE:
35+
self.logger.warning("Playwright not available, skipping admin simulation")
36+
return
37+
38+
self.logger.info("Starting headless browser admin simulation...")
39+
3240
async def _solve_admin_challenge(self, encrypted_b64: str):
3341
if not CRYPTO_AVAILABLE:
34-
raise MumbleException("Cryptography package missing for admin challenge")
42+
raise MumbleException("cryptography package missing for admin challenge")
3543

3644
try:
3745
ciphertext = base64.b64decode(encrypted_b64)
3846
except Exception as e:
39-
raise MumbleException(f"Invalid base64 in challenge")
47+
raise MumbleException(f"Invalid base64 in challenge.")
4048

4149
pem_path = os.path.join(os.path.dirname(__file__), 'admin_private.pem')
4250
try:
@@ -60,6 +68,8 @@ async def _solve_admin_challenge(self, encrypted_b64: str):
6068

6169

6270
async def load_feedback_page(self) -> None:
71+
self.validate()
72+
6373
message_data = generate_admin_message()
6474
message_text = message_data["message"]
6575
message_year = message_data["year"]
@@ -84,7 +94,7 @@ async def load_feedback_page(self) -> None:
8494

8595
match = re.search(r'<pre[^>]*>(.*?)</pre>', response.text, re.DOTALL)
8696
if not match:
87-
raise MumbleException("Could not find encrypted challenge on page (please wrap it in <pre> tags)")
97+
raise MumbleException("Could not find encrypted challenge on page (please use <pre> tag)")
8898

8999
encrypted_b64 = match.group(1).strip()
90100

@@ -110,59 +120,36 @@ async def load_feedback_page(self) -> None:
110120
'secure': ck.secure
111121
})
112122

113-
browser = None
114-
context: Optional[BrowserContext] = None
115-
try:
116-
pid = os.getpid()
117-
entry = _browsers.get(pid)
118-
if not entry or not entry["browser"].is_connected():
119-
if entry:
120-
await entry["browser"].close()
121-
await entry["playwright"].stop()
122-
123-
p: Playwright = await async_playwright().start()
124-
b: Browser = await p.chromium.launch(
125-
headless=True,
126-
args=["--no-sandbox", "--disable-setuid-sandbox"]
127-
)
128-
_browsers[pid] = {"playwright": p, "browser": b}
129-
browser = _browsers[pid]["browser"]
130-
except Exception as e:
131-
if browser:
132-
await browser.close()
133-
if _browsers[pid]["playwright"]:
134-
await _browsers[pid]["playwright"].stop()
135-
if pid in _browsers:
136-
_browsers.pop(pid, None)
137-
raise MumbleException(f"checker's side (4)")
138-
139-
try:
140-
context: BrowserContext = await browser.new_context()
141-
await context.route("**/*", lambda route, request:
142-
route.abort() if request.resource_type in ("image", "stylesheet", "font")
143-
else route.continue_()
123+
async with async_playwright() as p:
124+
browser = await p.chromium.launch(
125+
headless=True,
126+
args=['--no-sandbox', '--disable-setuid-sandbox']
144127
)
145-
await context.add_cookies(cookies)
146-
page = await context.new_page()
147-
page.set_default_timeout(10_000)
148-
await page.goto(f"{self.service_url}/admin/feedback")
149-
await page.wait_for_url(f"{self.service_url}/admin/feedback", timeout=2000)
150-
151-
if "/admin/feedback" not in page.url:
152-
raise MumbleException(f"Admin was redirected to problems page - service unavailable")
153-
except Exception as e:
154-
if context:
155-
await context.close()
156-
if browser:
128+
129+
try:
130+
context = await browser.new_context()
131+
await context.add_cookies(cookies)
132+
133+
page = await context.new_page()
134+
135+
page.set_default_timeout(10000)
136+
137+
await page.goto(f"{self.service_url}/admin/feedback")
138+
139+
await page.wait_for_url(f"{self.service_url}/admin/feedback", timeout=2000)
140+
141+
if "/admin/feedback" not in page.url:
142+
raise MumbleException(f"Failed to load feedback page")
143+
144+
except Exception as e:
145+
self.logger.warning(f"Admin simulation failed: {e}")
146+
raise MumbleException(f"checker's side (4)")
147+
finally:
157148
await browser.close()
158-
if pid in _browsers:
159-
await _browsers[pid]["playwright"].stop()
160-
_browsers.pop(pid, None)
161-
raise MumbleException(f"checker's side (5)")
162-
else:
163-
await context.close()
164149

165150
async def post_new_message(self) -> None:
151+
self.validate()
152+
166153
message_data = generate_admin_message()
167154
message_text = message_data["message"]
168155
message_year = message_data["year"]
@@ -200,7 +187,7 @@ async def post_new_message(self) -> None:
200187
)
201188

202189
if response.status_code not in [200, 201, 302]:
203-
raise MumbleException(f"Failed to submit admin challenge solution.")
190+
raise MumbleException(f"Failed to submit admin challenge solution: {response.text}, {response.status_code}")
204191

205192
response = await self.client.post(
206193
"/admin/message",

service/docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ services:
2828
- SYS_ADMIN
2929
volumes:
3030
- submissions_data:/var/www/html/public/submissions
31+
mem_limit: 2g
32+
cpus: 2
3133

3234
database:
3335
image: postgres:${POSTGRES_VERSION:-16}-alpine

0 commit comments

Comments
 (0)