UNPKG

@cocalc/hub

Version:
101 lines 4.13 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const lru_cache_1 = __importDefault(require("lru-cache")); const async_utils_1 = require("@cocalc/util/async-utils"); const logger_1 = __importDefault(require("../logger")); const database_1 = require("../servers/database"); const { user_has_write_access_to_project, user_has_read_access_to_project, } = require("../access"); const hash_1 = __importDefault(require("@cocalc/server/auth/hash")); const add_user_to_project_1 = __importDefault(require("@cocalc/server/projects/add-user-to-project")); const is_sandbox_1 = __importDefault(require("@cocalc/server/projects/is-sandbox")); const winston = (0, logger_1.default)("proxy: has-access"); // 5 minute cache: grant "yes" for a while const yesCache = new lru_cache_1.default({ max: 20000, maxAge: 1000 * 60 * 5 }); // 10 second cache: recheck "no" more frequently const noCache = new lru_cache_1.default({ max: 20000, maxAge: 1000 * 10 }); async function hasAccess(opts) { if (opts.isPersonal) { // In personal mode, anyone who can access localhost has full // access to everything, since this is meant to be used on // single-user personal computer. return true; } const { project_id, remember_me, type } = opts; const key = project_id + remember_me + type; for (const cache of [yesCache, noCache]) { if (cache.has(key)) return !!cache.get(key); } // not cached, so we have to determine access. let access; const dbg = (m) => { winston.debug(`(${type} access to ${project_id}): ${m}`); }; try { dbg("get remember_me message"); const x = remember_me.split("$"); const hash = (0, hash_1.default)(x[0], x[1], parseInt(x[2]), x[3]); const signed_in_mesg = await (0, async_utils_1.callback2)(database_1.database.get_remember_me, { hash, cache: true, }); if (signed_in_mesg == null) { throw Error("not signed in"); } const { account_id, email_address } = signed_in_mesg; dbg(`account_id="${account_id}", email_address="${email_address}"`); dbg(`now check if user has ${type} access to project`); if (type === "write") { access = await (0, async_utils_1.callback2)(user_has_write_access_to_project, { database: database_1.database, project_id, account_id, }); if (!access) { // if the project is a sandbox project, we add the user as a collaborator // and grant access. if (await (0, is_sandbox_1.default)(project_id)) { dbg("granting sandbox access"); await (0, add_user_to_project_1.default)({ project_id, account_id }); access = true; } } if (access) { // Record that user is going to actively access // this project. This is important since it resets // the idle timeout. database_1.database.touch({ account_id, project_id, }); } } else if (type == "read") { access = await (0, async_utils_1.callback2)(user_has_read_access_to_project, { database: database_1.database, project_id, account_id, }); } else { throw Error(`invalid access type ${type}`); } } catch (err) { dbg(`error trying to determine access; denying for now -- ${err}`); access = false; } dbg(`determined that access=${access}`); if (access) { yesCache.set(key, access); } else { noCache.set(key, access); } return access; } exports.default = hasAccess; //# sourceMappingURL=check-for-access-to-project.js.map