This commit is contained in:
2026-08-20 21:28:01 +02:00
parent 5f0d5c0e72
commit 5171669d4d
2 changed files with 190 additions and 183 deletions

View File

@@ -129,7 +129,10 @@ services:
context: ./scripts/social-worker context: ./scripts/social-worker
restart: unless-stopped restart: unless-stopped
environment: environment:
QRMASTER_API_BASE: http://web:3000 # Container name, not the `web` service alias: the staging stack joins this same
# external network and registers `web` as an alias too, so the alias can resolve
# to the staging app - which has a different INTERNAL_API_SECRET and answers 401.
QRMASTER_API_BASE: http://qrmaster-web:3000
INTERNAL_API_SECRET: ${INTERNAL_API_SECRET} INTERNAL_API_SECRET: ${INTERNAL_API_SECRET}
SOCIAL_MILESTONE_POSTING_ENABLED: ${SOCIAL_MILESTONE_POSTING_ENABLED:-false} SOCIAL_MILESTONE_POSTING_ENABLED: ${SOCIAL_MILESTONE_POSTING_ENABLED:-false}
SOCIAL_WORKER_INTERVAL_SECONDS: ${SOCIAL_WORKER_INTERVAL_SECONDS:-10} SOCIAL_WORKER_INTERVAL_SECONDS: ${SOCIAL_WORKER_INTERVAL_SECONDS:-10}

View File

@@ -5,9 +5,13 @@ import { isSocialChannel, SOCIAL_CHANNELS, SocialChannel } from '@/lib/social-mi
export const dynamic = 'force-dynamic'; export const dynamic = 'force-dynamic';
// The worker trims its own copy of the secret before sending it, so a stray
// trailing space or CR in the compose env file would otherwise show up here as a
// permanent 401 while both sides still look identical in a hash comparison.
function isAuthorized(request: NextRequest) { function isAuthorized(request: NextRequest) {
const secret = process.env.INTERNAL_API_SECRET; const secret = process.env.INTERNAL_API_SECRET?.trim();
return Boolean(secret) && request.headers.get('authorization') === `Bearer ${secret}`; const presented = request.headers.get('authorization')?.trim().replace(/^Bearer\s+/i, '');
return Boolean(secret) && presented === secret;
} }
function approvalDelayHours() { function approvalDelayHours() {