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

/***/ 559459:
/***/ ((__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__(877967);
/* 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()));


/***/ }),

/***/ 259972:
/***/ (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__(541808));
const misc_1 = __webpack_require__(854006);
const is_password_correct_1 = __importDefault(__webpack_require__(956897));
const has_password_1 = __importDefault(__webpack_require__(999591));
const random_key_1 = __webpack_require__(630900);
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

/***/ }),

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


Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getAccountIdFromApiKey = exports.getApiKey = void 0;
const misc_1 = __webpack_require__(854006);
const manage_1 = __webpack_require__(259972);
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

/***/ }),

/***/ 877967:
/***/ (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__(541808));
const api_1 = __webpack_require__(912203);
const remember_me_1 = __webpack_require__(820540);
// 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

/***/ }),

/***/ 999591:
/***/ (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__(541808));
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

/***/ }),

/***/ 956897:
/***/ (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__(541808));
const password_hash_1 = __webpack_require__(987909);
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

/***/ })

};
;