UNPKG

sinch-rtc

Version:

RTC JavaScript/Web SDK

262 lines 11.4 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 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) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.InstanceController = void 0; /* eslint-disable @typescript-eslint/no-var-requires */ const DeviceVersion_1 = require("./DeviceVersion"); const Capability_1 = require("../models/Capability"); const auth_1 = require("../ocra/auth"); const utils_1 = require("../utils/"); const ClientRegistration_1 = require("../ClientRegistration"); const jwt_1 = require("./jwt"); const Errors_1 = require("../utils/Errors"); const UserInstance_1 = require("./UserInstance"); const StorageFactory_1 = require("../storage/StorageFactory"); const { version } = require("../../package.json"); class InstanceController { constructor(applicationKey, userId, clientEvent, api) { this.applicationKey = applicationKey; this.userId = userId; this.clientEvent = clientEvent; this.api = api; this.DefaultCapabilities = [ Capability_1.Capability.P2p, Capability_1.Capability.IceProxy, Capability_1.Capability.Ocra, ]; this.deviceId = utils_1.StringHelper.UUID(); this.userInstance = null; this.createNewInstanceAuthentication = () => __awaiter(this, void 0, void 0, function* () { yield this.createInstance(); if (this.authentication) return this.authentication; else throw Error("Unable to create instance"); }); this.prolongInstance = () => __awaiter(this, void 0, void 0, function* () { return utils_1.PromiseHelper.setTimeout(new Promise((resolve, reject) => { this.clientEvent.onEvent({ eventType: "registration", context: new ClientRegistration_1.ClientRegistration((jwt) => __awaiter(this, void 0, void 0, function* () { this.updateInstanceExpiresAt(this.userId, jwt) .then(() => resolve()) .catch((reason) => { reject(reason); }); }), () => { reject("onCredentialsRequired failed."); }), }); }), InstanceController.REGISTRATION_TIMEOUT_MS); }); this.storage = StorageFactory_1.StorageFactory.createInstanceStorage(this.applicationKey, this.userId); this.deviceVersion = new DeviceVersion_1.DeviceVersion(InstanceController.APPLICATION_VERSION); this.capabilities = this.DefaultCapabilities; this.updateInstanceTtlWindowDays = InstanceController.UPDATE_INSTANCE_TTL_WINDOW_DAYS_DEFAULT; this.callUpdateInstanceApi = this.callUpdateInstanceApi.bind(this); this.setUpdatedInstance = this.setUpdatedInstance.bind(this); this.storeInstance = this.storeInstance.bind(this); this.updateInstance = (0, utils_1.pipeAsync)(this.callUpdateInstanceApi, this.setUpdatedInstance, this.storeInstance); } removeInstance() { this.storage.remove(); } setInstance(userInstance) { if (this.instance) this.removeInstance(); this.storage.set(userInstance); this.userInstance = userInstance; this.authentication = new auth_1.InstanceRequestSignatureV1Authentication({ applicationKey: this.applicationKey, username: this.userId, instance: this.userInstance.instance, }, userInstance, this.prolongInstance); this.api.setInstanceAuthentication(this.authentication, this.createNewInstanceAuthentication); } get instance() { return this.userInstance; } toggleCapability(capability, enabled) { const lengthBeforeToggling = this.capabilities.length; if (enabled) { this.capabilities.push(capability); } else { this.capabilities = this.capabilities.filter((c) => c !== capability); } if (lengthBeforeToggling !== this.capabilities.length) { this.scheduleInstanceUpdate(); } } isCapabilityEnabled(capability) { return this.capabilities.includes(capability); } setUpdateInstanceTtlWindow(updateTtlWindowDays) { if (updateTtlWindowDays) { this.updateInstanceTtlWindowDays = updateTtlWindowDays; } } start() { return __awaiter(this, void 0, void 0, function* () { const userInstance = this.storage.get(); if (userInstance) { if (userInstance.hasExpired()) { this.removeInstance(); } else { this.setInstance(userInstance); this.updateInstanceIfNecessary(); return userInstance.instance; } } // no persisted instance found ask for jwt token if (!this.clientEvent.hasListeners()) { throw new Errors_1.InvalidOperationError("No listener registered for onCredentialsRequired"); } else { return this.createInstance(); } }); } prolongInstanceIfNeeded() { return __awaiter(this, void 0, void 0, function* () { if (this.instance && this.instance.shouldProlong(this.updateInstanceTtlWindowDays)) { yield this.prolongInstance(); } }); } terminate() { if (this.updateInstanceTimeoutId) { clearTimeout(this.updateInstanceTimeoutId); } } createInstance() { return __awaiter(this, void 0, void 0, function* () { return utils_1.PromiseHelper.setTimeout(new Promise((resolve, reject) => { this.clientEvent.onEvent({ eventType: "registration", context: new ClientRegistration_1.ClientRegistration((jwt) => __awaiter(this, void 0, void 0, function* () { this.register(jwt) .then((instance) => resolve(instance)) .catch((reason) => { reject(reason); }); }), () => { reject("onCredentialsRequired failed."); }), }); }), InstanceController.REGISTRATION_TIMEOUT_MS); }); } updateInstanceIfNecessary() { const currentInstance = this.instance; if (!currentInstance) { console.error("Error during updating instance, current instance not set"); return; } if (!this.deviceVersion.equals(currentInstance.instance.version)) { this.scheduleInstanceUpdate(); } } /** * When the SDK is about to issue an UpdateInstance request, the request is delayed for a short time. * When the timer has expired, only the latest UpdateInstance request is actually sent over to the backend. * This is to avoid sending multiple UpdateInstance requests in a very * short time when multiple properties of an instance (e.g. capabilities / device information) are changed. */ scheduleInstanceUpdate() { if (this.updateInstanceTimeoutId) { return; } this.updateInstanceTimeoutId = setTimeout(() => { this.updateInstanceTimeoutId = undefined; this.updateInstance(); }, InstanceController.UPDATE_INSTANCE_DELAY_MS); } register(token) { return __awaiter(this, void 0, void 0, function* () { const jwt = jwt_1.JWT.parse(token); this.validateExpireAt(jwt); const response = yield this.api.createInstance(new auth_1.JwtAuthentication(token), { applicationKey: this.applicationKey, createInstanceRequest: { userId: this.userId, deviceId: this.deviceId, // todo fix device id capabilities: this.capabilities, version: this.deviceVersion, expireAt: jwt.instanceExpireAt, }, }); this.setInstance(new UserInstance_1.UserInstance(Object.assign({}, response.instance), response.config, new Date(jwt.iat * 1000))); return response.instance; }); } validateExpireAt(jwt) { if (jwt.instanceTtl < InstanceController.MIN_TTL_MS) throw new Errors_1.ArgumentError("instance TTL has to be greater than 48h", (0, utils_1.nameof)(jwt)); } storeInstance() { if (!this.instance) { return undefined; } this.storage.set(this.instance); } setUpdatedInstance(updatedInstance) { if (!updatedInstance || !this.instance) { return undefined; } this.instance.instance = updatedInstance; return updatedInstance; } callUpdateInstanceApi() { return __awaiter(this, void 0, void 0, function* () { if (!this.instance) { return undefined; } const { id: instanceId } = this.instance.instance; return yield this.api.updateInstance({ userId: this.userId, instanceId, updateInstanceRequest: { capabilities: this.capabilities, version: this.deviceVersion, }, }); }); } updateInstanceExpiresAt(userId, token) { return __awaiter(this, void 0, void 0, function* () { if (this.instance) { const jwt = jwt_1.JWT.parse(token); this.validateExpireAt(jwt); const response = yield this.api.updateInstanceTtl(new auth_1.JwtAuthentication(token), { instanceId: this.instance.instance.id, userId, updateInstanceTtlRequest: { expireAt: jwt.instanceExpireAt, }, }); this.instance.iat = new Date(jwt.iat * 1000); this.instance.instance.expireAt = response.expireAt; this.storeInstance(); } }); } } exports.InstanceController = InstanceController; InstanceController.MIN_TTL_MS = 48 * 3600 * 1000; InstanceController.REGISTRATION_TIMEOUT_MS = 4000; InstanceController.APPLICATION_VERSION = version; InstanceController.UPDATE_INSTANCE_DELAY_MS = 500; InstanceController.UPDATE_INSTANCE_TTL_WINDOW_DAYS_DEFAULT = 180; //# sourceMappingURL=InstanceController.js.map