diff --git a/public/js/logs.js b/public/js/logs.js
index 2e0a92c..374c46e 100644
--- a/public/js/logs.js
+++ b/public/js/logs.js
@@ -20,6 +20,7 @@
if (!res.ok) throw new Error(await res.text());
const logs = await res.json();
+ console.log(logs);
if (logs.length === 0) {
tbody.innerHTML = '
| No logs found |
';
diff --git a/src/middleware/authCheck.js b/src/middleware/authCheck.js
new file mode 100644
index 0000000..4660673
--- /dev/null
+++ b/src/middleware/authCheck.js
@@ -0,0 +1,86 @@
+// middleware/authCheck.js
+const fetch = require("node-fetch");
+
+const VERIFY_URL = process.env.AUTH_VERIFY;
+const CACHE_TTL = parseInt(process.env.AUTH_CACHE_TTL) || 120000; // 2 minutes default
+
+// Simple in-memory cache
+const authCache = new Map();
+
+// Helper to generate cache key
+function getCacheKey(cookie, authHeader) {
+ return `${cookie}:${authHeader}`;
+}
+
+// Helper to check if cache entry is valid
+function isCacheValid(entry) {
+ return entry && Date.now() - entry.timestamp < CACHE_TTL;
+}
+
+// Clean expired cache entries periodically
+setInterval(() => {
+ const now = Date.now();
+ for (const [key, entry] of authCache.entries()) {
+ if (now - entry.timestamp >= CACHE_TTL) {
+ authCache.delete(key);
+ }
+ }
+}, CACHE_TTL); // Clean up when entries would expire
+
+module.exports = async (req, res, next) => {
+ const cookie = req.headers["cookie"] || "";
+ const authHeader = req.headers["authorization"] || "";
+ const cacheKey = getCacheKey(cookie, authHeader);
+
+ // Check cache first
+ const cached = authCache.get(cacheKey);
+ if (isCacheValid(cached)) {
+ req.isAuthenticated = cached.isAuthenticated;
+ return next();
+ }
+
+ // Default to unauthenticated
+ req.isAuthenticated = false;
+
+ try {
+ const controller = new AbortController();
+ const timeout = setTimeout(() => controller.abort(), 5000); // 5 second timeout
+
+ const resVerify = await fetch(VERIFY_URL, {
+ headers: {
+ cookie,
+ authorization: authHeader,
+ },
+ credentials: "include",
+ signal: controller.signal,
+ });
+
+ clearTimeout(timeout);
+
+ const isAuthenticated = resVerify.status === 200;
+
+ // Cache the result
+ authCache.set(cacheKey, {
+ isAuthenticated,
+ timestamp: Date.now(),
+ });
+
+ req.isAuthenticated = isAuthenticated;
+ } catch (err) {
+ // Auth server down/timeout - silently fail, don't crash the app
+ req.isAuthenticated = false;
+
+ // Optional: Log for debugging, but don't spam logs
+ if (req.log) {
+ req.log.warn(
+ "[AuthCheck] Auth server unavailable, continuing unauthenticated"
+ );
+ } else {
+ console.warn(
+ "[AuthCheck] Auth server unavailable, continuing unauthenticated"
+ );
+ }
+ }
+
+ next();
+};
diff --git a/src/middleware/hbs.js b/src/middleware/hbs.js
index 47dcb3b..08f9660 100644
--- a/src/middleware/hbs.js
+++ b/src/middleware/hbs.js
@@ -12,7 +12,9 @@
helpers: {
section(name, options) {
this._sections ??= {};
- this._sections[name] = options.fn(this);
+ this._sections[name] ??= "";
+ this._sections[name] += options.fn(this);
+ req.log.debug(name, this._sections);
return null;
},
},
diff --git a/src/middleware/index.js b/src/middleware/index.js
index 2cd52b9..ebce2ee 100644
--- a/src/middleware/index.js
+++ b/src/middleware/index.js
@@ -11,7 +11,7 @@
const errorHandler = require("./errorHandler");
const baseContext = require("./baseContext");
const hbs = require("./hbs");
-const authentication = require("./authentication.js");
+const authCheck = require("./authCheck");
const {
loggingMiddleware,
@@ -22,7 +22,7 @@
function setupApp() {
const app = express();
- const excludedPaths = ['/contact', '/analytics', '/track'];
+ const excludedPaths = ["/contact", "/analytics", "/track"];
const DATA_LIMIT_BYTES = 10 * 1024; // 10k
// General parsers for non-excluded routes
@@ -30,18 +30,22 @@
if (excludedPaths.includes(req.path)) return next();
express.json({ limit: DATA_LIMIT_BYTES })(req, res, (err) => {
if (err) return next(err);
- express.urlencoded({ extended: false, limit: DATA_LIMIT_BYTES })(req, res, next);
+ express.urlencoded({ extended: false, limit: DATA_LIMIT_BYTES })(
+ req,
+ res,
+ next
+ );
});
});
// Raw parser + manual truncation for excluded routes
- const rawBodyParser = express.raw({ type: '*/*', limit: '100kb' });
+ const rawBodyParser = express.raw({ type: "*/*", limit: "100kb" });
app.use((req, res, next) => {
if (!excludedPaths.includes(req.path)) return next();
rawBodyParser(req, res, (err) => {
if (err) return next(err);
try {
- const raw = req.body.toString('utf8');
+ const raw = req.body.toString("utf8");
const truncated = raw.slice(0, DATA_LIMIT_BYTES);
req.body = JSON.parse(truncated);
} catch (e) {
@@ -51,17 +55,15 @@
});
});
-
-
app.use(hbs);
// Setup logging
app.use(logEvent, morganInfo, morganWarn, morganError, loggingMiddleware);
- app.use(authentication);
-
+ app.use(authCheck);
+
// Setup handlebars
- app.use(baseContext)
+ app.use(baseContext);
// Setup production environment
if (process.env.NODE_ENV === "production") {
diff --git a/src/routes/logs.js b/src/routes/logs.js
index 7fc4776..b4076da 100644
--- a/src/routes/logs.js
+++ b/src/routes/logs.js
@@ -6,7 +6,6 @@
const secured = require("../middleware/secured");
const allowedLevels = ["warn", "error", "info", "debug", "functions", "notice"];
-const allowedTypes = ["testing", "live", "dev"];
const dbPath = path.resolve(__dirname, "../../data/logs.sqlite3");
@@ -27,16 +26,16 @@
});
router.post("/logs", secured, (req, res) => {
- const log_type = req.query.log_type || "*";
+ // const log_type = req.query.log_type || "*";
const log_level = req.query.log_level || "*";
const date = req.query.date || "*";
if (log_level !== "*" && !allowedLevels.includes(log_level)) {
return res.status(400).json({ error: "Invalid log_level" });
}
- if (log_type !== "*" && !allowedTypes.includes(log_type)) {
- return res.status(400).json({ error: "Invalid log_type" });
- }
+ // if (log_type !== "*" && !allowedTypes.includes(log_type)) {
+ // return res.status(400).json({ error: "Invalid log_type" });
+ // }
const conditions = [];
const params = [];
@@ -51,14 +50,14 @@
params.push(date);
}
- if (log_type !== "*") {
- conditions.push(`EXISTS (
- SELECT 1 FROM log_metadata m
- JOIN keys k ON k.id = m.key_id
- WHERE m.log_id = l.id AND k.key = 'type' AND m.value = ?
- )`);
- params.push(log_type);
- }
+ // if (log_type !== "*") {
+ // conditions.push(`EXISTS (
+ // SELECT 1 FROM log_metadata m
+ // JOIN keys k ON k.id = m.key_id
+ // WHERE m.log_id = l.id AND k.key = 'type' AND m.value = ?
+ // )`);
+ // params.push(log_type);
+ // }
const whereClause = conditions.length
? "WHERE " + conditions.join(" AND ")
@@ -103,6 +102,7 @@
...meta,
};
});
+ console.log(logs.length);
res.json(logs);
} catch {
diff --git a/src/views/pages/logs.handlebars b/src/views/pages/logs.handlebars
index 69eb7bb..7ead8ea 100644
--- a/src/views/pages/logs.handlebars
+++ b/src/views/pages/logs.handlebars
@@ -8,6 +8,7 @@
Log Viewer