71 lines
1.4 KiB
TypeScript
71 lines
1.4 KiB
TypeScript
import { randomBytes } from 'crypto';
|
|
|
|
export interface IssuedToken {
|
|
token: string;
|
|
userId: string;
|
|
username: string;
|
|
displayName: string;
|
|
signalingServerUrl: string;
|
|
issuedAt: number;
|
|
expiresAt: number;
|
|
}
|
|
|
|
const TOKEN_TTL_MS = 24 * 60 * 60 * 1000;
|
|
|
|
const tokens = new Map<string, IssuedToken>();
|
|
|
|
export function issueToken(params: {
|
|
userId: string;
|
|
username: string;
|
|
displayName: string;
|
|
signalingServerUrl: string;
|
|
}): IssuedToken {
|
|
const token = randomBytes(32).toString('hex');
|
|
const issuedAt = Date.now();
|
|
const issued: IssuedToken = {
|
|
token,
|
|
issuedAt,
|
|
expiresAt: issuedAt + TOKEN_TTL_MS,
|
|
userId: params.userId,
|
|
username: params.username,
|
|
displayName: params.displayName,
|
|
signalingServerUrl: params.signalingServerUrl
|
|
};
|
|
|
|
tokens.set(token, issued);
|
|
return issued;
|
|
}
|
|
|
|
export function consumeToken(token: string): IssuedToken | null {
|
|
const issued = tokens.get(token);
|
|
|
|
if (!issued) {
|
|
return null;
|
|
}
|
|
|
|
if (issued.expiresAt < Date.now()) {
|
|
tokens.delete(token);
|
|
return null;
|
|
}
|
|
|
|
return issued;
|
|
}
|
|
|
|
export function revokeToken(token: string): void {
|
|
tokens.delete(token);
|
|
}
|
|
|
|
export function clearAllTokens(): void {
|
|
tokens.clear();
|
|
}
|
|
|
|
export function pruneExpiredTokens(): void {
|
|
const now = Date.now();
|
|
|
|
for (const [token, issued] of tokens) {
|
|
if (issued.expiresAt < now) {
|
|
tokens.delete(token);
|
|
}
|
|
}
|
|
}
|