51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import Database from 'better-sqlite3';
|
|
import { newSessionToken, PortalSession, SessionRepo } from '../accounts';
|
|
|
|
/** SQLite-backed portal sessions; survives server restarts. */
|
|
export class SqliteSessionRepo implements SessionRepo {
|
|
constructor(private db: Database.Database) {
|
|
this.db.exec(`
|
|
CREATE TABLE IF NOT EXISTS portal_sessions (
|
|
token TEXT PRIMARY KEY,
|
|
customer_id TEXT NOT NULL,
|
|
created_ms INTEGER NOT NULL,
|
|
expires_ms INTEGER NOT NULL
|
|
)
|
|
`);
|
|
}
|
|
|
|
create(customerId: string, ttlMs: number): PortalSession {
|
|
const now = Date.now();
|
|
const session: PortalSession = {
|
|
token: newSessionToken(),
|
|
customerId,
|
|
createdMs: now,
|
|
expiresMs: now + ttlMs,
|
|
};
|
|
this.db
|
|
.prepare(
|
|
'INSERT INTO portal_sessions (token, customer_id, created_ms, expires_ms) VALUES (?, ?, ?, ?)',
|
|
)
|
|
.run(session.token, session.customerId, session.createdMs, session.expiresMs);
|
|
return session;
|
|
}
|
|
|
|
get(token: string, nowMs = Date.now()): PortalSession | undefined {
|
|
const r = this.db
|
|
.prepare('SELECT * FROM portal_sessions WHERE token = ?')
|
|
.get(token) as
|
|
| { token: string; customer_id: string; created_ms: number; expires_ms: number }
|
|
| undefined;
|
|
if (!r || r.expires_ms <= nowMs) return undefined;
|
|
return {
|
|
token: r.token,
|
|
customerId: r.customer_id,
|
|
createdMs: r.created_ms,
|
|
expiresMs: r.expires_ms,
|
|
};
|
|
}
|
|
|
|
delete(token: string): void {
|
|
this.db.prepare('DELETE FROM portal_sessions WHERE token = ?').run(token);
|
|
}
|
|
}
|