fix: support scoped RomM API token for scan trigger

This commit is contained in:
2026-06-26 05:30:41 +00:00
parent b2079446e5
commit dd6dbb457e
3 changed files with 27 additions and 3 deletions

View File

@@ -40,6 +40,7 @@ QUIET_IDLE = os.environ.get("IMPORT_QUIET_IDLE", "true").lower() in {"1", "true"
ROMM_SERVER_URL = os.environ.get("ROMM_SERVER_URL", "").rstrip("/")
ROMM_USERNAME = os.environ.get("ROMM_USERNAME", "")
ROMM_PASSWORD = os.environ.get("ROMM_PASSWORD", "")
ROMM_API_TOKEN = os.environ.get("ROMM_API_TOKEN", "")
IGNORE_SUFFIXES = {".part", ".partial", ".tmp", ".crdownload"}
@@ -190,8 +191,19 @@ def quarantine(path: Path, reason: str) -> None:
def romm_token() -> str:
"""Return a RomM bearer token for task calls.
Prefer ROMM_API_TOKEN because RomM task execution requires the tasks.run
scope. Username/password logins can authenticate successfully while still
lacking that scope, which causes HTTP 403 on /api/tasks/run/scan_library.
"""
if ROMM_API_TOKEN:
return ROMM_API_TOKEN
if not (ROMM_SERVER_URL and ROMM_USERNAME and ROMM_PASSWORD):
raise RuntimeError("ROMM_SERVER_URL, ROMM_USERNAME, and ROMM_PASSWORD are required for scan trigger")
raise RuntimeError(
"ROMM_SERVER_URL plus either ROMM_API_TOKEN or ROMM_USERNAME/ROMM_PASSWORD are required for scan trigger"
)
data = parse.urlencode({"username": ROMM_USERNAME, "password": ROMM_PASSWORD}).encode()
req = request.Request(
f"{ROMM_SERVER_URL}/api/token",
@@ -223,6 +235,12 @@ def trigger_romm_scan() -> None:
log(f"triggered RomM scan_library: HTTP {resp.status} {body[:300]}")
except error.HTTPError as exc:
body = exc.read().decode("utf-8", errors="replace")
if exc.code == 403:
raise RuntimeError(
"RomM scan trigger failed: HTTP 403 Forbidden. The RomM credential/token can log in, "
"but it does not have the tasks.run scope required to run scan_library. "
"Create a RomM API token with Run tasks/tasks.run permission and set ROMM_API_TOKEN."
) from exc
raise RuntimeError(f"RomM scan trigger failed: HTTP {exc.code} {body}") from exc

View File

@@ -177,8 +177,9 @@ services:
environment:
TZ: ${TZ:-America/Chicago}
ROMM_SERVER_URL: ${ROMM_SERVER_URL:?set ROMM_SERVER_URL in .env}
ROMM_USERNAME: ${ROMM_USERNAME:?set ROMM_USERNAME in .env}
ROMM_PASSWORD: ${ROMM_PASSWORD:?set ROMM_PASSWORD in .env}
ROMM_USERNAME: ${ROMM_USERNAME:-}
ROMM_PASSWORD: ${ROMM_PASSWORD:-}
ROMM_API_TOKEN: ${ROMM_API_TOKEN:-}
ROMM_SCAN_AFTER_IMPORT: ${ROMM_SCAN_AFTER_IMPORT:-true}
IMPORT_POLL_SECONDS: ${IMPORT_POLL_SECONDS:-60}
IMPORT_QUIET_IDLE: ${IMPORT_QUIET_IDLE:-true}

View File

@@ -60,6 +60,11 @@ IGDB_CLIENT_SECRET=fill_me
ROMM_SERVER_URL=http://your-romm-host:port
ROMM_USERNAME=fill_me
ROMM_PASSWORD=fill_me
# Optional but recommended for the import worker scan trigger. Create a RomM API
# token with the Run tasks / tasks.run permission and paste it in the real env.
# Username/password may pass basic library checks but still receive HTTP 403 when
# trying to run /api/tasks/run/scan_library without this scope.
ROMM_API_TOKEN=
# Romarr image. Upstream docs list romarr/romarr:latest, but the public image was not pullable
# when this scaffold was created. Override this if we build/publish a local image.