swaf/src/auth/magic_link/MagicLinkWebSocketListener.ts

56 lines
2.0 KiB
TypeScript

import WebSocket from "ws";
import {IncomingMessage} from "http";
import WebSocketListener from "../../WebSocketListener";
import MagicLink from "../models/MagicLink";
export default class MagicLinkWebSocketListener extends WebSocketListener<any> {
private static readonly connections: { [p: string]: (() => void)[] } = {};
public static refreshMagicLink(sessionID: string) {
const fs = MagicLinkWebSocketListener.connections[sessionID];
if (fs) {
fs.forEach(f => f());
}
}
async handle(socket: WebSocket, request: IncomingMessage, session: Express.SessionData): Promise<void> {
// Refuse any incoming data
socket.on('message', () => {
socket.close(1003);
});
// Get magic link
const magicLink = await MagicLink.bySessionID(session.id);
// Refresh if immediately applicable
if (!magicLink || !await magicLink.isValid() || await magicLink.isAuthorized()) {
socket.send('refresh');
socket.close(1000);
return;
}
const validityTimeout = setTimeout(() => {
socket.send('refresh');
socket.close(1000);
}, magicLink.getExpirationDate().getTime() - new Date().getTime());
const f = () => {
clearTimeout(validityTimeout);
socket.send('refresh');
socket.close(1000);
};
socket.on('close', () => {
MagicLinkWebSocketListener.connections[session.id] = MagicLinkWebSocketListener.connections[session.id].filter(f => f !== f);
if (MagicLinkWebSocketListener.connections[session.id].length === 0) delete MagicLinkWebSocketListener.connections[session.id];
});
if (!MagicLinkWebSocketListener.connections[session.id]) MagicLinkWebSocketListener.connections[session.id] = [];
MagicLinkWebSocketListener.connections[session.id].push(f);
}
path(): string {
return '/magic-link';
}
}