feat: add internal API key bypass for service-to-service calls
Allows trusted internal services (e.g. rnotes) to push shapes without EncryptID auth by passing X-Internal-Key header. Key is set via INTERNAL_API_KEY env var. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3a04416b10
commit
6db71abef9
|
|
@ -11,6 +11,7 @@ services:
|
|||
- NODE_ENV=production
|
||||
- STORAGE_DIR=/data/communities
|
||||
- PORT=3000
|
||||
- INTERNAL_API_KEY=${INTERNAL_API_KEY}
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# Only handle subdomains (rspace-prod handles main domain)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ async function getSpaceConfig(slug: string): Promise<SpaceAuthConfig | null> {
|
|||
}
|
||||
|
||||
const PORT = Number(process.env.PORT) || 3000;
|
||||
const INTERNAL_API_KEY = process.env.INTERNAL_API_KEY || "";
|
||||
const DIST_DIR = resolve(import.meta.dir, "../dist");
|
||||
|
||||
// WebSocket data type
|
||||
|
|
@ -486,24 +487,30 @@ async function handleAPI(req: Request, url: URL): Promise<Response> {
|
|||
) {
|
||||
const slug = url.pathname.split("/")[3];
|
||||
|
||||
// Check space access (write required)
|
||||
const token = extractToken(req.headers);
|
||||
const access = await evaluateSpaceAccess(slug, token, req.method, {
|
||||
getSpaceConfig,
|
||||
});
|
||||
// Allow internal service-to-service calls with shared key
|
||||
const internalKey = req.headers.get("X-Internal-Key");
|
||||
const isInternalCall = INTERNAL_API_KEY && internalKey === INTERNAL_API_KEY;
|
||||
|
||||
if (!access.allowed) {
|
||||
return Response.json(
|
||||
{ error: access.reason },
|
||||
{ status: access.claims ? 403 : 401, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
if (!isInternalCall) {
|
||||
// Check space access (write required) for external calls
|
||||
const token = extractToken(req.headers);
|
||||
const access = await evaluateSpaceAccess(slug, token, req.method, {
|
||||
getSpaceConfig,
|
||||
});
|
||||
|
||||
if (access.readOnly) {
|
||||
return Response.json(
|
||||
{ error: "Write access required to add shapes" },
|
||||
{ status: 403, headers: corsHeaders }
|
||||
);
|
||||
if (!access.allowed) {
|
||||
return Response.json(
|
||||
{ error: access.reason },
|
||||
{ status: access.claims ? 403 : 401, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
if (access.readOnly) {
|
||||
return Response.json(
|
||||
{ error: "Write access required to add shapes" },
|
||||
{ status: 403, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue