56 lines
2.0 KiB
TypeScript
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 {
|
|
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';
|
|
}
|
|
} |