@cocalc/server
Version:
CoCalc server functionality: functions used by either the hub and the next.js server
115 lines • 4.99 kB
JavaScript
;
/*
* This file is part of CoCalc: Copyright © 2021 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.load_server_settings_from_env = exports.getServerSettings = exports.setPassportsCached = exports.getPassportsCached = exports.resetServerSettingsCache = void 0;
const lru_cache_1 = __importDefault(require("lru-cache"));
const site_settings_extras_1 = require("@cocalc/util/db-schema/site-settings-extras");
const schema_1 = require("@cocalc/util/schema");
const consts_1 = require("@cocalc/util/consts");
const pool_1 = __importDefault(require("@cocalc/database/pool"));
const async_utils_1 = require("@cocalc/util/async-utils");
const logger_1 = __importDefault(require("@cocalc/backend/logger"));
const L = (0, logger_1.default)("server:server-settings");
// We're just using this to cache this result for a **few seconds**.
const CACHE_TIME_SECONDS = process.env.NODE_ENV == "development" ? 3 : 15;
// TODO add something for the passports data type?
const cache = new lru_cache_1.default({
max: 10,
maxAge: 1000 * CACHE_TIME_SECONDS,
});
const KEY = "server-settings";
function resetServerSettingsCache() {
cache.reset();
}
exports.resetServerSettingsCache = resetServerSettingsCache;
function getPassportsCached() {
return cache.get("passports");
}
exports.getPassportsCached = getPassportsCached;
function setPassportsCached(val) {
return cache.set("passports", val);
}
exports.setPassportsCached = setPassportsCached;
async function getServerSettings() {
if (cache.has(KEY)) {
return cache.get(KEY); // can't be null
}
const pool = (0, pool_1.default)();
const { rows } = await pool.query("SELECT name, value FROM server_settings");
const settings = { _timestamp: Date.now() };
const raw = {};
for (const row of rows) {
raw[row.name] = row.value;
}
// process values, including any post-processing.
for (const row of rows) {
const { name, value } = row;
const spec = schema_1.site_settings_conf[name] ?? site_settings_extras_1.EXTRAS[name];
// we only process values we know
if (spec == null)
continue;
const toVal = spec.to_val;
settings[name] = toVal != null ? toVal(value, raw) : value;
}
// set default values for missing keys
for (const config of [site_settings_extras_1.EXTRAS, schema_1.site_settings_conf]) {
for (const key in config) {
if (settings[key] == null) {
const spec = config[key];
settings[key] =
spec?.to_val != null ? spec.to_val(spec.default, raw) : spec.default;
}
}
}
cache.set(KEY, settings);
return settings;
}
exports.getServerSettings = getServerSettings;
/*
This stores environment variables for server settings in the DB to make the life of an admin easier.
e.g. COCALC_SETTING_DNS, COCALC_SETTING_EMAIL_SMTP_SERVER, COCALC_SETTING_EMAIL_SMTP_PASSWORD, ...
Loaded once at startup, right after configuring the db schema, see hub/hub.ts.
*/
async function load_server_settings_from_env(db) {
const PREFIX = consts_1.SERVER_SETTINGS_ENV_PREFIX;
// reset all readonly values
await db.async_query({
query: "UPDATE server_settings",
set: { readonly: false },
where: ["1=1"], // otherwise there is an exception about not restricting the query
});
// now, check if there are any we know of
for (const config of [site_settings_extras_1.EXTRAS, schema_1.site_settings_conf]) {
for (const key in config) {
const envvar = `${PREFIX}_${key.toUpperCase()}`;
const envval = process.env[envvar];
if (envval == null)
continue;
// ATTN do not expose the value, could be a password
L.debug(`picking up $${envvar} and saving it in the database`);
// check validity
const valid = (schema_1.site_settings_conf[key] ?? site_settings_extras_1.EXTRAS[key])?.valid;
if (valid != null) {
if (Array.isArray(valid) && !valid.includes(envval)) {
throw new Error(`The value of $${envvar} is invalid. allowed are ${valid}.`);
}
else if (typeof valid == "function" && !valid(envval)) {
throw new Error(`The validation function rejected the value of $${envvar}.`);
}
}
await (0, async_utils_1.callback2)(db.set_server_setting, {
name: key,
value: envval,
readonly: true,
});
}
}
}
exports.load_server_settings_from_env = load_server_settings_from_env;
//# sourceMappingURL=server-settings.js.map