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/proxy/get-public-path.ts
Views: 687
/*1Supported proxy schema should be mostly consistent with (and an extension of) nbviewer.org:23`url/example.com/thingy...` or `gist/user/id` or `github/owner/repo...`, etc.45Three options handled right now; anything else is an error. The path must uniquely determine6what is publicly shared (at some unit), and it's nice if it is useful (e.g., for url's and gists).78- github/cocalc/sagemathinc/... --> 'github/cocalc/sagemathinc'; i.e., the github repo maps 1:1 to cocalc public path.9- gist/darribas/4121857 --> 'gist/4121857/guardian_gaza.ipynb'; here guardian_gaza.ipynb is the first filename hosted10in the gist, and requires api call to github to get it. This uniquely determines the gist *and* tells us what type of file11it contains so we can render it.12- url/wstein.org/Tables/modjac/curves.txt --> 'url/wstein.org/Tables/modjac/curves.txt'; path equals the url, since this is13completely generic and there is nothing further we could do.1415*/1617import getProxyProjectId from "lib/share/proxy/project";18import getPool from "@cocalc/database/pool";19import * as sha1 from "sha1";20import { fileInGist } from "./api";2122export function shouldUseProxy(owner: string): boolean {23return owner == "github" || owner == "gist";24}2526const QUERY = `SELECT id, project_id, path, url, description, counter::INT, last_edited,27(SELECT COUNT(*)::INT FROM public_path_stars WHERE public_path_id=id) AS stars28FROM public_paths WHERE `;2930export default async function getProxyPublicPath({31id,32project_id,33path,34url,35description,36}: {37id?: string;38url?: string;39project_id?: string;40path?: string;41description?: string;42}): Promise<{43id: string;44project_id: string;45path: string;46url: string;47counter?: number;48stars: number;49last_edited: Date;50description?: string;51}> {52const pool = getPool("short");53if (id != null) {54// id is given, so return public_path with that id, if there is one.55const { rows } = await pool.query(QUERY + " id = $1", [id]);56if (rows.length > 0) {57return rows[0];58}59}60if (url != null) {61// url is given, so return public_path with that url, if already known.62const { rows } = await pool.query(QUERY + " url = $1", [url]);63if (rows.length > 0) {64return rows[0];65}66}67if (project_id == null) {68// this is the unique project used for all url proxying functionality; if not given,69// we just look it up for convenience.70project_id = await getProxyProjectId();71}72if (id == null && path != null) {73// if id not given but path is, then we can compute the id from project_id and path, since it's derived from them.74id = sha1(project_id + path);75// try based on the id, which we now know:76const { rows } = await pool.query(QUERY + " id = $1", [id]);77if (rows.length > 0) {78return rows[0];79}80}8182// We need to create this public_path and return that.83if (!url) {84// There is no possible way to create a public_path associated to85// proxying a URL without knowing the URL.86throw Error("url must be specified in order to create public_path");87}88// We can assume url is known.89if (path == null) {90path = await getPath(url);91}9293if (id == null) {94id = sha1(project_id + path);95}96if (id == null) throw Error("bug"); // not possible.9798// It could still be that the path with this id is in the database.99// Example is gist/4121857 and gist/darribas/4121857 resolve to same record,100// but initial search for 'gist/4121857' does not find anything.101// id is given, so return public_path with that id, if there is one.102const { rows } = await pool.query(QUERY + " id = $1", [id]);103if (rows.length > 0) {104return rows[0];105}106107let publicPathUrl;108if (url.startsWith("github/")) {109// URL to the repository, not the exact path being requested.110publicPathUrl = url.split("/").slice(0, 3).join("/");111} else {112publicPathUrl = url;113}114115const now = new Date();116await pool.query(117"INSERT INTO public_paths (id, url, project_id, path, description, last_edited, last_saved, created) VALUES($1, $2, $3, $4, $5, $6, $7, $8)",118[id, publicPathUrl, project_id, path, description, now, now, now]119);120return {121id,122url,123project_id,124path,125description,126last_edited: now,127counter: 0,128stars: 0,129};130}131132async function getPath(url: string) {133if (url.startsWith("github/")) {134const v = url.split("/");135if (v.length < 3) {136throw Error(`invalid url - ${url} - must at least specify repo`);137}138return v.slice(0, 3).join("/");139}140if (url.startsWith("url/")) {141return url;142}143if (url.startsWith("gist/")) {144const v = url.split("/");145return await fileInGist(v.length >= 3 ? v[2] : v[1]);146}147throw Error(`unknown proxy url schema -- ${url}`);148}149150151