fix: extract softAuth to shared module and apply to icon_sets router
Move the softAuth middleware from devices.js into a new shared lib/api/soft_auth.js module. Apply router.use(softAuth) and router.use(errorMiddleware) to icon_sets.js so that POST/DELETE owner-only routes return 401 (not 500) when no auth is present. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,32 +5,9 @@ import { requireOwner } from '../cap.js';
|
||||
import { validate } from '../validate.js';
|
||||
import * as devices from '../../db/repos/lan_devices.js';
|
||||
import { isRandomizedMac } from '../../infra/scan.js';
|
||||
import * as agents from '../../db/repos/agents.js';
|
||||
import { timingSafeStrEqual } from '../../auth/safe_compare.js';
|
||||
import { accessOwnerEmail } from '../../auth/cf_access.js';
|
||||
import { softAuth } from '../soft_auth.js';
|
||||
|
||||
export const router = Router();
|
||||
|
||||
// Soft auth: identifies the actor if auth is present but never blocks the request.
|
||||
// Owner-only sub-routes enforce 401/403 via requireOwner.
|
||||
async function softAuth(req, _res, next) {
|
||||
try {
|
||||
const cfEmail = await accessOwnerEmail(req);
|
||||
if (cfEmail) { req.actor = { kind: 'user', id: null }; return next(); }
|
||||
const auth = req.headers.authorization || '';
|
||||
const [scheme, token] = auth.split(' ');
|
||||
if (scheme === 'Bearer' && token) {
|
||||
if (process.env.OWNER_TOKEN && timingSafeStrEqual(token, process.env.OWNER_TOKEN)) {
|
||||
req.actor = { kind: 'user', id: null }; return next();
|
||||
}
|
||||
try {
|
||||
const agent = await agents.verifyToken(token);
|
||||
if (agent) req.actor = { kind: 'agent', id: agent.id, capabilities: agent.capabilities || {}, scopes: agent.scopes || {} };
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
next();
|
||||
}
|
||||
const GROUP_ORDER = ['Smart Home', 'Entertainment', 'Personal', 'Network', 'Flagged'];
|
||||
|
||||
router.use(softAuth);
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
import { Router } from 'express';
|
||||
import multer from 'multer';
|
||||
import { requireOwner } from '../cap.js';
|
||||
import { asyncWrap } from '../errors.js';
|
||||
import { asyncWrap, errorMiddleware } from '../errors.js';
|
||||
import { softAuth } from '../soft_auth.js';
|
||||
import * as sets from '../../icons/sets.js';
|
||||
import { processFile, unpackZip, fetchUrl, isZip } from '../../icons/ingest.js';
|
||||
|
||||
export const router = Router();
|
||||
router.use(softAuth);
|
||||
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 6 * 1024 * 1024, files: 50 } });
|
||||
|
||||
// GET /api/icon-sets — list sets + their icons (open; <img> can't send bearer).
|
||||
@@ -49,3 +51,5 @@ router.delete('/:set', requireOwner, asyncWrap(async (req, res) => {
|
||||
catch (e) { return res.status(e.message === 'reserved_set' ? 409 : 400).json({ error: { code: e.message } }); }
|
||||
res.json({ ok: true });
|
||||
}));
|
||||
|
||||
router.use(errorMiddleware);
|
||||
|
||||
25
lib/api/soft_auth.js
Normal file
25
lib/api/soft_auth.js
Normal file
@@ -0,0 +1,25 @@
|
||||
// lib/api/soft_auth.js — shared middleware
|
||||
// Soft auth: identifies the actor if auth is present but never blocks the request.
|
||||
// Owner-only sub-routes enforce 401/403 via requireOwner.
|
||||
import * as agents from '../db/repos/agents.js';
|
||||
import { timingSafeStrEqual } from '../auth/safe_compare.js';
|
||||
import { accessOwnerEmail } from '../auth/cf_access.js';
|
||||
|
||||
export async function softAuth(req, _res, next) {
|
||||
try {
|
||||
const cfEmail = await accessOwnerEmail(req);
|
||||
if (cfEmail) { req.actor = { kind: 'user', id: null }; return next(); }
|
||||
const auth = req.headers.authorization || '';
|
||||
const [scheme, token] = auth.split(' ');
|
||||
if (scheme === 'Bearer' && token) {
|
||||
if (process.env.OWNER_TOKEN && timingSafeStrEqual(token, process.env.OWNER_TOKEN)) {
|
||||
req.actor = { kind: 'user', id: null }; return next();
|
||||
}
|
||||
try {
|
||||
const agent = await agents.verifyToken(token);
|
||||
if (agent) req.actor = { kind: 'agent', id: agent.id, capabilities: agent.capabilities || {}, scopes: agent.scopes || {} };
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
next();
|
||||
}
|
||||
Reference in New Issue
Block a user