UNPKG

@cocalc/server

Version:

CoCalc server functionality: functions used by either the hub and the next.js server

71 lines (69 loc) 3.28 kB
"use strict"; /* User management of the v1 API key associated to an account. This supports three actions: - get: get the existing key associated to an account; return undefined if there is no api key set. - delete: delete the existing key associated to an account - regenerate: delete the existing key and replace it by a new random key. If the user has a password, then it must be provided and be correct. If they have no password, then the provided one is ignored. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAccountWithApiKey = void 0; const pool_1 = __importDefault(require("@cocalc/database/pool")); const misc_1 = require("@cocalc/util/misc"); const is_password_correct_1 = __importDefault(require("@cocalc/server/auth/is-password-correct")); const has_password_1 = __importDefault(require("@cocalc/server/auth/has-password")); const random_key_1 = require("random-key"); async function manage({ account_id, password, action, }) { if (!misc_1.isValidUUID) { throw Error("account_id is not a valid uuid"); } // Check if the user has a password if (await (0, has_password_1.default)(account_id)) { if (!password) { throw Error("password must be provided"); } // verify password is correct if (!(await (0, is_password_correct_1.default)({ account_id, password }))) { throw Error("invalid password"); } } // Now we allow the action. const pool = (0, pool_1.default)(); switch (action) { case "get": const { rows } = await pool.query("SELECT api_key FROM accounts WHERE account_id=$1::UUID", [account_id]); if (rows.length == 0) { throw Error("no such account"); } return rows[0].api_key; case "delete": await pool.query("UPDATE accounts SET api_key=NULL WHERE account_id=$1::UUID", [account_id]); return; case "regenerate": // There is a unique index on api_key, so there is a small probability // that this query fails. However, it's probably smaller than the probability // that the database connection is broken, so if it were to ever happen, then // the user could just retry. For context, for the last few years, this query // happened on cocalc.com only a few thousand times *total*. const api_key = `sk_${(0, random_key_1.generate)()}`; await pool.query("UPDATE accounts SET api_key=$1 WHERE account_id=$2::UUID", [api_key, account_id]); return api_key; default: throw Error(`unknown action="${action}"`); } } exports.default = manage; /* Get the account that has the given api key, or returns undefined if there is no such account. */ async function getAccountWithApiKey(api_key) { const pool = (0, pool_1.default)("medium"); const { rows } = await pool.query("SELECT account_id FROM accounts WHERE api_key = $1::TEXT", [api_key]); return rows[0]?.account_id; } exports.getAccountWithApiKey = getAccountWithApiKey; //# sourceMappingURL=manage.js.map