"use strict";
exports.id = 9580;
exports.ids = [9580];
exports.modules = {

/***/ 939894:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.verifyPassword = void 0;
const password_hash_1 = __webpack_require__(18303);
Object.defineProperty(exports, "verifyPassword", ({ enumerable: true, get: function () { return password_hash_1.verify; } }));
// You can change the parameters at any time and no existing passwords
// or cookies should break.  This will only impact newly created
// passwords and cookies.  Old ones can be read just fine (with the old
// parameters).
const HASH_ALGORITHM = "sha512";
const HASH_ITERATIONS = 1000;
const HASH_SALT_LENGTH = 32;
function passwordHash(password) {
    // This blocks the server for around 5ms.
    // There are newer async libraries as explained at https://www.npmjs.com/package/password-hash
    // that do NOT block, which maybe we should be using instead....
    return (0, password_hash_1.generate)(password, {
        algorithm: HASH_ALGORITHM,
        saltLength: HASH_SALT_LENGTH,
        iterations: HASH_ITERATIONS,
    });
}
exports["default"] = passwordHash;
//# sourceMappingURL=password-hash.js.map

/***/ }),

/***/ 19864:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


/*
 *  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 }));
/* Determine the base path for this CoCalc service.

The default export of this module is base path, which should
be used by the CoCalc backend hub server.
*/
const DEFN = `
The basePath is the URL prefix for all paths, relative to the
host root. It must start with a leading slash /, but does not
end with one unless it is '/'.  It also should not include ://.
Some examples of valid basePaths:

- /
- /10f0e544-313c-4efe-8718-1111ac97ad11/port/5000

These are not valid:

- //
- "" (empty string)
- /foo/
- https://cocalc.com/

If the environment variable BASE_PATH is set then use that (e.g., used
when running a project), or throw an error if our assumptions are not satisfied.

Otherwise, if this code is running in a CoCalc project (i.e., if the env variable
COCALC_PROJECT_ID is set), then the base path is a combination of
COCALC_PROJECT_ID and the port that the hub will serve on.

If neither of the above conditions are met, then the base path is /.

NOTES:

- We use this code in a project started by the hub to determine the base path;
in that case, the env variable BASE_PATH is set, since otherwise the project
itself would view the base path as being relative to its own id.

`;
const port_1 = __importDefault(__webpack_require__(91117));
function isValidBasePath(s) {
    if (s[0] != "/")
        return false;
    if (s.length == 1)
        return true;
    if (s[s.length - 1] == "/")
        return false;
    if (s.includes("://"))
        return false;
    return true;
}
function basePath() {
    if (true) {
        if (!isValidBasePath("/")) {
            throw Error(`BASE_PATH (="${"/"}") is invalid - ${DEFN}.`);
        }
        return "/";
    }
    if (!process.env.COCALC_PROJECT_ID)
        return "/";
    return `/${process.env.COCALC_PROJECT_ID}/port/${port_1.default}`;
}
exports["default"] = basePath();
//# sourceMappingURL=base-path.js.map

/***/ }),

/***/ 91117:
/***/ ((__unused_webpack_module, exports) => {


/* Determine the port that the hub will serve on.

If the environment variable PORT is set, use that port; otherwise, use port 5000.

The default export of this module is the port number.
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
const DEFAULT_PORT = 5000;
function port() {
    if (process.env.PORT) {
        return parseInt(process.env.PORT);
    }
    return DEFAULT_PORT;
}
exports["default"] = port();
//# sourceMappingURL=port.js.map

/***/ }),

/***/ 17763:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.timeInSeconds = exports.getClient = void 0;
const pool_1 = __importStar(__webpack_require__(818245));
Object.defineProperty(exports, "getClient", ({ enumerable: true, get: function () { return pool_1.getClient; } }));
exports["default"] = pool_1.default;
var util_1 = __webpack_require__(532465);
Object.defineProperty(exports, "timeInSeconds", ({ enumerable: true, get: function () { return util_1.timeInSeconds; } }));
//# sourceMappingURL=index.js.map

/***/ }),

/***/ 425335:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
const path_1 = __webpack_require__(371017);
const data_1 = __webpack_require__(838699);
const fs_1 = __webpack_require__(657147);
function dbPassword() {
    const filename = (0, path_1.join)(data_1.secrets, "postgres");
    try {
        // fine to use sync, since reading db password happens only on startup
        return (0, fs_1.readFileSync)(filename).toString().trim();
    }
    catch {
        return undefined;
    }
}
exports["default"] = dbPassword;
//# sourceMappingURL=password.js.map

/***/ }),

/***/ 661879:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _cocalc_server_auth_get_account__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(763599);
/* harmony import */ var _cocalc_server_auth_get_account__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_cocalc_server_auth_get_account__WEBPACK_IMPORTED_MODULE_0__);
// There's a ton of code that imports from this file, so just importing and exporting instead of changing all of that.
// getAccount takes a req and returns the account_id, resolving either the api key or remember_me token.

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((_cocalc_server_auth_get_account__WEBPACK_IMPORTED_MODULE_0___default()));


/***/ }),

/***/ 818164:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (/* binding */ getAccountInfo),
/* harmony export */   "o": () => (/* binding */ getName)
/* harmony export */ });
/* harmony import */ var _cocalc_database_pool__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17763);
/* harmony import */ var _cocalc_database_pool__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_cocalc_database_pool__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(809774);
/* harmony import */ var lib_account_get_account__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(661879);
/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */ 


async function getAccountInfo(account_id, req) {
    return {
        account_id,
        ...await getName(account_id),
        publicPaths: await getPublicPaths(account_id, req)
    };
}
async function getName(account_id) {
    if (!(0,_util__WEBPACK_IMPORTED_MODULE_1__/* .isUUID */ .t)(account_id)) {
        throw Error("invalid UUID");
    }
    const pool = _cocalc_database_pool__WEBPACK_IMPORTED_MODULE_0___default()("long");
    // Get the database entry
    const { rows  } = await pool.query("SELECT name, first_name, last_name, email_address, passports FROM accounts WHERE account_id=$1", [
        account_id
    ]);
    if (rows.length == 0) {
        throw Error("no such user");
    }
    const is_anonymous = !rows[0].email_address && !rows[0].passports;
    return {
        first_name: rows[0].first_name,
        last_name: rows[0].last_name,
        name: rows[0].name,
        email_address: rows[0].email_address,
        is_anonymous
    };
}
async function getPublicPaths(account_id, req // used to get account_id of requester to see if we should include unlisted and disabled public_paths
) {
    if (!(0,_util__WEBPACK_IMPORTED_MODULE_1__/* .isUUID */ .t)(account_id)) {
        // VERY important to check this because we substitute the account_id
        // into the query string directly, and this is input directly from the user!
        throw Error("invalid UUID");
    }
    const pool = _cocalc_database_pool__WEBPACK_IMPORTED_MODULE_0___default()("medium");
    // Returns public paths for which account_id is a collaborator on the project and they have
    // actively used the project at some point.
    // We sort from most recently edited.
    const query = `SELECT public_paths.id as id, public_paths.path as path, public_paths.description as description,
  public_paths.disabled as disabled, public_paths.unlisted as unlisted, public_paths.vhost as vhost, public_paths.authenticated as authenticated,
  (SELECT COUNT(*)::INT FROM public_path_stars WHERE public_path_id=public_paths.id) AS stars,
  public_paths.counter::INT AS counter,
  ${(0,_cocalc_database_pool__WEBPACK_IMPORTED_MODULE_0__.timeInSeconds)("public_paths.last_edited", "last_edited")} FROM public_paths, projects WHERE public_paths.project_id = projects.project_id AND projects.last_active ? '${account_id}' AND projects.users ? '${account_id}'  ORDER BY stars DESC, public_paths.last_edited DESC`;
    const { rows  } = await pool.query(query);
    // If there are any disabled or unlisted public_paths, we also get the id of the requestor so we can filter them out.
    return await filterNonPublicAndNotAuthenticated(rows, account_id, req);
}
async function filterNonPublicAndNotAuthenticated(rows, account_id, req) {
    const v = [];
    let client_id = undefined;
    for (const row of rows){
        if (!row.disabled && !row.unlisted && !row.authenticated) {
            v.push(row);
            continue;
        }
        if (client_id == null) {
            client_id = await (0,lib_account_get_account__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(req) ?? "";
        }
        if (client_id == account_id) {
            v.push(row);
        } else if (row.authenticated === true && client_id !== "") {
            v.push(row);
        }
    }
    return v;
}


/***/ }),

/***/ 809774:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Fe": () => (/* reexport safe */ _cocalc_util_misc__WEBPACK_IMPORTED_MODULE_1__.containingPath),
/* harmony export */   "RF": () => (/* binding */ trunc),
/* harmony export */   "RT": () => (/* reexport safe */ _cocalc_util_misc__WEBPACK_IMPORTED_MODULE_1__.getExtension),
/* harmony export */   "YQ": () => (/* binding */ getTitle),
/* harmony export */   "t": () => (/* binding */ isUUID)
/* harmony export */ });
/* unused harmony export isSha1Hash */
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(371017);
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _cocalc_util_misc__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(477389);
/* harmony import */ var _cocalc_util_misc__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_cocalc_util_misc__WEBPACK_IMPORTED_MODULE_1__);
/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */ 

function isUUID(s) {
    // todo: add full check.
    return typeof s == "string" && s.length == 36;
}
function isSha1Hash(s) {
    return typeof s == "string" && s.length == 40;
// todo: could add full check (i.e., each character is in 0-e)
}
function trunc(s, n) {
    return s.length > n ? s.slice(0, n - 1) + "…" : s;
}
function getTitle({ path , relativePath  }) {
    const b = (0,path__WEBPACK_IMPORTED_MODULE_0__.basename)(relativePath);
    return b ? b : (0,path__WEBPACK_IMPORTED_MODULE_0__.basename)(path);
}


/***/ }),

/***/ 601880:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (/* binding */ withCustomize)
/* harmony export */ });
/* harmony import */ var _cocalc_server_settings_customize__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(280783);
/* harmony import */ var _cocalc_server_settings_customize__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_cocalc_server_settings_customize__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var lib_account_get_account__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(661879);
/* harmony import */ var lib_share_get_account_info__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(818164);
/* harmony import */ var _cocalc_server_projects_is_collaborator__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(954314);
/* harmony import */ var _cocalc_server_projects_is_collaborator__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_cocalc_server_projects_is_collaborator__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _cocalc_util_db_schema_site_defaults__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(16563);
/* harmony import */ var _cocalc_server_software_envs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(790775);
/* harmony import */ var _cocalc_server_software_envs__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_cocalc_server_software_envs__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _cocalc_util_db_schema__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(335783);
/* harmony import */ var _cocalc_util_db_schema__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_cocalc_util_db_schema__WEBPACK_IMPORTED_MODULE_6__);
/*
 *  This file is part of CoCalc: Copyright © 2021 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */ 






const revalidate = 30;
async function withCustomize(obj, options = {}) {
    let customize;
    try {
        // NOTE: important to make a (shallow) copy, since customize gets mutated below.
        customize = {
            ...await _cocalc_server_settings_customize__WEBPACK_IMPORTED_MODULE_0___default()()
        };
    } catch (_err) {
        // fallback to be empty; during static build
        // this happens.
        customize = {};
    }
    if (obj.context?.req != null) {
        const account_id = await (0,lib_account_get_account__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(obj.context.req);
        customize.isAuthenticated = !!account_id;
        if (account_id) {
            customize.account = {
                account_id,
                ...options.name ? await (0,lib_share_get_account_info__WEBPACK_IMPORTED_MODULE_2__/* .getName */ .o)(account_id) : undefined
            };
            // Also, if a project id is in the props and account_id is set, it's very
            // useful to know if the user is a collaborator on the project, since that
            // can impact a lot about how we display things.  This is typically used
            // for the share pages.
            const project_id = obj.props?.project_id;
            if (project_id) {
                customize.isCollaborator = await _cocalc_server_projects_is_collaborator__WEBPACK_IMPORTED_MODULE_3___default()({
                    account_id,
                    project_id
                });
            }
        }
    } else {
        customize.isAuthenticated = false;
    }
    customize.onCoCalcCom = customize.kucalc === _cocalc_util_db_schema_site_defaults__WEBPACK_IMPORTED_MODULE_4__.KUCALC_COCALC_COM;
    customize.noindex = obj.props?.unlisted ?? false;
    customize.imprintOrPolicies = (customize.imprint ?? "" + customize.policies ?? "") != "";
    customize.serverTime = Date.now();
    // this is used for creating new projects from a share
    const softwareEnvs = await (0,_cocalc_server_software_envs__WEBPACK_IMPORTED_MODULE_5__.getSoftwareEnvironments)("server");
    customize.defaultComputeImage = softwareEnvs?.default ?? _cocalc_util_db_schema__WEBPACK_IMPORTED_MODULE_6__.DEFAULT_COMPUTE_IMAGE;
    if (obj == null) {
        return {
            props: {
                customize
            }
        };
    }
    if (obj.revalidate != null) {
        obj.revalidate = Math.min(revalidate, obj.revalidate);
    }
    if (obj.props == null) {
        obj.props = {
            customize
        };
    } else {
        obj.props.customize = customize;
    }
    delete obj.context;
    return obj;
}


/***/ }),

/***/ 41998:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


/*
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(__webpack_require__(17763));
const misc_1 = __webpack_require__(477389);
const is_password_correct_1 = __importDefault(__webpack_require__(231899));
const has_password_1 = __importDefault(__webpack_require__(423640));
const random_key_1 = __webpack_require__(689685);
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

/***/ }),

/***/ 878474:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getAccountIdFromApiKey = exports.getApiKey = void 0;
const misc_1 = __webpack_require__(477389);
const manage_1 = __webpack_require__(41998);
function getApiKey(req) {
    const h = req.header("Authorization");
    if (h == null) {
        throw Error("You must provide authentication via an API key.");
    }
    const [type, user] = (0, misc_1.split)(h);
    switch (type) {
        case "Bearer":
            return user;
        case "Basic":
            return Buffer.from(user, "base64").toString().split(":")[0];
    }
    throw Error(`Unknown authorization type '${type}'`);
}
exports.getApiKey = getApiKey;
async function getAccountIdFromApiKey(req) {
    return await (0, manage_1.getAccountWithApiKey)(getApiKey(req));
}
exports.getAccountIdFromApiKey = getAccountIdFromApiKey;
//# sourceMappingURL=api.js.map

/***/ }),

/***/ 763599:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


/*
 *  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 }));
const pool_1 = __importDefault(__webpack_require__(17763));
const api_1 = __webpack_require__(878474);
const remember_me_1 = __webpack_require__(420818);
// Return account_id if they are signed in.
// If not, returns undefined.
// This is determined by looking in their cookie and checking
// who it identifies in the database.
async function getAccountId(req, noCache = false) {
    if (req == null)
        return;
    // caching a bit --  We thus want the query below to happen rarely.  We also
    // get expire field as well (since it is usually there) so that the result isn't empty
    // (hence not cached) when a cookie has expired.
    const hash = (0, remember_me_1.getRememberMeHash)(req);
    if (!hash) {
        // not signed in via a cookie.
        // What about an api key?
        if (req.header("Authorization")) {
            try {
                return await (0, api_1.getAccountIdFromApiKey)(req);
            }
            catch (_err) {
                // non-fatal, at least for now...
                return;
            }
        }
        return;
    }
    const pool = (0, pool_1.default)(noCache ? "short" : undefined);
    // important to use CHAR(127) instead of TEXT for 100x performance gain.
    const result = await pool.query("SELECT account_id, expire FROM remember_me WHERE hash = $1::CHAR(127)", [hash]);
    if (result.rows.length == 0) {
        return;
    }
    const { account_id, expire } = result.rows[0];
    if (expire <= new Date()) {
        // expired
        return;
    }
    return account_id;
}
exports["default"] = getAccountId;
//# sourceMappingURL=get-account.js.map

/***/ }),

/***/ 423640:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


/*
If the account with given id does not exist, throw an error.

Return true if the account with given id exists and has a password set.

Otherwise, return false... since auth is only doing via a passport.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const pool_1 = __importDefault(__webpack_require__(17763));
async function hasPassword(account_id) {
    const pool = (0, pool_1.default)("short");
    const { rows } = await pool.query("SELECT password_hash FROM accounts WHERE account_id=$1::UUID", [account_id]);
    if (rows.length == 0) {
        throw Error("no such account");
    }
    return !!rows[0].password_hash;
}
exports["default"] = hasPassword;
//# sourceMappingURL=has-password.js.map

/***/ }),

/***/ 233437:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
const crypto_1 = __webpack_require__(706113);
// This function is private and burried inside the password-hash
// library.  To avoid having to fork/modify that library, we've just
// copied it here.  We need it for remember_me cookies.
function hash(algorithm, salt, iterations, password) {
    // there are cases where createHmac throws an error, because "salt" is undefined
    if (algorithm == null || salt == null) {
        throw new Error(`undefined arguments: algorithm='${algorithm}' salt='${salt}'`);
    }
    iterations = iterations || 1;
    if (!isFinite(iterations) || iterations > 10000) {
        // If somebody could make their own cookie, they might set the number of iterations
        // to be very large and hang the server.
        throw Error("number of iterations invalid or too large");
    }
    let hash = password;
    for (let i = 1, end = iterations, asc = 1 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
        hash = (0, crypto_1.createHmac)(algorithm, salt).update(hash).digest("hex");
    }
    return algorithm + "$" + salt + "$" + iterations + "$" + hash;
}
exports["default"] = hash;
//# sourceMappingURL=hash.js.map

/***/ }),

/***/ 231899:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


/*
Returns true if the account with given id exists and the password
is correct for the account.  Returns false in all other cases.

NOTE: Of course some accounts don't even have a password, in which
case this will always return false.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const pool_1 = __importDefault(__webpack_require__(17763));
const password_hash_1 = __webpack_require__(939894);
async function isPasswordCorrect({ account_id, password, }) {
    const pool = (0, pool_1.default)();
    const { rows } = await pool.query("SELECT password_hash FROM accounts WHERE account_id=$1", [account_id]);
    if (rows.length == 0)
        return false;
    const { password_hash } = rows[0];
    if (!password_hash)
        return false;
    return (0, password_hash_1.verifyPassword)(password, password_hash);
}
exports["default"] = isPasswordCorrect;
//# sourceMappingURL=is-password-correct.js.map

/***/ }),

/***/ 420818:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getRememberMeHash = exports.deleteAllRememberMe = exports.deleteRememberMe = exports.createRememberMeCookie = exports.COOKIE_NAME = void 0;
const base_path_1 = __importDefault(__webpack_require__(19864));
const uuid_1 = __webpack_require__(385534);
const password_hash_1 = __importDefault(__webpack_require__(939894));
const pool_1 = __importDefault(__webpack_require__(17763));
const util_1 = __webpack_require__(532465);
const cookies_1 = __importDefault(__webpack_require__(429018));
const hash_1 = __importDefault(__webpack_require__(233437));
exports.COOKIE_NAME = `${base_path_1.default.length <= 1 ? "" : encodeURIComponent(base_path_1.default)}remember_me`;
// Create a remember me cookie for the given account_id and store
// it in the database.  The cookie is similar to using a server
// assigned random uuid-v4 as a password.  The user knows the
// uuid-v4, and we only store what it hashes to, so even if
// somebody gets our database, they can't make fake cookies and use
// them to sign in.
async function createRememberMeCookie(account_id, arg_ttl_s) {
    // compute the value and ttl_s:
    const session_id = (0, uuid_1.v4)();
    const hash_session_id = (0, password_hash_1.default)(session_id);
    const x = hash_session_id.split("$");
    const value = [x[0], x[1], x[2], session_id].join("$");
    const ttl_s = arg_ttl_s ?? 24 * 3600 * 30; // 30 days -- seems to work well, but this could be per user configurable, etc.
    // store the cookie in the database
    const pool = (0, pool_1.default)();
    await pool.query("INSERT INTO remember_me (hash, expire, account_id) VALUES($1::TEXT, $2::TIMESTAMP, $3::UUID)", [hash_session_id.slice(0, 127), (0, util_1.expireTime)(ttl_s), account_id]);
    return { value, ttl_s };
}
exports.createRememberMeCookie = createRememberMeCookie;
// delete the remember me database entry for the given hash
async function deleteRememberMe(hash) {
    const pool = (0, pool_1.default)();
    await pool.query("DELETE FROM remember_me WHERE hash=$1::TEXT", [
        hash.slice(0, 127),
    ]);
}
exports.deleteRememberMe = deleteRememberMe;
// delete all remember me cookies for the account
async function deleteAllRememberMe(account_id) {
    const pool = (0, pool_1.default)();
    await pool.query("DELETE FROM remember_me WHERE account_id=$1::UUID", [
        account_id,
    ]);
}
exports.deleteAllRememberMe = deleteAllRememberMe;
function getRememberMeHash(req) {
    const cookies = new cookies_1.default(req);
    const rememberMe = cookies.get(exports.COOKIE_NAME);
    if (!rememberMe) {
        return;
    }
    const x = rememberMe.split("$");
    if (x.length !== 4) {
        throw Error("badly formatted remember_me cookie");
    }
    return (0, hash_1.default)(x[0], x[1], parseInt(x[2]), x[3]).slice(0, 127);
}
exports.getRememberMeHash = getRememberMeHash;
//# sourceMappingURL=remember-me.js.map

/***/ }),

/***/ 954314:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const pool_1 = __importDefault(__webpack_require__(17763));
const misc_1 = __webpack_require__(477389);
async function isCollaborator({ account_id, project_id, }) {
    if (!(0, misc_1.is_valid_uuid_string)(account_id) || !(0, misc_1.is_valid_uuid_string)(project_id)) {
        throw Error("invalid input");
    }
    const pool = (0, pool_1.default)("long"); // fine to cache "yes, you're a collab" for a while
    const { rows } = await pool.query(`SELECT users#>'{${account_id},group}' AS group FROM projects WHERE project_id=\$1`, [project_id]);
    const group = rows[0]?.group;
    return group == "owner" || group == "collaborator";
}
exports["default"] = isCollaborator;
//# sourceMappingURL=is-collaborator.js.map

/***/ }),

/***/ 280783:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


/*
 *  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 }));
const site_defaults_1 = __webpack_require__(16563);
const get_strategies_1 = __importDefault(__webpack_require__(825556));
const server_settings_1 = __webpack_require__(567934);
const site_url_1 = __importDefault(__webpack_require__(295847));
const fallback = (a, b) => typeof a == "string" && a.length > 0 ? a : `${b}`;
/*
Create a Javascript object that describes properties of the server.
This is used on the next.js server landing pages and the share server
to customize their look and behavior.

This function is cached via the parameters in ./server-settings, i.e.,
for a few seconds.
*/
let cachedSettings = undefined;
let cachedCustomize = undefined;
async function getCustomize() {
    const [settings, strategies] = await Promise.all([(0, server_settings_1.getServerSettings)(), (0, get_strategies_1.default)()]);
    if (settings === cachedSettings && cachedCustomize != null) {
        return cachedCustomize;
    }
    cachedSettings = settings;
    cachedCustomize = {
        siteName: fallback(settings.site_name, "On Premises CoCalc"),
        siteDescription: fallback(settings.site_description, "Collaborative Calculation using Python, Sage, R, Julia, and more."),
        organizationName: settings.organization_name,
        organizationEmail: settings.organization_email,
        organizationURL: settings.organization_url,
        termsOfServiceURL: settings.terms_of_service_url,
        helpEmail: settings.help_email,
        contactEmail: fallback(settings.organization_email, settings.help_email),
        isCommercial: settings.commercial,
        kucalc: settings.kucalc,
        sshGateway: settings.ssh_gateway,
        sshGatewayDNS: settings.ssh_gateway_dns,
        anonymousSignup: settings.anonymous_signup,
        emailSignup: settings.email_signup,
        accountCreationInstructions: settings.account_creation_email_instructions,
        logoSquareURL: settings.logo_square,
        logoRectangularURL: settings.logo_rectangular,
        splashImage: settings.splash_image,
        shareServer: !!settings.share_server,
        // additionally restrict showing landing pages only in cocalc.com-mode
        landingPages: !!settings.landing_pages && settings.kucalc === site_defaults_1.KUCALC_COCALC_COM,
        googleAnalytics: settings.google_analytics,
        indexInfo: settings.index_info_html,
        imprint: settings.imprint,
        policies: settings.policies,
        // Is important for invite emails, password reset, etc. (e.g., so we can construct a url to our site).
        // This *can* start with http:// to explicitly use http instead of https, and can end
        // in something like :3594 to indicate a port.
        dns: settings.dns,
        // siteURL is derived from settings.dns and the basePath -- it combines the dns, https://
        // and the basePath.  It never ends in a slash.  This is used in practice for
        // things like invite emails, password reset, etc.
        siteURL: await (0, site_url_1.default)(settings.dns),
        zendesk: settings.zendesk_token &&
            settings.zendesk_username &&
            settings.zendesk_uri,
        // obviously only the public key here!
        stripePublishableKey: settings.stripe_publishable_key,
        // obviously only the public key here too!
        reCaptchaKey: settings.re_captcha_v3_publishable_key,
        // a sandbox project
        sandboxProjectId: settings.sandbox_project_id,
        // GitHub proxy project
        githubProjectId: settings.github_project_id,
        // public info about SSO strategies
        strategies,
    };
    return cachedCustomize;
}
exports["default"] = getCustomize;
//# sourceMappingURL=customize.js.map

/***/ }),

/***/ 295847:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {


var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const server_settings_1 = __webpack_require__(567934);
const base_path_1 = __importDefault(__webpack_require__(19864));
// Returns url of this site in terms of the base path (determined
// by an env variable when server starts) and the "Domain name"
// setting of site settings.  This URL does NOT end in a /
async function siteURL(dns) {
    if (!dns) {
        dns = (await (0, server_settings_1.getServerSettings)()).dns?.toLowerCase();
    }
    if (!dns) {
        dns = "localhost";
    }
    if (!dns.startsWith("http")) {
        dns = "https://" + dns;
    }
    return `${dns}${base_path_1.default == "/" ? "" : base_path_1.default}`;
}
exports["default"] = siteURL;
//# sourceMappingURL=site-url.js.map

/***/ }),

/***/ 5011:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ssoDispayedName = void 0;
// Authentication and SSO related utility functions or data shared between all packages
const misc_1 = __webpack_require__(477389);
function ssoDispayedName({ display, name, // name of strategy
 }) {
    return display ?? (name === "github" ? "GitHub" : (0, misc_1.capitalize)(name));
}
exports.ssoDispayedName = ssoDispayedName;
//# sourceMappingURL=auth.js.map

/***/ }),

/***/ 328577:
/***/ ((__unused_webpack_module, exports) => {


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DOC_CLOUD_STORAGE_URL = exports.DUMMY_SECRET = void 0;
exports.DUMMY_SECRET = `[SECRET HIDDEN]`;
exports.DOC_CLOUD_STORAGE_URL = "https://doc.cocalc.com/project-settings.html#cloud-storage-remote-file-systems";
//# sourceMappingURL=project.js.map

/***/ }),

/***/ 573433:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


/*
 *  This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.EDITOR_COLOR_SCHEMES = exports.EDITOR_BINDINGS = void 0;
const types_1 = __webpack_require__(730483);
const name_rules_1 = __webpack_require__(988772);
const index_1 = __webpack_require__(335783);
const defaults_1 = __webpack_require__(912707);
(0, types_1.Table)({
    name: "accounts",
    fields: {
        account_id: {
            type: "uuid",
            desc: "The uuid that determines the user account",
            render: { type: "account" },
            title: "Account",
        },
        created: {
            type: "timestamp",
            desc: "When the account was created.",
        },
        created_by: {
            type: "string",
            pg_type: "inet",
            desc: "IP address that created the account.",
        },
        creation_actions_done: {
            type: "boolean",
            desc: "Set to true after all creation actions (e.g., add to projects) associated to this account are succesfully completed.",
        },
        password_hash: {
            type: "string",
            pg_type: "VARCHAR(173)",
            desc: "hash of the password",
        },
        deleted: {
            type: "boolean",
            desc: "True if the account has been deleted.",
        },
        name: {
            type: "string",
            pg_type: "VARCHAR(39)",
            desc: "The username of this user.  This is optional but globally unique across all accoutns *and* organizations.  It can be between 1 and 39 characters from a-z A-Z 0-9 - and must not start with a dash.",
        },
        email_address: {
            type: "string",
            pg_type: "VARCHAR(254)",
            desc: "The email address of the user.  This is optional, since users may instead be associated to passport logins.",
            unique: true,
            render: { type: "email_address" },
        },
        email_address_before_delete: {
            type: "string",
            desc: "The email address of the user before they deleted their account.",
        },
        email_address_verified: {
            type: "map",
            desc: 'Verified email addresses as { "email@addre.ss" : <timestamp>, ... }',
        },
        email_address_challenge: {
            type: "map",
            desc: 'Contains random token for verification of an address: {"email": "...", "token": <random>, "time" : <timestamp for timeout>}',
        },
        email_address_problem: {
            type: "map",
            desc: 'Describes a problem with a given email address. example: { "wrong@email.address" : { "type": "bounce", "time": "2018-...", "mesg": "554 5.7.1 <....>: Recipient address rejected: Access denied, user does not exist", "status": <status code>}}',
        },
        passports: {
            type: "map",
            desc: 'Map from string ("[strategy]-[id]") derived from passport name and id to the corresponding profile',
        },
        editor_settings: {
            type: "map",
            desc: "Description of configuration settings for the editor.  See the user_query get defaults.",
        },
        other_settings: {
            type: "map",
            desc: "Miscellaneous overall configuration settings for SMC, e.g., confirm close on exit?",
        },
        first_name: {
            type: "string",
            pg_type: "VARCHAR(254)",
            desc: "The first name of this user.",
            render: { type: "text", maxLength: 254, editable: true },
        },
        last_name: {
            type: "string",
            pg_type: "VARCHAR(254)",
            desc: "The last name of this user.",
            render: { type: "text", maxLength: 254, editable: true },
        },
        banned: {
            type: "boolean",
            desc: "Whether or not this user is banned.",
        },
        terminal: {
            type: "map",
            desc: "Settings for the terminal, e.g., font_size, etc. (see get query)",
        },
        autosave: {
            type: "integer",
            desc: "File autosave interval in seconds",
        },
        evaluate_key: {
            type: "string",
            desc: "Key used to evaluate code in Sage worksheet.",
        },
        font_size: {
            type: "integer",
            desc: "Default font-size for the editor, jupyter, etc. (px)",
        },
        last_active: {
            type: "timestamp",
            desc: "When this user was last active.",
        },
        stripe_customer_id: {
            type: "string",
            desc: "The id of this customer in the stripe billing system.",
        },
        stripe_customer: {
            type: "map",
            desc: "Information about customer from the point of view of stripe (exactly what is returned by stripe.customers.retrieve).",
        },
        coupon_history: {
            type: "map",
            desc: "Information about which coupons the customer has used and the number of times",
        },
        profile: {
            type: "map",
            desc: "Information related to displaying an avatar for this user's location and presence in a document or chatroom.",
        },
        groups: {
            type: "array",
            pg_type: "TEXT[]",
            desc: "Array of groups that this user belongs to; usually empty.  The only group right now is 'admin', which grants admin rights.",
        },
        ssh_keys: {
            type: "map",
            desc: "Map from ssh key fingerprints to ssh key objects.",
        },
        api_key: {
            type: "string",
            desc: "Optional API key that grants full API access to anything this account can access. Key is of the form 'sk_9QabcrqJFy7JIhvAGih5c6Nb', where the random part is 24 characters (base 62).",
            unique: true,
        },
        sign_up_usage_intent: {
            type: "string",
            desc: "What user intended to use CoCalc for at sign up",
        },
        lti_id: {
            type: "array",
            pg_type: "TEXT[]",
            desc: "LTI ISS and user ID",
        },
        lti_data: {
            type: "map",
            desc: "extra information related to LTI",
        },
        unlisted: {
            type: "boolean",
            desc: "If true then exclude user for full name searches (but not exact email address searches).",
        },
    },
    rules: {
        desc: "All user accounts.",
        primary_key: "account_id",
        // db_standby: "unsafe",
        pg_indexes: [
            "(lower(first_name) text_pattern_ops)",
            "(lower(last_name)  text_pattern_ops)",
            "created_by",
            "created",
            "last_active DESC NULLS LAST",
            "lti_id",
            "unlisted",
            "((passports IS NOT NULL))",
            "((ssh_keys IS NOT NULL))", // used by ssh-gateway to speed up getting all users
        ],
        crm_indexes: [
            "(lower(first_name) text_pattern_ops)",
            "(lower(last_name)  text_pattern_ops)",
            "(lower(email_address)  text_pattern_ops)",
            "created",
            "last_active DESC NULLS LAST",
        ],
        pg_unique_indexes: [
            "api_key",
            "LOWER(name)", // ensure user-assigned name is case sensitive globally unique
        ],
        // and this index is just a step in that direction; full uniquness must be
        // checked as an extra step.
        user_query: {
            get: {
                throttle_changes: 500,
                pg_where: [{ "account_id = $::UUID": "account_id" }],
                fields: {
                    account_id: null,
                    email_address: null,
                    lti_id: null,
                    email_address_verified: null,
                    email_address_problem: null,
                    editor_settings: {
                        /* NOTE: there is a editor_settings.jupyter = { kernel...} that isn't documented here. */
                        strip_trailing_whitespace: false,
                        show_trailing_whitespace: true,
                        line_wrapping: true,
                        line_numbers: true,
                        jupyter_line_numbers: false,
                        smart_indent: true,
                        electric_chars: true,
                        match_brackets: true,
                        auto_close_brackets: true,
                        code_folding: true,
                        match_xml_tags: true,
                        auto_close_xml_tags: true,
                        auto_close_latex: true,
                        spaces_instead_of_tabs: true,
                        multiple_cursors: true,
                        track_revisions: true,
                        extra_button_bar: true,
                        build_on_save: true,
                        first_line_number: 1,
                        indent_unit: 4,
                        tab_size: 4,
                        bindings: "standard",
                        theme: "default",
                        undo_depth: 300,
                        jupyter_classic: false,
                        jupyter_window: false,
                        disable_jupyter_windowing: false,
                        show_exec_warning: true,
                        physical_keyboard: "default",
                        keyboard_variant: "",
                        ask_jupyter_kernel: true,
                        disable_jupyter_virtualization: false,
                    },
                    other_settings: {
                        katex: true,
                        confirm_close: false,
                        mask_files: true,
                        page_size: 500,
                        standby_timeout_m: 5,
                        default_file_sort: "time",
                        [defaults_1.NEW_FILENAMES]: defaults_1.DEFAULT_NEW_FILENAMES,
                        show_global_info2: null,
                        first_steps: true,
                        newsletter: false,
                        time_ago_absolute: false,
                        // if true, do not show warning when using non-member projects
                        no_free_warnings: false,
                        allow_mentions: true,
                        dark_mode: false,
                        dark_mode_brightness: 100,
                        dark_mode_contrast: 90,
                        dark_mode_sepia: 0,
                        dark_mode_grayscale: 0,
                    },
                    name: null,
                    first_name: "",
                    last_name: "",
                    terminal: {
                        font_size: defaults_1.DEFAULT_FONT_SIZE,
                        color_scheme: "default",
                        font: "monospace",
                    },
                    autosave: 45,
                    evaluate_key: "Shift-Enter",
                    font_size: defaults_1.DEFAULT_FONT_SIZE,
                    passports: {},
                    groups: [],
                    last_active: null,
                    stripe_customer: null,
                    coupon_history: null,
                    profile: {
                        image: undefined,
                        color: "rgb(170,170,170)",
                    },
                    ssh_keys: {},
                    created: null,
                    unlisted: false,
                },
            },
            set: {
                fields: {
                    account_id: "account_id",
                    name: true,
                    editor_settings: true,
                    other_settings: true,
                    first_name: true,
                    last_name: true,
                    terminal: true,
                    autosave: true,
                    evaluate_key: true,
                    font_size: true,
                    profile: true,
                    ssh_keys: true,
                    sign_up_usage_intent: true,
                    unlisted: true,
                },
                async check_hook(db, obj, account_id, _project_id, cb) {
                    if (obj["name"] != null) {
                        // NOTE: there is no way to unset/remove a username after one is set...
                        try {
                            (0, name_rules_1.checkAccountName)(obj["name"]);
                        }
                        catch (err) {
                            cb(err.toString());
                            return;
                        }
                        const id = await db.nameToAccountOrOrganization(obj["name"]);
                        if (id != null && id != account_id) {
                            cb(`name "${obj["name"]}" is already taken by another organization or account`);
                            return;
                        }
                    }
                    // Hook to truncate some text fields to at most 254 characters, to avoid
                    // further trouble down the line.
                    for (const field of ["first_name", "last_name", "email_address"]) {
                        if (obj[field] != null) {
                            obj[field] = obj[field].slice(0, 254);
                            if (field != "email_address" && !obj[field]) {
                                // name fields can't be empty
                                cb(`${field} must be nonempty`);
                                return;
                            }
                        }
                    }
                    cb();
                },
            },
        },
    },
});
exports.EDITOR_BINDINGS = {
    standard: "Standard",
    sublime: "Sublime",
    vim: "Vim",
    emacs: "Emacs",
};
exports.EDITOR_COLOR_SCHEMES = {
    default: "Default",
    "3024-day": "3024 day",
    "3024-night": "3024 night",
    abcdef: "abcdef",
    //'ambiance-mobile'         : 'Ambiance mobile'  # doesn't highlight python, confusing
    ambiance: "Ambiance",
    "base16-dark": "Base 16 dark",
    "base16-light": "Base 16 light",
    bespin: "Bespin",
    blackboard: "Blackboard",
    cobalt: "Cobalt",
    colorforth: "Colorforth",
    darcula: "Darcula",
    dracula: "Dracula",
    "duotone-dark": "Duotone Dark",
    "duotone-light": "Duotone Light",
    eclipse: "Eclipse",
    elegant: "Elegant",
    "erlang-dark": "Erlang dark",
    "gruvbox-dark": "Gruvbox-Dark",
    hopscotch: "Hopscotch",
    icecoder: "Icecoder",
    idea: "Idea",
    isotope: "Isotope",
    "lesser-dark": "Lesser dark",
    liquibyte: "Liquibyte",
    lucario: "Lucario",
    material: "Material",
    mbo: "mbo",
    "mdn-like": "MDN like",
    midnight: "Midnight",
    monokai: "Monokai",
    neat: "Neat",
    neo: "Neo",
    night: "Night",
    "oceanic-next": "Oceanic next",
    "panda-syntax": "Panda syntax",
    "paraiso-dark": "Paraiso dark",
    "paraiso-light": "Paraiso light",
    "pastel-on-dark": "Pastel on dark",
    railscasts: "Railscasts",
    rubyblue: "Rubyblue",
    seti: "Seti",
    shadowfox: "Shadowfox",
    "solarized dark": "Solarized dark",
    "solarized light": "Solarized light",
    ssms: "ssms",
    "the-matrix": "The Matrix",
    "tomorrow-night-bright": "Tomorrow Night - Bright",
    "tomorrow-night-eighties": "Tomorrow Night - Eighties",
    ttcn: "ttcn",
    twilight: "Twilight",
    "vibrant-ink": "Vibrant ink",
    "xq-dark": "Xq dark",
    "xq-light": "Xq light",
    yeti: "Yeti",
    zenburn: "Zenburn",
};
(0, types_1.Table)({
    name: "crm_accounts",
    rules: {
        virtual: "accounts",
        primary_key: "account_id",
        user_query: {
            get: {
                pg_where: [],
                admin: true,
                fields: index_1.SCHEMA.accounts.user_query?.get?.fields ?? {},
            },
            set: {
                admin: true,
                fields: {
                    account_id: true,
                    name: true,
                    first_name: true,
                    last_name: true,
                    autosave: true,
                    font_size: true,
                },
            },
        },
    },
    fields: index_1.SCHEMA.accounts.fields,
});
(0, types_1.Table)({
    name: "crm_agents",
    rules: {
        virtual: "accounts",
        primary_key: "account_id",
        user_query: {
            get: {
                // There where condition restricts to only admin accounts for now.
                // TODO: Later this will change to 'crm'=any(groups) or something like that.
                pg_where: ["'admin'=any(groups)"],
                admin: true,
                fields: index_1.SCHEMA.accounts.user_query?.get?.fields ?? {},
            },
        },
    },
    fields: index_1.SCHEMA.accounts.fields,
});
//# sourceMappingURL=accounts.js.map

/***/ }),

/***/ 988772:
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {


/* Checks that name satisfies the following constraints
Inspired by -- https://github.com/isiahmeadows/github-limits



Each function checks the basic rules, but NOT for uniqueness,
which requires a DB query.

If a rule fails, throws an Error.
*/
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.checkPublicPathName = exports.checkProjectName = exports.checkAccountName = exports.isReserved = void 0;
const misc_1 = __webpack_require__(477389);
function isReserved(name) {
    return RESERVED.has(name.toLowerCase());
}
exports.isReserved = isReserved;
/*
Account name:
 - between 1 and 39 characters
 - doesn't start with a -
 - only includes the characters 0-9,a-z,A-Z,-
 - Don't allow uuid's.
 - cannot include consecutive hyphens
*/
function checkAccountName(name) {
    if (name.length < 1) {
        throw Error("name must have at least 1 character");
    }
    if (name.length > 39) {
        throw Error("name must have at most 39 characters");
    }
    if ((0, misc_1.is_valid_uuid_string)(name)) {
        throw Error("name must not be a v4 UUID");
    }
    if (name.includes("--")) {
        throw Error("name must not contain consecutive hyphens");
    }
    if (!/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i.test(name)) {
        throw Error("name must contain only a-z,A-Z,0-9, or -, and not start with hyphen.");
    }
    // Check for reserved names.
    if (isReserved(name)) {
        throw Error(`username "${name}" is reserved -- not available`);
    }
}
exports.checkAccountName = checkAccountName;
/*
Project name:

- Max length: 100 characters
- All characters must be either a hyphen (-), a period (.), or alphanumeric
- Unique amongst projects with given owner
- Don't allow uuid's.
*/
function checkProjectName(name) {
    if (name.length < 1) {
        throw Error("name must have at least 1 character");
    }
    if (name.length > 100) {
        throw Error("name must have at most 100 characters");
    }
    if ((0, misc_1.is_valid_uuid_string)(name)) {
        throw Error("name must not be a v4 UUID");
    }
    if (!/^[\.a-z\d](?:[\.a-z\d]|-(?=[\.a-z\d])){0,99}$/i.test(name)) {
        throw Error("name must contain only a-z,A-Z,0-9, . or -, and not start with hyphen or have spaces.");
    }
}
exports.checkProjectName = checkProjectName;
/*
Public path name:

- Max length: 100 characters
- All characters must be either a hyphen (-), a period (.), or alphanumeric
- Unique amongst public paths in a given project.
- Don't allow uuid's.
*/
function checkPublicPathName(name) {
    if (name.length < 1) {
        throw Error("name must have at least 1 character");
    }
    if (name.length > 100) {
        throw Error("name must have at most 100 characters");
    }
    if ((0, misc_1.is_valid_uuid_string)(name)) {
        throw Error("name must not be a v4 UUID");
    }
    if (!/^[\.a-z\d](?:[\.a-z\d]|-(?=[\.a-z\d])){0,99}$/i.test(name)) {
        throw Error("name must contain only a-z,A-Z,0-9, . or -, and not start with hyphen or have spaces.");
    }
    // Check for reserved names.  We also ban these for public path names, since
    // we want to have URL's like
    //    https://cocalc.com/sagemathinc/myproject/settings -- configure settings
    //    https://cocalc.com/sagemathinc/myproject/files -- browse all files directly
    //    snapshots, timetravel, new, search, etc...
    if (isReserved(name)) {
        throw Error(`path name "${name}" is reserved -- not available`);
    }
}
exports.checkPublicPathName = checkPublicPathName;
// Combined words from what we use, https://www.quora.com/How-do-sites-prevent-vanity-URLs-from-colliding-with-future-features
// and https://github.com/Mottie/github-reserved-names/blob/master/reserved-names.json and
// https://github.com/Mottie/github-reserved-names and random other things.
// If you add more and want to clean this up in the console, this may be helpful:
//       Array.from(RESERVED).sort().join(' ')
const RESERVED = new Set(`0 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 500 501 502 503 504 505 506 507 508 509 510 511 about access account accounts activate activities activity ad add address adm admin administration administrator ads adult advertising advisories affiliate affiliates ajax alive all alpha analysis analytics android anon anonymous any api app apps archive archives article articles asct asset assets atom attributes auth authentication avatar backup balancer-manager banner banners beta better billing bin blob blobs blog blogs board book bookmark bot bots bounty branches bug business businesses c cache cadastro calendar call campaign cancel captcha career careers cart case-studies categories category cdn central certification cgi cgi-bin changelog chat check checking checkout cla client cliente clients cloud cocalc cocksucker code codereview collection collections comercial comment comments commit commits communities community companies company compare compras config configuration connect contact contact-us contact_us contactus contest contribute contributing cookbook cookies corp coupons create crm css cunt customer customer-stories customers customize dashboard dashboards data db default delete demo design designer destroy dev devel develop developer developers diagram diary dict dictionary die diff dir direct_messages directory discover discussions dist doc docs documentation domain download downloads downtime ecommerce edit editor editors edu education email embed employment empty end enterprise entries entry error errors eval event events exit explore facebook faq favorite favorites feature featured features feed feedback feeds file files first fixtures flash fleet fleets flog follow followers following font fonts forgot forked form forum forums founder free friend friends ftp fuck gadget gadgets game games garage get ghost gift gifts gist gists github github.com gitlab gitlab.com grafana graph graphs group groups guest guests guide guides help help-wanted home homepage hooks host hosting hostmaster hostname hovercards howto hpg html http httpd https hub i iamges icon icons id idea ideas identity image images imap img inbox include includes index indice individual info information inquiry instagram integration interfaces intern internal intranet introduction invalid-email-address investors invitations invite invoice ipad iphone irc is issue issues it item items java javascript job jobs join journal journals js json jump knowledgebase lab labs language languages last launch layouts ldap-status learn legal library license licenses link links linux list listings lists log log-in log-out log_in log_out login logos logout logs m mac mail mail1 mail2 mail3 mail4 mail5 mailer mailing maintenance malware man manager manual map maps marketing marketplace master me media member members mention mentioned mentioning mentions message messages messenger metrics microblog microblogs migrating milestones mine mirrors mis misc mob mobile module modules monitor motherfucker movie movies mp3 msg msn music musicas mx my mysql name named nan navi navigation net network new news newsletter nick nickname nocodb node nodes none nonprofit nonprofits notes notices noticias notification notifications notify ns ns1 ns10 ns2 ns3 ns4 ns5 ns6 ns7 ns8 ns9 null oauth oauth_clients offer offers office official old online open-source openid operator order orders organisations organization organizations orgs overview owner owners page pager pages panel partners password password-reset payment payments perl personal phone photo photoalbum photos php phpmyadmin phppgadmin phpredisadmin pic pics ping piss plan plans plugin plugins policies policy poll polls pop pop3 popular popularity portal post postfix postmaster posts pr premium press price pricing primus privacy privacy-policy privacy_policy privacypolicy private processes product products professional profile profiles project projects prometheus promo pub public pulls purpose put python query random ranking raw rdf rdfs read readme recent recommendations recruit recruitment redeem register registration release releases remove render replies reply report reports repositories repository req request requests reset resources restore revert roc root rss ruby rule sag sagemath sagemathinc sale sales sample samples save save-net-neutrality saved school scraping script scripts search secure security self send server server-info server-status service services session sessions setting settings setup share shareholders shit shop show showcases sign-in sign-up sign_in sign_up signin signout signup site sitemap sites smartphone smtp snapshots software soporte source spam spec special sponsors sql src ssh ssl ssladmin ssladministrator sslwebmaster sso staff stage staging star starred stars start stat state static statistics stats status statuses storage store stores stories style styleguide stylesheet stylesheets subdomain subscribe subscriptions suggest suggestion suggestions suporte support survey surveys suspended svn swf sys sysadmin sysadministrator system tablet tablets tag talk talks task tasks teach teacher teachers teaching team teams tech telnet template templates ten term terms terms-of-service terms_of_service termsofservice test test1 test2 test3 teste testing tests theme themes thread threads timeline timetravel tits tmp todo tool tools top topic topics tos tour train training translations tree trending trends try tutorial tutorials tux tv twitter twittr undef unfollow unsubscribe update updates upload uploads url usage user username users usuario vendas ver version video videos visitor visualization w watch watching weather web webapp webhook webhooks webmail webmaster website websites welcome widget widgets wiki win windows word work works works-with workshop ww wws www www0 www1 www2 www3 www4 www5 www6 www7 www8 www9 wwws wwww xfn xml xmpp xpg xxx yaml year yml you yourdomain yourname yoursite yourusername`.split(/\s+/));
//# sourceMappingURL=name-rules.js.map

/***/ })

};
;