swaf/src/auth/magic_link/MagicLinkWebSocketListener.ts

69 lines
2.3 KiB
TypeScript
Raw Normal View History

import {Session} from "express-session";
import {IncomingMessage} from "http";
import WebSocket from "ws";
import Application from "../../Application.js";
import SessionWebSocketListener from "../../SessionWebSocketListener.js";
import MagicLink from "../models/MagicLink.js";
2020-05-09 23:19:47 +02:00
export default class MagicLinkWebSocketListener<A extends Application> extends SessionWebSocketListener<A> {
private readonly connections: { [p: string]: (() => void)[] | undefined } = {};
2020-05-09 23:19:47 +02:00
public refreshMagicLink(sessionId: string): void {
const fs = this.connections[sessionId];
2020-05-09 23:19:47 +02:00
if (fs) {
fs.forEach(f => f());
}
}
public async handleSessionSocket(socket: WebSocket, request: IncomingMessage, session: Session): Promise<void> {
2020-05-09 23:19:47 +02:00
// Refuse any incoming data
socket.on('message', () => {
socket.close(1003);
});
// Get magic link
const magicLink = await MagicLink.select()
.where('session_id', session.id)
.sortBy('authorized')
.first();
2020-05-09 23:19:47 +02:00
// Refresh if immediately applicable
if (!magicLink || !await magicLink.isValid() || await magicLink.isAuthorized()) {
socket.send('refresh');
const reason = magicLink ?
'Magic link state changed.' :
'Magic link not found for session ' + session.id;
socket.close(1000, reason);
2020-05-09 23:19:47 +02:00
return;
}
const validityTimeout = setTimeout(() => {
socket.send('refresh');
socket.close(1000, 'Timed out');
2020-05-09 23:19:47 +02:00
}, magicLink.getExpirationDate().getTime() - new Date().getTime());
const f = () => {
clearTimeout(validityTimeout);
socket.send('refresh');
socket.close(1000, 'Closed by server');
2020-05-09 23:19:47 +02:00
};
socket.on('close', () => {
const connections = this.connections[session.id];
if (connections) {
this.connections[session.id] = connections.filter(f => f !== f);
if (connections.length === 0) delete this.connections[session.id];
}
2020-05-09 23:19:47 +02:00
});
let connections = this.connections[session.id];
if (!connections) connections = this.connections[session.id] = [];
connections.push(f);
2020-05-09 23:19:47 +02:00
}
public path(): string {
2020-05-09 23:19:47 +02:00
return '/magic-link';
}
}