CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/next/pages/api/v2/projects/copy-path.ts
Views: 687
1
/*
2
API endpoint to copy a path from one project to another (or from public files to
3
a project) or within a project.
4
5
This requires the user to be signed in with appropriate access.
6
7
See "@cocalc/server/projects/control/base" for params.
8
*/
9
import getAccountId from "lib/account/get-account";
10
import { getProject } from "@cocalc/server/projects/control";
11
import { isValidUUID } from "@cocalc/util/misc";
12
import getPool from "@cocalc/database/pool";
13
import isCollaborator from "@cocalc/server/projects/is-collaborator";
14
import getParams from "lib/api/get-params";
15
16
export default async function handle(req, res) {
17
const params = getParams(req);
18
19
const error = checkParams(params);
20
if (error) {
21
res.json({ error });
22
return;
23
}
24
25
const {
26
public_id,
27
path,
28
src_project_id,
29
target_project_id,
30
target_path,
31
overwrite_newer,
32
delete_missing,
33
backup,
34
timeout,
35
bwlimit,
36
} = params;
37
38
try {
39
const account_id = await getAccountId(req);
40
if (!account_id) {
41
throw Error("must be signed in");
42
}
43
if (
44
!(await isCollaborator({ account_id, project_id: target_project_id }))
45
) {
46
throw Error("must be a collaborator on target project");
47
}
48
if (public_id) {
49
// Verify that path is contained in the public path with id public_id:
50
if (
51
!(await isContainedInPublicPath({
52
id: public_id,
53
project_id: src_project_id,
54
path,
55
}))
56
) {
57
}
58
} else {
59
if (!(await isCollaborator({ account_id, project_id: src_project_id }))) {
60
throw Error("must be a collaborator on source project");
61
}
62
}
63
const project = getProject(src_project_id);
64
await project.copyPath({
65
path,
66
target_project_id,
67
target_path,
68
overwrite_newer,
69
delete_missing,
70
backup,
71
timeout,
72
bwlimit,
73
public: !!public_id,
74
wait_until_done: true,
75
});
76
// success means no exception and no error field in response.
77
res.json({});
78
} catch (err) {
79
res.json({ error: `${err.message}` });
80
}
81
}
82
83
function checkParams(obj: any): string | undefined {
84
if (obj.path == null) return "path must be specified";
85
if (!isValidUUID(obj.src_project_id))
86
return "src_project_id must be a valid uuid";
87
if (!isValidUUID(obj.target_project_id))
88
return "target_project_id must be a valid uuid";
89
}
90
91
async function isContainedInPublicPath({ id, project_id, path }) {
92
const pool = getPool("long");
93
const { rows } = await pool.query(
94
"SELECT project_id, path FROM public_paths WHERE disabled IS NOT TRUE AND vhost IS NULL AND id=$1",
95
[id],
96
);
97
return (
98
rows.length > 0 &&
99
rows[0].project_id == project_id &&
100
path.startsWith(rows[0].path)
101
);
102
}
103
104