@cocalc/database
Version:
CoCalc: code for working with our PostgreSQL database
90 lines • 3.47 kB
JavaScript
;
/*
* This file is part of CoCalc: Copyright © 2022 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.loadSSOConf = void 0;
const logger_1 = __importDefault(require("@cocalc/backend/logger"));
const promises_1 = require("fs/promises");
const L = (0, logger_1.default)("auth:sso:import-sso-configuration").debug;
// The path to the file. In actual use, this is a K8S secret exported as a file to /secrets/sso/sso.json
// content of that file: "{ [strategy name]: {conf: {…}, info: {…}}, […] : { … } | null, … }"
// further details are describe in src/packages/server/auth/sso/types.ts
const SSO_JSON = process.env.COCALC_SSO_CONFIG;
// This function imports the SSO configuration from a file into the database.
// If a key points to "null", the entry is deleted.
// This runs only once during startup, called by the hub's auth.ts.
async function loadSSOConf(db) {
if (SSO_JSON == null) {
L("No SSO configuration file specified via $COCALC_SSO_CONFIG.");
return;
}
// test if the path at SSO_JSON is a regular file and is readable
try {
// the file could be a symlink, we have to resolve it
const ssofn = await (0, promises_1.realpath)(SSO_JSON);
const stats = await (0, promises_1.lstat)(ssofn);
if (!stats.isFile()) {
L(`SSO configuration file ${SSO_JSON} is not a regular file`);
return;
}
}
catch (err) {
L(`SSO configuration file ${SSO_JSON} does not exist or is not readable`);
return;
}
await load(db);
}
exports.loadSSOConf = loadSSOConf;
async function load(db) {
if (SSO_JSON == null) {
throw new Error("SSO_JSON is not defined, should never happen");
}
// load the json data stored in the file SSO_JSON
L(`Loading SSO configuration from '${SSO_JSON}'`);
const client = db._client();
if (client == null) {
L(`no database client available -- skipping SSO configuration`);
return;
}
// throws upon JSON parsing errors
const data = JSON.parse(await (0, promises_1.readFile)(SSO_JSON, "utf8"));
try {
await client.query("BEGIN");
for (const strategy in data) {
const val = data[strategy];
if (val == null) {
await deleteSSO(client, strategy);
}
else {
await upsertSSO(client, strategy, val);
}
}
await client.query("COMMIT");
}
catch (err) {
L(`ROLLBACK -- err=${err}`);
await client.query("ROLLBACK");
}
}
const deleteQuery = `
DELETE FROM passport_settings
WHERE strategy = $1`;
async function deleteSSO(client, strategy) {
L(`Deleting SSO configuration for ${strategy}`);
await client.query(deleteQuery, [strategy]);
}
const upsertQuery = `
INSERT INTO passport_settings (strategy, conf, info)
VALUES ($1, $2, $3)
ON CONFLICT (strategy) DO UPDATE SET conf = $2, info = $3`;
async function upsertSSO(client, strategy, val) {
const { conf, info } = val;
L(`Updating SSO configuration for ${strategy}:`, { conf, info });
await client.query(upsertQuery, [strategy, conf, info]);
}
//# sourceMappingURL=load-sso-conf.js.map