Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/next/lib/share/get-account-info.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import getPool, { timeInSeconds } from "@cocalc/database/pool";6import { isUUID } from "./util";7import { PublicPath } from "./types";8import getAccountId from "lib/account/get-account";910interface AccountInfo {11account_id: string;12first_name: string;13last_name: string;14name: string;15publicPaths: PublicPath[];16}1718export default async function getAccountInfo(19account_id: string,20req21): Promise<AccountInfo> {22return {23account_id,24...(await getName(account_id)),25publicPaths: await getPublicPaths(account_id, req),26};27}2829export async function getName(account_id: string): Promise<{30first_name: string;31last_name: string;32name: string;33email_address: string;34is_anonymous: boolean;35}> {36if (!isUUID(account_id)) {37throw Error("invalid UUID");38}39const pool = getPool("long");4041// Get the database entry42const { rows } = await pool.query(43"SELECT name, first_name, last_name, email_address, passports FROM accounts WHERE account_id=$1",44[account_id]45);46if (rows.length == 0) {47throw Error("no such user");48}49const is_anonymous = !rows[0].email_address && !rows[0].passports;50return {51first_name: rows[0].first_name,52last_name: rows[0].last_name,53name: rows[0].name,54email_address: rows[0].email_address,55is_anonymous,56};57}5859async function getPublicPaths(60account_id: string,61req // used to get account_id of requester to see if we should include unlisted and disabled public_paths62): Promise<PublicPath[]> {63if (!isUUID(account_id)) {64// VERY important to check this because we substitute the account_id65// into the query string directly, and this is input directly from the user!66throw Error("invalid UUID");67}68const pool = getPool("medium");6970// Returns public paths for which account_id is a collaborator on the project and they have71// actively used the project at some point.72// We sort from most recently edited.73const query = `SELECT public_paths.id as id, public_paths.path as path, public_paths.description as description,74public_paths.disabled as disabled, public_paths.unlisted as unlisted, public_paths.vhost as vhost, public_paths.authenticated as authenticated,75(SELECT COUNT(*)::INT FROM public_path_stars WHERE public_path_id=public_paths.id) AS stars,76public_paths.counter::INT AS counter,77${timeInSeconds(78"public_paths.last_edited",79"last_edited"80)} 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`;81const { rows } = await pool.query(query);82// If there are any disabled or unlisted public_paths, we also get the id of the requestor so we can filter them out.83return await filterNonPublicAndNotAuthenticated(rows, account_id, req);84}8586async function filterNonPublicAndNotAuthenticated(87rows: PublicPath[],88account_id: string,89req90): Promise<PublicPath[]> {91const v: any[] = [];92let client_id: string | undefined = undefined;93for (const row of rows) {94if (!row.disabled && !row.unlisted && !row.authenticated) {95v.push(row);96continue;97}98if (client_id == null) {99client_id = (await getAccountId(req)) ?? "";100}101if (client_id == account_id) {102v.push(row);103} else if (row.authenticated === true && client_id !== "") {104v.push(row);105}106}107return v;108}109110111