Skip to content

Commit e8a7370

Browse files
authored
Merge pull request #3740 from rommapp/posthog-code/screenscraper-dev-creds-build-time
feat: inject ScreenScraper dev credentials at build time
2 parents bf3366f + 355ee14 commit e8a7370

8 files changed

Lines changed: 41 additions & 24 deletions

File tree

.github/workflows/build.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ jobs:
115115
tags: ${{ steps.meta-slim.outputs.tags }}
116116
labels: ${{ steps.meta-slim.outputs.labels }}
117117
target: slim-image
118+
build-args: |
119+
SCREENSCRAPER_DEV_ID=${{ secrets.SCREENSCRAPER_DEV_ID }}
120+
SCREENSCRAPER_DEV_PASSWORD=${{ secrets.SCREENSCRAPER_DEV_PASSWORD }}
118121
119122
- name: Build full image
120123
id: build-full
@@ -127,6 +130,9 @@ jobs:
127130
tags: ${{ steps.meta.outputs.tags }}
128131
labels: ${{ steps.meta.outputs.labels }}
129132
target: full-image
133+
build-args: |
134+
SCREENSCRAPER_DEV_ID=${{ secrets.SCREENSCRAPER_DEV_ID }}
135+
SCREENSCRAPER_DEV_PASSWORD=${{ secrets.SCREENSCRAPER_DEV_PASSWORD }}
130136
131137
trigger-docs-and-web:
132138
permissions:

.github/workflows/test-build.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ jobs:
107107
platforms: linux/arm64,linux/amd64
108108
tags: ${{ steps.meta.outputs.tags }}
109109
target: full-image
110+
build-args: |
111+
SCREENSCRAPER_DEV_ID=${{ secrets.SCREENSCRAPER_DEV_ID }}
112+
SCREENSCRAPER_DEV_PASSWORD=${{ secrets.SCREENSCRAPER_DEV_PASSWORD }}
110113
111114
# PR builds always push to GHCR only, so the image link is hardcoded to GHCR.
112115
- name: Comment PR with GHCR image link

backend/adapters/services/screenscraper.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import asyncio
2-
import base64
32
import http
43
import json
54
from typing import Final, cast
@@ -10,14 +9,17 @@
109
from fastapi import HTTPException, status
1110

1211
from adapters.services.screenscraper_types import SSGame
13-
from config import SCREENSCRAPER_PASSWORD, SCREENSCRAPER_USER
12+
from config import (
13+
SCREENSCRAPER_DEV_ID,
14+
SCREENSCRAPER_DEV_PASSWORD,
15+
SCREENSCRAPER_PASSWORD,
16+
SCREENSCRAPER_USER,
17+
)
1418
from logger.logger import log
1519
from utils import get_version
1620
from utils.context import ctx_aiohttp_session
1721
from utils.rate_limiter import ConcurrencyLimiter
1822

19-
SS_DEV_ID: Final = base64.b64decode("enVyZGkxNQ==").decode()
20-
SS_DEV_PASSWORD: Final = base64.b64decode("eFRKd29PRmpPUUc=").decode()
2123
LOGIN_ERROR_CHECK: Final = "Erreur de login"
2224

2325
# ScreenScraper enforces a per-account *thread* (concurrency) cap rather than a
@@ -82,8 +84,8 @@ async def auth_middleware(
8284
"""ScreenScraper API authentication mechanism."""
8385
req.url = req.url.update_query(
8486
{
85-
"devid": SS_DEV_ID,
86-
"devpassword": SS_DEV_PASSWORD,
87+
"devid": SCREENSCRAPER_DEV_ID or "",
88+
"devpassword": SCREENSCRAPER_DEV_PASSWORD or "",
8789
"output": "json",
8890
"softname": "romm",
8991
"ssid": SCREENSCRAPER_USER or "",

backend/config/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ def _get_env(var: str, fallback: str | None = None) -> str | None:
8989
# SCREENSCRAPER
9090
SCREENSCRAPER_USER: Final[str | None] = _get_env("SCREENSCRAPER_USER")
9191
SCREENSCRAPER_PASSWORD: Final[str | None] = _get_env("SCREENSCRAPER_PASSWORD")
92+
# Developer credentials, injected at build time.
93+
SCREENSCRAPER_DEV_ID: Final[str | None] = _get_env("SCREENSCRAPER_DEV_ID")
94+
SCREENSCRAPER_DEV_PASSWORD: Final[str | None] = _get_env("SCREENSCRAPER_DEV_PASSWORD")
9295

9396
# STEAMGRIDDB
9497
STEAMGRIDDB_API_KEY: Final[str | None] = _get_env("STEAMGRIDDB_API_KEY")

backend/tests/adapters/services/test_screenscraper.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import asyncio
2-
import base64
32
import http
43
import json
54
from unittest.mock import AsyncMock, MagicMock, patch
@@ -11,8 +10,6 @@
1110

1211
from adapters.services.screenscraper import (
1312
LOGIN_ERROR_CHECK,
14-
SS_DEV_ID,
15-
SS_DEV_PASSWORD,
1613
ScreenScraperService,
1714
auth_middleware,
1815
is_daily_quota_exhausted,
@@ -26,22 +23,14 @@
2623
class TestScreenScraperConstants:
2724
"""Test ScreenScraper constants and configuration."""
2825

29-
def test_ss_dev_id_decoded(self):
30-
"""Test that SS_DEV_ID is properly decoded."""
31-
expected = base64.b64decode("enVyZGkxNQ==").decode()
32-
assert SS_DEV_ID == expected
33-
34-
def test_ss_dev_password_decoded(self):
35-
"""Test that SS_DEV_PASSWORD is properly decoded."""
36-
expected = base64.b64decode("eFRKd29PRmpPUUc=").decode()
37-
assert SS_DEV_PASSWORD == expected
38-
3926
def test_login_error_check_constant(self):
4027
"""Test that LOGIN_ERROR_CHECK constant is defined."""
4128
assert LOGIN_ERROR_CHECK == "Erreur de login"
4229

4330

4431
class TestAuthMiddleware:
32+
@patch("adapters.services.screenscraper.SCREENSCRAPER_DEV_ID", "dev_id")
33+
@patch("adapters.services.screenscraper.SCREENSCRAPER_DEV_PASSWORD", "dev_pass")
4534
@patch("adapters.services.screenscraper.SCREENSCRAPER_USER", "test_user")
4635
@patch("adapters.services.screenscraper.SCREENSCRAPER_PASSWORD", "test_pass")
4736
@pytest.mark.asyncio
@@ -59,8 +48,8 @@ async def test_auth_middleware_adds_auth_params(self):
5948

6049
# Check that the URL now contains all auth parameters
6150
expected_params = {
62-
"devid": SS_DEV_ID,
63-
"devpassword": SS_DEV_PASSWORD,
51+
"devid": "dev_id",
52+
"devpassword": "dev_pass",
6453
"output": "json",
6554
"softname": "romm",
6655
"ssid": "test_user",
@@ -73,6 +62,8 @@ async def test_auth_middleware_adds_auth_params(self):
7362
mock_handler.assert_called_once_with(mock_request)
7463
assert result == mock_response
7564

65+
@patch("adapters.services.screenscraper.SCREENSCRAPER_DEV_ID", None)
66+
@patch("adapters.services.screenscraper.SCREENSCRAPER_DEV_PASSWORD", None)
7667
@patch("adapters.services.screenscraper.SCREENSCRAPER_USER", "")
7768
@patch("adapters.services.screenscraper.SCREENSCRAPER_PASSWORD", "")
7869
@pytest.mark.asyncio
@@ -88,8 +79,8 @@ async def test_auth_middleware_with_empty_credentials(self):
8879
result = await auth_middleware(mock_request, mock_handler)
8980

9081
expected_params = {
91-
"devid": SS_DEV_ID,
92-
"devpassword": SS_DEV_PASSWORD,
82+
"devid": "",
83+
"devpassword": "",
9384
"output": "json",
9485
"softname": "romm",
9586
"ssid": "",

docker/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ COPY --from=backend-build /src/.venv /src/.venv
224224

225225
ENV PATH="/src/.venv/bin:${PATH}"
226226

227+
# ScreenScraper developer (application) credentials, injected at build time from
228+
# CI secrets. Kept out of the source tree; empty when not supplied at build.
229+
ARG SCREENSCRAPER_DEV_ID
230+
ARG SCREENSCRAPER_DEV_PASSWORD
231+
ENV SCREENSCRAPER_DEV_ID=${SCREENSCRAPER_DEV_ID}
232+
ENV SCREENSCRAPER_DEV_PASSWORD=${SCREENSCRAPER_DEV_PASSWORD}
233+
227234
# Security: Set security-focused environment variables
228235
ENV PYTHONDONTWRITEBYTECODE=1
229236
ENV PYTHONUNBUFFERED=1

docker/build_local_image.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
branch_name="$(git symbolic-ref HEAD 2>/dev/null)"
44
branch_name=${branch_name##refs/heads/}
55
branch_name=${branch_name//\//-} # Replace slashes with dashes
6-
docker build -t "rommapp/romm-testing:local-${branch_name}" . --file ./docker/Dockerfile
6+
docker build -t "rommapp/romm-testing:local-${branch_name}" . --file ./docker/Dockerfile \
7+
--build-arg "SCREENSCRAPER_DEV_ID=${SCREENSCRAPER_DEV_ID}" \
8+
--build-arg "SCREENSCRAPER_DEV_PASSWORD=${SCREENSCRAPER_DEV_PASSWORD}"

env.template

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ HASHEOUS_API_ENABLED=false # Enable Hasheous API integration
6969
FLASHPOINT_API_ENABLED=false # Enable Flashpoint API integration
7070
HLTB_API_ENABLED=false # Enable HowLongToBeat API integration
7171
TGDB_API_ENABLED=false # Enable TheGamesDB API integration
72+
# Only use when building your own image or running from source
73+
# SCREENSCRAPER_DEV_ID=
74+
# SCREENSCRAPER_DEV_PASSWORD=
7275

7376
# Scans & Tasks
7477
SCAN_TIMEOUT=14400 # Timeout for background scan/rescan tasks in seconds

0 commit comments

Comments
 (0)