realm-object-server
Version:
88 lines • 3.81 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const uws = require("uws");
const errors = require("../errors");
const util_1 = require("./util");
class ServiceWebSocketServer extends uws.Server {
constructor(logger, tokenValidator) {
super({ noServer: true });
this.tokenValidator = tokenValidator;
this.logger = logger;
}
setLogger(logger) {
this.logger = logger;
}
upgradeAuthenticated(req, socket, head, mustBeAdmin = false) {
return __awaiter(this, void 0, void 0, function* () {
const client = yield this.upgradeWebSocket(req, socket, head);
const authenticatedClient = new Promise((resolve, reject) => {
client.on("message", message => {
try {
const token = this.isValidFirstMessage(message, mustBeAdmin);
if (token) {
socket.identity = token.identity;
resolve(client);
}
else {
throw new Error("Not a valid first message");
}
}
catch (err) {
if (err instanceof SyntaxError) {
err = new errors.realm.InvalidCredentials({
title: "Expected a serialized JSON object as the first message"
});
}
reject(err);
}
});
});
const ms = ServiceWebSocketServer.AUTHENTICATION_TIMEOUT;
return util_1.timeout(authenticatedClient, ms).catch((err) => {
this.logger.debug(`Couldn't upgrade WebSocket: ${err.stack}`);
if (client.readyState === uws.OPEN || client.readyState === uws.CONNECTING) {
client.close(1008, err.message);
}
throw err;
});
});
}
isValidFirstMessage(message, mustBeAdmin) {
const msg = JSON.parse(message);
if (!msg.action) {
throw new errors.realm.MissingParameters("action");
}
if (msg.action === "authenticate") {
if (!msg.token) {
throw new errors.realm.MissingParameters("token");
}
return this.tokenValidator.parse(msg.token, { mustBeAdmin });
}
else {
const example = '{ action: "authenticate", ... }';
throw new errors.realm.InvalidCredentials({
title: `Expected an authentication message: ${example}`
});
}
}
upgradeWebSocket(req, socket, head) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
this.handleUpgrade(req, socket, head, (client) => {
resolve(client);
});
});
});
}
}
ServiceWebSocketServer.AUTHENTICATION_TIMEOUT = 1000;
exports.ServiceWebSocketServer = ServiceWebSocketServer;
//# sourceMappingURL=websocket.js.map