const crypto = require('crypto') const adminPassword = process.env.MUNIN_ADMIN_PASSWORD || '' const sessions = new Map() const SESSION_TTL_MS = 24 * 60 * 60 * 1000 function createSession() { const token = crypto.randomBytes(32).toString('hex') sessions.set(token, { expiresAt: Date.now() + SESSION_TTL_MS, }) return token } function parseCookies(cookieHeader) { const cookies = {} for (const part of (cookieHeader || '').split(';')) { const index = part.indexOf('=') if (index === -1) continue const name = part.slice(0, index).trim() const value = part.slice(index + 1).trim() if (name) { cookies[name] = decodeURIComponent(value) } } return cookies } function isValidSession(req) { const token = parseCookies(req.headers.cookie).munin_session if (!token) return false const session = sessions.get(token) if (!session) return false if (session.expiresAt <= Date.now()) { sessions.delete(token) return false } return true } function passwordsEqual(a, b) { const left = Buffer.from(a) const right = Buffer.from(b) if (left.length !== right.length) return false return crypto.timingSafeEqual(left, right) } function checkPassword(password) { if (!adminPassword || typeof password !== 'string') { return false } return passwordsEqual(password, adminPassword) } function cleanupSessions() { const now = Date.now() for (const [token, session] of sessions) { if (session.expiresAt <= now) { sessions.delete(token) } } } setInterval(cleanupSessions, 60 * 60 * 1000).unref() module.exports = { checkPassword, createSession, isValidSession, }