UNPKG

@cocalc/hub

Version:
166 lines 6.31 kB
"use strict"; /* * This file is part of CoCalc: Copyright © 2020 Sagemath, Inc. * License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebappConfiguration = exports.clear_cache = void 0; const software_envs_1 = require("@cocalc/server/software-envs"); const async_utils_1 = require("@cocalc/util/async-utils"); const site_settings_extras_1 = require("@cocalc/util/db-schema/site-settings-extras"); const schema_1 = require("@cocalc/util/schema"); const awaiting_1 = require("awaiting"); const debug_1 = __importDefault(require("debug")); const parse_domain_1 = require("parse-domain"); const auth_1 = require("./auth"); const server_settings_1 = __importDefault(require("./servers/server-settings")); const utils_1 = require("./utils"); const L = (0, debug_1.default)("hub:webapp-config"); const lru_cache_1 = __importDefault(require("lru-cache")); const CACHE = new lru_cache_1.default({ max: 1000, maxAge: 60 * 1000 }); // 1 minutes function clear_cache() { CACHE.reset(); } exports.clear_cache = clear_cache; async function get_passport_manager_async() { // the only issue here is, that the http server already starts up before the // passport manager is configured – but, the passport manager depends on the http server // we just retry during that initial period of uncertainty… let ms = 100; while (true) { const pp_manager = (0, auth_1.get_passport_manager)(); if (pp_manager != null) { return pp_manager; } else { L(`WARNING: Passport Manager not available yet -- trying again in ${ms}ms`); await (0, awaiting_1.delay)(ms); ms = Math.min(10000, 1.3 * ms); } } } class WebappConfiguration { constructor({ db }) { this.db = db; this.init(); } async init() { // this.data.pub updates automatically – do not modify it! this.data = await (0, server_settings_1.default)(); this.passport_manager = await get_passport_manager_async(); } // server settings with whitelabeling settings // TODO post-process all values async settings(vID) { const res = await (0, async_utils_1.callback2)(this.db._query, { query: "SELECT id, settings FROM whitelabeling", cache: true, where: { "id = $::TEXT": vID }, }); if (this.data == null) { // settings not yet initialized return {}; } const data = res.rows[0]; if (data != null) { return { ...this.data.all, ...data.settings }; } else { return this.data.all; } } // derive the vanity ID from the host string get_vanity_id(host) { const host_parsed = (0, parse_domain_1.parseDomain)(host); if (host_parsed.type === parse_domain_1.ParseResultType.Listed) { // vanity for vanity.cocalc.com or foo.p for foo.p.cocalc.com return host_parsed.subDomains.join("."); } return undefined; } async theme(vID) { const res = await (0, async_utils_1.callback2)(this.db._query, { query: "SELECT id, theme FROM whitelabeling", cache: true, where: { "id = $::TEXT": vID }, }); const data = res.rows[0]; if (data != null) { // post-process data, but do not set default values… const theme = {}; for (const [key, value] of Object.entries(data.theme)) { const config = schema_1.site_settings_conf[key] ?? site_settings_extras_1.EXTRAS[key]; if (typeof config?.to_val == "function") { theme[key] = config.to_val(value, data.theme); } else { if (typeof value == "string" || typeof value == "boolean") { theme[key] = value; } } } L(`vanity theme=${JSON.stringify(theme)}`); return theme; } else { L(`theme id=${vID} not found`); return {}; } } async get_vanity(vID) { if (vID != null && vID !== "") { L(`vanity ID = "${vID}"`); return await this.theme(vID); } else { return {}; } } // returns the global configuration + eventually vanity specific site config settings async get_configuration({ host, country }) { if (this.data == null) { // settings not yet initialized return {}; } const vID = this.get_vanity_id(host); const config = this.data.pub; const vanity = this.get_vanity(vID); return { ...config, ...vanity, ...{ country, dns: host } }; } get_strategies() { const key = "strategies"; let strategies = CACHE.get(key); if (strategies == null) { strategies = this.passport_manager.get_strategies_v2(); CACHE.set(key, strategies); } return strategies; } async get_config({ country, host }) { const [configuration, registration, software] = await Promise.all([ this.get_configuration({ host, country }), (0, utils_1.have_active_registration_tokens)(this.db), (0, software_envs_1.getSoftwareEnvironments)("webapp"), ]); const strategies = this.get_strategies(); return { configuration, registration, strategies, software }; } // it returns a shallow copy, hence you can modify/add keys in the returned map! async get({ country, host }) { const key = `config::${country}::${host}`; let config = CACHE.get(key); if (config == null) { config = await this.get_config({ country, host }); CACHE.set(key, config); } else { L(`cache hit -- '${key}'`); } return config; } } exports.WebappConfiguration = WebappConfiguration; //# sourceMappingURL=webapp-configuration.js.map