chore(accounting): PR #622 nits — stray artifact, dedupe requireFlag, IMAP poll backoff
1. Remove the committed test artifact backend/storage/business-docs/quote/2026/ Q-2026-0001.pdf and gitignore backend/storage/business-docs/ so generated CRM docs can't be committed again. 2. adminLedger + adminExpenses dropped their local requireFlag copies and now import the shared (now cached) requireFeatureFlag middleware. 4. roundTripTest polls IMAP with ×1.5 backoff (cap 8s) instead of a flat 3s, so a 30s test takes ~5 SELECT/SEARCH locks not ~10 (some servers throttle). Nit 3 (dashboard + events pages still on the gallery-theme vars, not dark-mode- swapped) is left as a documented follow-up per the review.
This commit is contained in:
@@ -48,19 +48,11 @@ function diskUpload(subdir) {
|
||||
const inboundUpload = diskUpload('inbound');
|
||||
const proofUpload = diskUpload('expenses/proof');
|
||||
|
||||
function requireFlag(key, code) {
|
||||
return async (req, res, next) => {
|
||||
try {
|
||||
const row = await db('feature_flags').where({ key }).first();
|
||||
const enabled = row && (row.value === true || row.value === 1 || row.value === '1');
|
||||
if (!enabled) return res.status(403).json({ error: `${key} feature is disabled`, code });
|
||||
return next();
|
||||
} catch (err) { return next(err); }
|
||||
};
|
||||
}
|
||||
const requireIncoming = requireFlag('incomingInvoices', 'INCOMING_INVOICES_DISABLED');
|
||||
const requireExpenses = requireFlag('expenses', 'EXPENSES_DISABLED');
|
||||
const requireAccounting = requireFlag('accounting', 'ACCOUNTING_DISABLED');
|
||||
// Shared cached feature gate (PR #622 nit 2) — replaces the former local copy.
|
||||
const { requireFeatureFlag } = require('../middleware/requireFeatureFlag');
|
||||
const requireIncoming = requireFeatureFlag('incomingInvoices', 'INCOMING_INVOICES_DISABLED');
|
||||
const requireExpenses = requireFeatureFlag('expenses', 'EXPENSES_DISABLED');
|
||||
const requireAccounting = requireFeatureFlag('accounting', 'ACCOUNTING_DISABLED');
|
||||
|
||||
router.use(adminAuth);
|
||||
|
||||
|
||||
@@ -21,17 +21,9 @@ const ledgerService = require('../services/ledgerService');
|
||||
const router = express.Router();
|
||||
const toInt = (v) => { const n = parseInt(v, 10); return Number.isFinite(n) ? n : undefined; };
|
||||
|
||||
function requireFlag(key, code) {
|
||||
return async (req, res, next) => {
|
||||
try {
|
||||
const row = await db('feature_flags').where({ key }).first();
|
||||
const enabled = row && (row.value === true || row.value === 1 || row.value === '1');
|
||||
if (!enabled) return res.status(403).json({ error: `${key} feature is disabled`, code });
|
||||
return next();
|
||||
} catch (err) { return next(err); }
|
||||
};
|
||||
}
|
||||
const requireAccounting = requireFlag('accounting', 'ACCOUNTING_DISABLED');
|
||||
// Shared cached feature gate (PR #622 nit 2) — replaces the former local copy.
|
||||
const { requireFeatureFlag } = require('../middleware/requireFeatureFlag');
|
||||
const requireAccounting = requireFeatureFlag('accounting', 'ACCOUNTING_DISABLED');
|
||||
|
||||
router.use(adminAuth);
|
||||
router.use(requireAccounting);
|
||||
|
||||
@@ -202,6 +202,9 @@ async function roundTripTest({ timeoutMs = 30000, intervalMs = 3000 } = {}) {
|
||||
const client = makeImapClient(cfg);
|
||||
await connectWithTimeout(client);
|
||||
const started = Date.now();
|
||||
// Backoff (PR #622 nit 4): some IMAP servers throttle frequent SELECT/SEARCH.
|
||||
// Grow the gap ×1.5 (cap 8s) so a 30s test does ~5 polls, not ~10.
|
||||
let delay = intervalMs;
|
||||
try {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
@@ -219,7 +222,8 @@ async function roundTripTest({ timeoutMs = 30000, intervalMs = 3000 } = {}) {
|
||||
return { ok: false, sent: true, reason: 'not_received', recipient };
|
||||
}
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await new Promise((r) => setTimeout(r, intervalMs));
|
||||
await new Promise((r) => setTimeout(r, delay));
|
||||
delay = Math.min(Math.round(delay * 1.5), 8000);
|
||||
}
|
||||
} finally {
|
||||
await client.logout().catch(() => {});
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
pdf
|
||||
Reference in New Issue
Block a user