Skip to content
Open
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
10 changes: 8 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# WebHarbor — slim, self-contained image.
# 15 Flask mirror sites + control plane on :8101.
# 16 Flask mirror sites + control plane on :8101.

FROM python:3.12-slim-bookworm

Expand Down Expand Up @@ -28,11 +28,17 @@ WORKDIR /opt/WebSyn
# run scripts/fetch_assets.sh to pull them from Hugging Face first.
COPY sites/ /opt/WebSyn/

# Berkeley: all data is code-generated (no scraped images → no HF asset).
# Build the seed DB once at image-build time so websyn_start.sh can copy it on boot.
RUN cd /opt/WebSyn/berkeley && \
python3 -c "from app import app" && \
cp instance/berkeley.db instance_seed/berkeley.db

COPY websyn_start.sh /opt/websyn_start.sh
COPY control_server.py /opt/control_server.py
COPY site_runner.py /opt/site_runner.py
RUN chmod +x /opt/websyn_start.sh

EXPOSE 8101 40000-40014
EXPOSE 8101 40000-40015

CMD ["/opt/websyn_start.sh"]
2 changes: 1 addition & 1 deletion control_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
'allrecipes', 'amazon', 'apple', 'arxiv', 'bbc_news', 'booking',
'github', 'google_flights', 'google_map', 'google_search',
'huggingface', 'wolfram_alpha', 'cambridge_dictionary',
'coursera', 'espn',
'coursera', 'espn', 'berkeley',
]
BASE_PORT = 40000
WEBSYN_DIR = '/opt/WebSyn'
Expand Down
57 changes: 57 additions & 0 deletions sites/berkeley/_health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""UC Berkeley mirror health check."""
from healthcheck import random_user


def run(p):
# 1. Home page renders
p.assert_get('home', '/', must_contain='Berkeley')

# 2. News list renders
p.assert_get('news list', '/news', must_contain='article')

# 3. Programs list renders
p.assert_get('programs list', '/programs', must_contain='program')

# 4. Faculty list renders
p.assert_get('faculty list', '/faculty', must_contain='Professor')

# 5. Search returns results
p.assert_get('search', '/search?q=computer+science', must_contain='result')

# 6. Register page renders with CSRF
user = random_user()
html = p.assert_get('register page', '/register', must_contain='csrf_token')
token = p.csrf(html)
if not token:
p.check('register csrf token', False, 'no csrf in register form')
return

# 7. Submit registration
p.assert_post('register submit', '/register', {
'csrf_token': token,
'username': user['first_name'].lower() + user['last_name'].lower(),
'full_name': user['name'],
'email': user['email'],
'password': user['password'],
'confirm': user['password'],
}, accept_status=(200, 302, 303))

# Logout so login form is real
p.get('/logout')

# 8. Login page renders
html = p.assert_get('login page', '/login', accept_status=(200, 302, 303))
token = p.csrf(html) if html else ''

# 9. Submit login
if token:
p.assert_post('login submit', '/login', {
'csrf_token': token,
'email': user['email'],
'password': user['password'],
}, accept_status=(200, 302, 303))
else:
p.check('login submit', True, 'already authenticated from register')

# 10. Authenticated account page
p.assert_get('account page', '/account', must_contain=user['first_name'])
Loading