Initial commit: auth

This commit is contained in:
jtricerolph 2026-07-01 12:09:54 +00:00
commit 372e71c8f5
11 changed files with 500 additions and 0 deletions

40
src/ip-check.js Normal file
View file

@ -0,0 +1,40 @@
import dns from 'dns/promises'
// OFFICE_IP_CHECK supports: static IP, CIDR range, DDNS hostname, or 'disabled'
const config = process.env.OFFICE_IP_CHECK || 'disabled'
let cachedIP = null
let cacheExpiry = 0
function ipInCidr(ip, cidr) {
const [range, bits] = cidr.split('/')
const mask = ~(2 ** (32 - parseInt(bits)) - 1) >>> 0
const toInt = s => s.split('.').reduce((a, o) => (a << 8) + parseInt(o), 0) >>> 0
return (toInt(ip) & mask) === (toInt(range) & mask)
}
async function getOfficeIP() {
if (config === 'disabled') return null
if (Date.now() < cacheExpiry && cachedIP) return cachedIP
const isHostname = /[a-zA-Z]/.test(config) && !config.includes('/')
if (isHostname) {
try {
const addrs = await dns.resolve4(config)
cachedIP = addrs[0]
cacheExpiry = Date.now() + 5 * 60 * 1000 // 5 min TTL
} catch {
// DNS failed — keep last known good IP rather than locking everyone out
}
} else {
cachedIP = config
cacheExpiry = Infinity
}
return cachedIP
}
export async function isOnsite(requestIP) {
if (config === 'disabled') return true
const officeIP = await getOfficeIP()
if (!officeIP) return true
return officeIP.includes('/') ? ipInCidr(requestIP, officeIP) : requestIP === officeIP
}