even better security

This commit is contained in:
KingKDot
2026-03-21 17:03:42 -05:00
parent 2af73b8a81
commit 00675aa329
4 changed files with 79 additions and 28 deletions
+45
View File
@@ -97,6 +97,16 @@ db.run(
`CREATE INDEX IF NOT EXISTS idx_banned_ips_created_at ON banned_ips(created_at DESC);`,
);
db.run(`
CREATE TABLE IF NOT EXISTS revoked_tokens (
token_hash TEXT PRIMARY KEY,
expires_at INTEGER NOT NULL
);
`);
db.run(
`CREATE INDEX IF NOT EXISTS idx_revoked_tokens_expires ON revoked_tokens(expires_at);`,
);
db.run(`
CREATE TABLE IF NOT EXISTS builds (
id TEXT PRIMARY KEY,
@@ -317,6 +327,41 @@ export function isIpBanned(ip: string): boolean {
return !!row?.ip;
}
// ── Revoked token persistence ──
function hashToken(token: string): string {
return new Bun.CryptoHasher("sha256").update(token).digest("hex");
}
export function persistRevokedToken(token: string, expiresAt: number): void {
db.run(
`INSERT OR IGNORE INTO revoked_tokens (token_hash, expires_at) VALUES (?, ?)`,
hashToken(token),
expiresAt,
);
}
export function isTokenRevoked(token: string): boolean {
const row = db.query<{ token_hash: string }>(
`SELECT token_hash FROM revoked_tokens WHERE token_hash=?`,
).get(hashToken(token));
return !!row;
}
export function loadAllRevokedTokenHashes(): Set<string> {
const now = Math.floor(Date.now() / 1000);
const rows = db.query<{ token_hash: string }>(
`SELECT token_hash FROM revoked_tokens WHERE expires_at > ?`,
).all(now);
return new Set(rows.map((r) => r.token_hash));
}
export function pruneExpiredRevokedTokens(): number {
const now = Math.floor(Date.now() / 1000);
const result = db.run(`DELETE FROM revoked_tokens WHERE expires_at <= ?`, now);
return result.changes;
}
export function markAllClientsOffline() {
db.run(`UPDATE clients SET online=0`);
console.log("[db] marked all clients as offline");