Merge pull request #986 from filecoin-project/@martinalong/api-v3

Api v3
This commit is contained in:
martinalong 2021-11-11 17:49:21 -08:00 committed by GitHub
commit 9f6334ddcb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 1281 additions and 183 deletions

View File

@ -44,6 +44,7 @@ export const convertToV1File = (file) => {
ownerId: file.ownerId,
blurhash: file.blurhash,
body: file.body,
public: file.isPublic,
linkName: file.linkName,
linkBody: file.linkBody,
linkAuthor: file.linkAuthor,

View File

@ -39,71 +39,56 @@ print(JSON.dumps(r.json(), indent=2))`;
const EXAMPLE_RESPONSE = `
{
decorator: "V2_GET",
slates: [
decorator: "V2_GET",
slates: [
{
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
slatename: "public-example",
isPublic: true,
objects: [
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
slatename: "public-example",
isPublic: true,
objects: [
{
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
cid: "bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a", // the file URL is "https://slate.textile.io/ipfs/bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a"
filename: "door.jpg",
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
data: {
name: "Door",
size: 33676,
type: "image/jpeg",
blurhash: "U6BzILt700IADjWBx]oz00f6?bs:00Rj_Nt7",
},
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
cid: "bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a", // the file URL is "https://slate.textile.io/ipfs/bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a"
filename: "door.jpg",
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
data: {
name: "Door",
size: 33676,
type: "image/jpeg",
blurhash: "U6BzILt700IADjWBx]oz00f6?bs:00Rj_Nt7",
},
},
],
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
data: {
],
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
data: {
body: "just a public collection, nothing special",
name: "Public Example",
layouts: {
ver: "2.0",
layout: [
{
h: 200,
w: 200,
x: 0,
y: 0,
z: 0,
id: "fce946be-7212-4f62-a74c-adfafd8d0d15",
},
],
fileNames: false,
defaultLayout: true,
},
url: "https://slate.host/devexamples/public-example",
},
},
},
],
user: {
],
user: {
username: "devexamples",
library: [
{
{
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
cid: "bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a", // the file URL is "https://slate.textile.io/ipfs/bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a"
filename: "door.jpg",
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
data: {
name: "Door",
size: 33676,
type: "image/jpeg",
blurhash: "U6BzILt700IADjWBx]oz00f6?bs:00Rj_Nt7",
},
name: "Door",
size: 33676,
type: "image/jpeg",
blurhash: "U6BzILt700IADjWBx]oz00f6?bs:00Rj_Nt7",
},
},
],
data: {
photo: "https://slate.textile.io/ipfs/cid-goes-here",
body: "A user of slate",
name: "Bob Smith",
},
photo: "https://slate.textile.io/ipfs/cid-goes-here",
body: "A user of slate",
name: "Bob Smith",
},
},
};`;
export default class APIDocsGet extends React.Component {

View File

@ -0,0 +1,71 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (key, slateId) => {
return `const response = await fetch("https://slate.host/api/v3/create-collection", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Basic ${key}", // API key
},
body: JSON.stringify({
data: {
name: "My Dog Fido",
isPublic: true,
body: "This is an album of my dog, Fido, a golden retriever",
},
}),
});`;
};
const EXAMPLE_CODE_PY = (key, slateId) =>
`import requests
headers = {
"content-type": "application/json",
"Authorization": "Basic ${key}", # API key
}
postJson = {
data: {
name: "My Dog Fido",
isPublic: true,
body: "This is an album of my dog, Fido, a golden retriever",
}
}
url = "https://slate.host/api/v3/create-collection"
r = requests.post(url, headers=headers, json=postJson)`;
export default class APIDocsCreateCollection extends React.Component {
render() {
let language = this.props.language;
let key = this.props.APIKey;
let slateId = this.props.slateId;
let code = {
javascript: EXAMPLE_CODE_JS(key, slateId),
python: EXAMPLE_CODE_PY(key, slateId),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Create Collection"
description="This API endpoint allows you to create a collection. All fields except name are optional."
/>
<CodeBlock
children={code}
style={{ maxWidth: "820px" }}
language={language}
title="Create collection"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
</div>
);
}
}

View File

@ -0,0 +1,69 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (key, slateId) => {
return `const response = await fetch("https://slate.host/api/v3/create-link", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Basic ${key}", // API key
},
body: JSON.stringify({
data: {
url: "https://google.com",
slate: { id: "${slateId}" }, // Optional slate ID
},
}),
});`;
};
const EXAMPLE_CODE_PY = (key, slateId) =>
`import requests
headers = {
"content-type": "application/json",
"Authorization": "Basic ${key}", # API key
}
postJson = {
data: {
url: "https://google.com",
slate: { id: "${slateId}" }, # Optional slate ID
},
}
url = "https://slate.host/api/v3/create-link"
r = requests.post(url, headers=headers, json=postJson)`;
export default class APIDocsCreateLink extends React.Component {
render() {
let language = this.props.language;
let key = this.props.APIKey;
let slateId = this.props.slateId;
let code = {
javascript: EXAMPLE_CODE_JS(key, slateId),
python: EXAMPLE_CODE_PY(key, slateId),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Create link"
description="This API endpoint allows you to upload a link and optionally add it to a slate. Include a slate id to add it to a slate."
/>
<CodeBlock
children={code}
style={{ maxWidth: "820px" }}
language={language}
title="Create link"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
</div>
);
}
}

View File

@ -5,15 +5,15 @@ import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (
key,
userId
) => `const response = await fetch('https://slate.host/api/v2/get-user', {
slateId
) => `const response = await fetch('https://slate.host/api/v3/get-collection', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: '${key}',
},
body: JSON.stringify({ data: {
id: '${userId}' // user ID
id: '${slateId}' // collection ID
}})
});
@ -26,13 +26,13 @@ const json = await response.json();
if (json.error) {
console.log(json);
} else {
const user = json.user;
const collection = json.collection;
}`;
const EXAMPLE_CODE_PY = (key, userId) => `import requests
const EXAMPLE_CODE_PY = (key, slateId) => `import requests
import json as JSON
url = 'https://slate.host/api/v2/get-user'
url = 'https://slate.host/api/v3/get-collection'
headers = {
'content-type': 'application/json',
'Authorization': '${key}'
@ -40,35 +40,35 @@ headers = {
json = {
"data": {
"id": "${userId}" # user ID
"id": "${slateId}" # collection ID
}
}
r = requests.post(url, headers=headers, json=json)`;
export default class APIDocsGetUser extends React.Component {
export default class APIDocsGetCollection extends React.Component {
render() {
let APIKey = this.props.APIKey;
let userId = this.props.userId;
let slateId = this.props.slateId;
let language = this.props.language;
let code = {
javascript: EXAMPLE_CODE_JS(APIKey, userId),
python: EXAMPLE_CODE_PY(APIKey, userId),
javascript: EXAMPLE_CODE_JS(APIKey, slateId),
python: EXAMPLE_CODE_PY(APIKey, slateId),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Get user by ID"
description="This API request will return a specific user"
label="Get collection by ID"
description="This API request will return a specific collection. You can save the response locally and send this JSON back to our API server using the route /api/v3/update-collection to update your collection."
/>
<CodeBlock
children={code}
style={{ maxWidth: "820px" }}
language={language}
title="Get user by ID"
title="Get collection by ID"
onLanguageChange={this.props.onLanguageChange}
multiLang="true"
/>

View File

@ -0,0 +1,122 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (key) => `const response = await fetch('https://slate.host/api/v3/get', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: '${key}',
}
});
if (!response) {
console.log("No response");
return;
}
const json = await response.json();
if (json.error) {
console.log(json);
} else {
const collections = json.collections;
const user = json.user;
}`;
const EXAMPLE_CODE_PY = (key) => `import requests
import json as JSON
url = "https://slate.host/api/v3/get"
headers = {
"content-type": "application/json",
"Authorization": "${key}",
}
r = requests.get(url, headers=headers)
print(JSON.dumps(r.json(), indent=2))`;
const EXAMPLE_RESPONSE = `
{
decorator: "V3_GET",
slates: [
{
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
slatename: "public-example",
isPublic: true,
objects: [
{
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
cid: "bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a", // the file URL is "https://slate.textile.io/ipfs/bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a"
filename: "door.jpg",
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
name: "Door",
size: 33676,
type: "image/jpeg",
blurhash: "U6BzILt700IADjWBx]oz00f6?bs:00Rj_Nt7",
},
],
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
body: "just a public collection, nothing special",
name: "Public Example",
url: "https://slate.host/devexamples/public-example",
},
],
user: {
username: "devexamples",
library: [
{
id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
cid: "bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a", // the file URL is "https://slate.textile.io/ipfs/bafkreibrpxcv37juaq67it2gu7xyjo5fzq7v3r55ykcgzylvsfljcv3s3a"
filename: "door.jpg",
ownerId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
name: "Door",
size: 33676,
type: "image/jpeg",
blurhash: "U6BzILt700IADjWBx]oz00f6?bs:00Rj_Nt7",
},
],
photo: "https://slate.textile.io/ipfs/cid-goes-here",
body: "A user of slate",
name: "Bob Smith",
},
};
`;
export default class APIDocsGet extends React.Component {
render() {
let APIKey = this.props.APIKey;
let language = this.props.language;
let code = {
javascript: EXAMPLE_CODE_JS(APIKey),
python: EXAMPLE_CODE_PY(APIKey),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Get your data"
description="This API request returns your user data and collections. If the request body is omitted, the request will return only your public collections by default."
/>
<CodeBlock
children={code}
language={language}
style={{ maxWidth: "820px" }}
title="Get your data"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
<br />
<CodeBlock
children={EXAMPLE_RESPONSE}
style={{ maxWidth: "820px" }}
language="javascript"
title="Get your data response"
/>
</div>
);
}
}

View File

@ -0,0 +1,82 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (key, slateId) => {
return `const COLLECTION_ID = "${slateId}"
const collectionResponseData = getCollectionById(COLLECTION_ID);
const collection = collectionResponseData.collection;
const file = collection.objects[0];
file.name = "New filename";
file.body = "New file description";
const response = await fetch('https://slate.host/api/v3/update-file', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: '${key}', // API key
},
body: JSON.stringify({ data: file })
});
const json = await response.json();`;
};
const EXAMPLE_CODE_PY = (key, slateId) =>
`import requests
headers = {
"content-type": "application/json",
"Authorization": "${key}", # API key
}
json = { "id": "${slateId}" } # collection ID
get_collection = requests.post(
"https://slate.host/api/v3/get-collection", headers=headers, json=json
)
get_collection_response = get_collection.json()
collection = get_collection_response["collection"]
file = collection["objects"][0]
file["name"] = "New filename"
file["body"] = "New file description"
postJson = { "data": file }
url = "https://slate.host/api/v3/update-file"
r = requests.post(url, headers=headers, json=postJson)`;
export default class APIDocsUpdateFile extends React.Component {
render() {
let language = this.props.language;
let key = this.props.APIKey;
let slateId = this.props.slateId;
let code = {
javascript: EXAMPLE_CODE_JS(key, slateId),
python: EXAMPLE_CODE_PY(key, slateId),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Update file"
description="This API endpoint allows you to modify a file by saving the collection object in the response from get-collection, modifying it, and sending it back"
/>
<CodeBlock
children={code}
style={{ maxWidth: "820px" }}
language={language}
title="Update file"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
</div>
);
}
}

View File

@ -0,0 +1,81 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (key, slateId) => {
return `const COLLECTION_ID = "${slateId}"
const collectionResponseData = getCollectionById(COLLECTION_ID);
const collection = collectionResponseData.collection;
collection.name = "New title";
collection.body = "New description";
const response = await fetch('https://slate.host/api/v3/update-collection', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: '${key}', // API key
},
body: JSON.stringify({ data: collection })
});
const json = await response.json();`;
};
const EXAMPLE_CODE_PY = (key, slateId) =>
`import requests
headers = {
"content-type": "application/json",
"Authorization": "${key}", # API key
}
json = { "id": "${slateId}" } # collection ID
get_collection = requests.post(
"https://slate.host/api/v3/get-collection", headers=headers, json=json
)
get_collection_response = get_collection.json()
collection = get_collection_response["collection"]
collection["name"] = "New title";
collection["body"] = "New description";
postJson = { "data": collection }
url = "https://slate.host/api/v3/update-collection"
r = requests.post(url, headers=headers, json=postJson)`;
export default class APIDocsUpdateCollection extends React.Component {
render() {
let language = this.props.language;
let key = this.props.APIKey;
let slateId = this.props.slateId;
let code = {
javascript: EXAMPLE_CODE_JS(key, slateId),
python: EXAMPLE_CODE_PY(key, slateId),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Update collection"
description="This API endpoint allows you to modify a collection by saving the response from get-collection, modifying it, and sending it back"
/>
<CodeBlock
children={code}
style={{ maxWidth: "820px" }}
language={language}
title="Update collection"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
</div>
);
}
}

View File

@ -0,0 +1,73 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (
key
) => `const url = 'https://uploads.slate.host/api/v3/public/upload-by-cid';
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': "application/json",
Authorization: '${key}', // API key
},
body: JSON.stringify({
data: {
cid: "FILE-CID-HERE",
filename: "OPTIONAL-FILENAME-HERE", // if no filename is provided, filename defaults to the cid
},
}),
});
const json = await response.json();`;
const EXAMPLE_CODE_PY = (key) => `import requests
url = "https://uploads.slate.host/api/v3/public/upload-by-cid"
headers = {
"Content-Type": "application/json",
"Authorization": "${key}" # API key
}
json = {
data: {
cid: "FILE-CID-HERE",
filename: "OPTIONAL-FILENAME-HERE", # if no filename is provided, filename defaults to the cid
}
}
r = requests.post(url, headers=headers, json=json)`;
export default class APIDocsUploadByCID extends React.Component {
render() {
let language = this.props.language;
let key = this.props.APIKey;
let slateId = this.props.slateId;
let uploadCode = {
javascript: EXAMPLE_CODE_JS(key),
python: EXAMPLE_CODE_PY(key),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Upload File by CID"
description={
"This API endpoint allows you to upload a file that already exists on the IPFS network to Slate using its CID."
}
/>
<CodeBlock
children={uploadCode}
style={{ maxWidth: "820px" }}
language={language}
title="Upload File by URL"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
</div>
);
}
}

View File

@ -0,0 +1,73 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (
key
) => `const url = 'https://uploads.slate.host/api/v3/public/upload-by-url';
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': "application/json",
Authorization: '${key}', // API key
},
body: JSON.stringify({
data: {
url: "www.example-file-url.com",
filename: "OPTIONAL-FILENAME-HERE", // if no filename is provided, filename defaults to the cid
},
}),
});
const json = await response.json();`;
const EXAMPLE_CODE_PY = (key) => `import requests
url = "https://uploads.slate.host/api/v3/public/upload-by-url"
headers = {
"Content-Type": "application/json",
"Authorization": "${key}" # API key
}
json = {
data: {
url: "www.example-file-url.com",
filename: "OPTIONAL-FILENAME-HERE", # if no filename is provided, filename defaults to the cid
}
}
r = requests.post(url, headers=headers, json=json)`;
export default class APIDocsUploadByURL extends React.Component {
render() {
let language = this.props.language;
let key = this.props.APIKey;
let slateId = this.props.slateId;
let uploadCode = {
javascript: EXAMPLE_CODE_JS(key),
python: EXAMPLE_CODE_PY(key),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Upload File by URL"
description={
"This API endpoint allows you to upload a file directly from a URL. The URL you use should point directly to the source link of the desired file."
}
/>
<CodeBlock
children={uploadCode}
style={{ maxWidth: "820px" }}
language={language}
title="Upload File by URL"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
</div>
);
}
}

View File

@ -0,0 +1,105 @@
import * as React from "react";
import * as System from "~/components/system";
import CodeBlock from "~/components/system/CodeBlock";
const EXAMPLE_CODE_JS = (key) => `const url = 'https://uploads.slate.host/api/v3/public';
let file = e.target.files[0];
let data = new FormData();
data.append("data", file);
const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: '${key}', // API key
},
body: data
});`;
const EXAMPLE_CODE_PY = (key) => `import requests
url = "https://uploads.slate.host/api/v3/public"
files = {
"file": open("example-file.txt", "rb")
}
headers = {
"Authorization": "${key}" # API key
}
r = requests.post(url, headers=headers, files=files)`;
const SLATE_EXAMPLE_CODE_JS = (
key,
slateId
) => `const url = 'https://uploads.slate.host/api/v3/public/${slateId}'; // collection ID
let file = e.target.files[0];
let data = new FormData();
data.append("data", file);
const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: '${key}', // API key
},
body: data
});
const json = await response.json();`;
const SLATE_EXAMPLE_CODE_PY = (key, slateId) => `import requests
url = "https://uploads.slate.host/api/v3/public/${slateId}" # collection ID
files = {
"file": open("example-file.txt", "rb")
}
headers = {
"Authorization": "${key}" # API key
}
r = requests.post(url, headers=headers, files=files)`;
export default class APIDocsUploadToSlate extends React.Component {
render() {
let language = this.props.language;
let key = this.props.APIKey;
let slateId = this.props.slateId;
let uploadCode = {
javascript: EXAMPLE_CODE_JS(key),
python: EXAMPLE_CODE_PY(key),
};
let slateUploadCode = {
javascript: SLATE_EXAMPLE_CODE_JS(key, slateId),
python: SLATE_EXAMPLE_CODE_PY(key, slateId),
};
return (
<div css={this.props.cssValue} style={this.props.style}>
<System.DescriptionGroup
style={{ maxWidth: 640 }}
label="Upload File"
description={
"This API endpoint allows you to upload file(s) to your collection. This uses our data transfer microservice to interact with Textile Buckets and upload data to the IPFS/Filecoin network."
}
/>
<CodeBlock
children={uploadCode}
style={{ maxWidth: "820px" }}
language={language}
title="Upload file"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
<br />
<CodeBlock
children={slateUploadCode}
style={{ maxWidth: "820px" }}
language={language}
title="Upload file to collection"
multiLang="true"
onLanguageChange={this.props.onLanguageChange}
/>
</div>
);
}
}

View File

@ -1,8 +1,8 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Powergate from "~/node_common/powergate";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
@ -35,28 +35,7 @@ export default async (req, res) => {
return res.status(400).send({ decorator: "SLATE_IS_PRIVATE", error: true });
}
//NOTE(martina): convert the new database structure to the old structure
let reformattedObjects = slate.objects.map((file) => {
return {
...file,
...file.data,
data: null,
url: Strings.getURLfromCID(file.cid),
};
});
let reformattedSlate = {
id: slate.id,
updated_at: slate.updatedAt,
created_at: slate.createdAt,
slatename: slate.slatename,
data: {
name: slate.data.name,
public: slate.isPublic,
objects: reformattedObjects,
ownerId: slate.ownerId,
},
};
let reformattedSlate = Conversions.convertToV1Slate(slate);
return res.status(200).send({ decorator: "V1_GET_SLATE", slate: reformattedSlate });
};

View File

@ -1,22 +1,15 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Powergate from "~/node_common/powergate";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
let reformattedUser = {
username: user.username,
data: {
name: user.data.name,
photo: user.data.photo,
body: user.data.body,
},
};
let reformattedUser = Conversions.convertToV1User(user);
let slates = await Data.getSlatesByUserId({
ownerId: user.id,
@ -38,30 +31,7 @@ export default async (req, res) => {
});
}
let reformattedSlates = slates.map((slate) => {
let reformattedObjects = slate.objects.map((file) => {
return {
...file,
...file.data,
data: null,
url: Strings.getURLfromCID(file.cid),
};
});
return {
id: slate.id,
updated_at: slate.updatedAt,
created_at: slate.createdAt,
slatename: slate.slatename,
url: `https://slate.host/${user.username}/${slate.slatename}`,
data: {
name: slate.data.name,
public: slate.isPublic,
objects: reformattedObjects,
ownerId: slate.ownerId,
},
};
});
let reformattedSlates = slates.map((slate) => Conversions.convertToV1Slate(slate));
return res
.status(200)

View File

@ -2,9 +2,11 @@ import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Validations from "~/common/validations";
import SearchManager from "~/node_common/managers/search";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
@ -40,10 +42,8 @@ export default async (req, res) => {
slatename: req.body.data.slatename,
isPublic: req.body.data.data.public,
updatedAt: new Date(),
data: {
name: req.body.data.data.name,
body: req.body.data.data.body,
},
name: req.body.data.data.name,
body: req.body.data.data.body,
};
if (typeof updates.isPublic !== "undefined" && slate.isPublic !== updates.isPublic) {
@ -73,8 +73,8 @@ export default async (req, res) => {
SearchManager.updateFile(updatedFiles);
}
if (updates.data.name && updates.data.name !== slate.data.name) {
if (!Validations.slatename(slate.data.name)) {
if (updates.name && updates.name !== slate.name) {
if (!Validations.slatename(slate.name)) {
return res.status(400).send({
decorator: "UPDATE_SLATE_INVALID_NAME",
error: true,
@ -82,7 +82,7 @@ export default async (req, res) => {
}
const existingSlate = await Data.getSlateByName({
slatename: updates.data.name,
slatename: updates.name,
ownerId: user.id,
});
@ -92,7 +92,7 @@ export default async (req, res) => {
error: true,
});
} else {
updates.slatename = Strings.createSlug(updates.data.name);
updates.slatename = Strings.createSlug(updates.name);
}
}

View File

@ -2,9 +2,11 @@ import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as ViewerManager from "~/node_common/managers/viewer";
import SearchManager from "~/node_common/managers/search";
import * as Monitor from "~/node_common/monitor";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
@ -47,5 +49,7 @@ export default async (req, res) => {
Monitor.createSlate({ user, slate });
return res.status(200).send({ decorator: "CREATE_COLLECTION", slate });
let reformattedSlate = Conversions.convertToV2Slate(slate);
return res.status(200).send({ decorator: "CREATE_COLLECTION", slate: reformattedSlate });
};

View File

@ -3,10 +3,12 @@ import * as Data from "~/node_common/data";
import * as LinkUtilities from "~/node_common/link-utilities";
import * as Strings from "~/common/strings";
import * as ViewerManager from "~/node_common/managers/viewer";
import SearchManager from "~/node_common/managers/search";
import * as ArrayUtilities from "~/node_common/array-utilities";
import * as Monitor from "~/node_common/monitor";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
@ -46,7 +48,9 @@ export default async (req, res) => {
});
if (!filteredFiles?.length) {
return res.status(200).send({ decorator: "LINK_DUPLICATE", data: duplicateFiles });
let reformattedFiles = duplicateFiles.map((file) => Conversions.convertToV2File(file));
return res.status(200).send({ decorator: "LINK_DUPLICATE", data: reformattedFiles });
}
files = [];
@ -125,7 +129,6 @@ export default async (req, res) => {
if (returnedDecorator) {
decorator = returnedDecorator;
}
added = addedToSlate;
}
SearchManager.indexFile(createdFiles);
@ -136,8 +139,10 @@ export default async (req, res) => {
Monitor.upload({ user, files });
}
let reformattedFiles = filesToAddToSlate.map((file) => Conversions.convertToV2File(file));
return res.status(200).send({
decorator,
data: filesToAddToSlate,
data: reformattedFiles,
});
};

View File

@ -1,8 +1,8 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Powergate from "~/node_common/powergate";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
@ -10,13 +10,12 @@ export default async (req, res) => {
const { id, key, user } = userInfo;
let slateId = req.body?.data?.id;
let slate;
if (Strings.isEmpty(slateId)) {
return res.status(400).send({ decorator: "NO_ID_PROVIDED", error: true });
}
slate = await Data.getSlateById({ id: slateId, includeFiles: true });
let slate = await Data.getSlateById({ id: slateId, includeFiles: true });
if (!slate) {
return res.status(404).send({
@ -39,5 +38,7 @@ export default async (req, res) => {
});
}
return res.status(200).send({ decorator: "GET_COLLECTION", collection: slate });
let reformattedSlate = Conversions.convertToV2Slate(slate);
return res.status(200).send({ decorator: "GET_COLLECTION", collection: reformattedSlate });
};

View File

@ -1,14 +1,16 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Powergate from "~/node_common/powergate";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
let reformattedUser = Conversions.convertToV2User(user);
let slates = await Data.getSlatesByUserId({
ownerId: id,
includeFiles: true,
@ -33,5 +35,9 @@ export default async (req, res) => {
return each;
});
return res.status(200).send({ decorator: "GET", user, collections: slates });
let reformattedSlates = slates.map((slate) => Conversions.convertToV2Slate(slate));
return res
.status(200)
.send({ decorator: "GET", user: reformattedUser, collections: reformattedSlates });
};

View File

@ -1,9 +1,12 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Validations from "~/common/validations";
import SearchManager from "~/node_common/managers/search";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
@ -39,10 +42,8 @@ export default async (req, res) => {
id: req.body.data.id,
updatedAt: new Date(),
isPublic: req.body.data.isPublic,
data: {
name: req.body.data.data?.name,
body: req.body.data.data?.body,
},
name: req.body.data.data?.name,
body: req.body.data.data?.body,
};
if (typeof updates.isPublic !== "undefined" && slate.isPublic !== updates.isPublic) {
@ -61,8 +62,8 @@ export default async (req, res) => {
}
}
if (updates.data.name && updates.data.name !== slate.data.name) {
if (!Validations.slatename(slate.data.name)) {
if (updates.name && updates.name !== slate.name) {
if (!Validations.slatename(slate.name)) {
return res.status(400).send({
decorator: "INVALID_COLLECTION_NAME",
error: true,
@ -70,7 +71,7 @@ export default async (req, res) => {
}
const existingSlate = await Data.getSlateByName({
slatename: updates.data.name,
slatename: updates.name,
ownerId: user.id,
});
@ -80,7 +81,7 @@ export default async (req, res) => {
error: true,
});
} else {
updates.slatename = Strings.createSlug(updates.data.name);
updates.slatename = Strings.createSlug(updates.name);
}
}
@ -108,5 +109,7 @@ export default async (req, res) => {
ViewerManager.hydratePartial(user.id, { slates: true });
return res.status(200).send({ decorator: "UPDATE_COLLECTION", collection: updatedSlate });
let reformattedSlate = Conversions.convertToV2Slate(updatedSlate);
return res.status(200).send({ decorator: "UPDATE_COLLECTION", collection: reformattedSlate });
};

View File

@ -1,8 +1,10 @@
import * as Strings from "~/common/strings";
import * as Data from "~/node_common/data";
import SearchManager from "~/node_common/managers/search";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
@ -16,10 +18,8 @@ export default async (req, res) => {
//NOTE(martina): cleans the input to remove fields they should not be changing like ownerId, createdAt, filename, size, type etc.
let updates = {
id: req.body.data.id,
data: {
name: req.body.data.data?.name,
body: req.body.data.data?.body,
},
name: req.body.data.data?.name,
body: req.body.data.data?.body,
};
const file = await Data.getFileById({ id: updates.id });
@ -31,18 +31,20 @@ export default async (req, res) => {
});
}
let response = await Data.updateFileById(updates);
let updatedFile = await Data.updateFileById(updates);
if (!response || response.error) {
if (!updatedFile || updatedFile.error) {
return res.status(500).send({ decorator: "UPDATE_FILE_FAILED", error: true });
}
SearchManager.updateFile(response);
SearchManager.updateFile(updatedFile);
ViewerManager.hydratePartial(user.id, { library: true, slates: true });
let reformattedFile = Conversions.convertToV2File(updatedFile);
return res.status(200).send({
decorator: "UPDATE_FILE",
file: response,
file: reformattedFile,
});
};

View File

@ -0,0 +1,53 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as Monitor from "~/node_common/monitor";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
if (!req.body?.data?.name) {
return res.status(500).send({
decorator: "MUST_PROVIDE_DATA",
error: true,
});
}
const slatename = Strings.createSlug(req.body.data.name);
const existingSlate = await Data.getSlateByName({
slatename,
ownerId: user.id,
});
if (existingSlate) {
return res.status(500).send({ decorator: "EXISTING_SLATE_NAME", error: true });
}
const slate = await Data.createSlate({
ownerId: id,
slatename: Strings.createSlug(req.body.data.name),
isPublic: req.body.data.isPublic,
name: req.body.data.name,
body: req.body.data.body,
});
if (!slate || slate.error) {
return res.status(500).send({ decorator: "CREATE_COLLECTION_FAILED", error: true });
}
ViewerManager.hydratePartial(id, { slates: true });
SearchManager.indexSlate(slate);
Monitor.createSlate({ user, slate });
return res.status(200).send({ decorator: "CREATE_COLLECTION", slate });
};

144
pages/api/v3/create-link.js Normal file
View File

@ -0,0 +1,144 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as LinkUtilities from "~/node_common/link-utilities";
import * as Strings from "~/common/strings";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as ArrayUtilities from "~/node_common/array-utilities";
import * as Monitor from "~/node_common/monitor";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
let decorator = "SERVER_CREATE_LINK";
const slateId = req.body.data.slate?.id;
let slate;
if (slateId) {
slate = await Data.getSlateById({ id: slateId });
if (!slate || slate.error) {
slate = null;
decorator = "SLATE_NOT_FOUND";
}
}
let urls;
if (req.body?.data?.url) {
urls = [req.body.data.url];
} else if (req.body?.data?.urls) {
urls = req.body.data.urls;
} else {
return res.status(400).send({ decorator: "NO_LINK_PROVIDED", error: true });
}
let files = [];
for (let url of urls) {
const cid = await LinkUtilities.getCIDofString(url);
files.push({ cid, url });
}
let { duplicateFiles, filteredFiles } = await ArrayUtilities.removeDuplicateUserFiles({
files,
user,
});
if (!filteredFiles?.length) {
return res.status(200).send({ decorator: "LINK_DUPLICATE", data: duplicateFiles });
}
files = [];
for (let file of filteredFiles) {
const url = file.url;
const data = await LinkUtilities.fetchLinkData(url);
if (!data) {
continue;
}
const filename = Strings.createSlug(data.title);
const domain = LinkUtilities.getDomainFromURL(url);
const html = await LinkUtilities.fetchEmbed(url);
const iFrameAllowed = await LinkUtilities.testIframe(url);
const newFile = {
filename,
cid: file.cid,
isLink: true,
url: file.url,
type: "link",
name: data.title,
body: data.description,
linkName: data.title,
linkBody: data.description,
linkSource: data.publisher,
linkAuthor: data.author,
linkImage: data.image?.url,
linkFavicon: data.logo?.url,
linkDomain: domain,
linkHtml: html,
linkIFrameAllowed: iFrameAllowed,
};
files.push(newFile);
}
if (!files?.length) {
return res.status(400).send({ decorator: "SERVER_CREATE_LINK_INVALID_LINK", error: true });
}
if (slate?.isPublic) {
files = files.map((file) => {
return { ...file, isPublic: true };
});
}
let createdFiles = [];
if (files?.length) {
createdFiles = (await Data.createFile({ owner: user, files })) || [];
if (!createdFiles?.length) {
return res.status(404).send({ decorator: "SERVER_CREATE_LINK_FAILED", error: true });
}
if (createdFiles.error) {
return res.status(500).send({ decorator: createdFiles.decorator, error: createdFiles.error });
}
}
// for (let file of createdFiles) {
// LinkUtilities.uploadScreenshot(file, user);
// }
let filesToAddToSlate = createdFiles.concat(duplicateFiles); //NOTE(martina): files that are already owned by the user are included in case they aren't yet in that specific slate
if (slate && filesToAddToSlate.length) {
const { decorator: returnedDecorator, added: addedToSlate } = await Utilities.addToSlate({
slate,
files: filesToAddToSlate,
user,
});
if (returnedDecorator) {
decorator = returnedDecorator;
}
}
SearchManager.indexFile(createdFiles);
ViewerManager.hydratePartial(id, { library: true, slates: slate ? true : false });
if (!slate) {
Monitor.upload({ user, files });
}
return res.status(200).send({
decorator,
data: filesToAddToSlate,
});
};

View File

@ -0,0 +1,42 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
let slateId = req.body?.data?.id;
if (Strings.isEmpty(slateId)) {
return res.status(400).send({ decorator: "NO_ID_PROVIDED", error: true });
}
let slate = await Data.getSlateById({ id: slateId, includeFiles: true });
if (!slate) {
return res.status(404).send({
decorator: "COLLECTION_NOT_FOUND",
error: true,
});
}
if (slate.error) {
return res.status(500).send({
decorator: "ERROR_WHILE_LOCATING_COLLECTION",
error: true,
});
}
if (!slate.isPublic) {
return res.status(400).send({
decorator: "COLLECTION_IS_PRIVATE",
error: true,
});
}
return res.status(200).send({ decorator: "GET_COLLECTION", collection: slate });
};

View File

@ -1,40 +1,34 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Powergate from "~/node_common/powergate";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
let userId = req.body?.data?.id;
let reformattedUser = Conversions.convertToV3User(user);
if (Strings.isEmpty(userId)) {
return res.status(400).send({ decorator: "NO_USER_ID_PROVIDED", error: true });
}
let targetUser = await Data.getUserById({
id: userId,
sanitize: true,
publicOnly: true,
let slates = await Data.getSlatesByUserId({
ownerId: id,
includeFiles: true,
});
if (!targetUser) {
if (!slates) {
return res.status(404).send({
decorator: "USER_NOT_FOUND",
decorator: "COULD_NOT_FETCH_COLLECTIONS",
error: true,
});
}
if (targetUser.error) {
if (slates.error) {
return res.status(500).send({
decorator: "USER_NOT_FOUND",
decorator: "COULD_NOT_FETCH_COLLECTIONS",
error: true,
});
}
return res.status(200).send({ decorator: "GET_USER", user: targetUser });
return res.status(200).send({ decorator: "GET", user: reformattedUser, collections: slates });
};

View File

@ -0,0 +1,113 @@
import * as Utilities from "~/node_common/utilities";
import * as Data from "~/node_common/data";
import * as Strings from "~/common/strings";
import * as Validations from "~/common/validations";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
if (!req.body?.data?.id) {
return res.status(500).send({
decorator: "UPDATE_COLLECTION_MUST_PROVIDE_DATA",
error: true,
});
}
const slate = await Data.getSlateById({ id: req.body.data.id, includeFiles: true });
if (!slate) {
return res.status(404).send({ decorator: "COLLECTION_NOT_FOUND", error: true });
}
if (slate.error) {
return res.status(500).send({ decorator: "COLLECTION_NOT_FOUND", error: true });
}
if (slate.ownerId !== user.id) {
return res.status(400).send({
decorator: "NOT_COLLECTION_OWNER_UPDATE_NOT_PERMITTED",
error: true,
});
}
//NOTE(martina): cleans the input to remove fields they should not be changing like ownerId, createdAt, etc.
let updates = {
id: req.body.data.id,
updatedAt: new Date(),
isPublic: req.body.data.isPublic,
name: req.body.data.name,
body: req.body.data.body,
};
if (typeof updates.isPublic !== "undefined" && slate.isPublic !== updates.isPublic) {
let privacyResponse = await Data.updateSlatePrivacy({
ownerId: user.id,
id: updates.id,
isPublic: updates.isPublic,
});
if (!privacyResponse) {
return res.status(404).send({ decorator: "UPDATE_COLLECTION_PRIVACY_FAILED", error: true });
}
if (privacyResponse.error) {
return res.status(500).send({ decorator: "UPDATE_COLLECTION_PRIVACY_FAILED", error: true });
}
}
if (updates.name && updates.name !== slate.name) {
if (!Validations.slatename(slate.name)) {
return res.status(400).send({
decorator: "INVALID_COLLECTION_NAME",
error: true,
});
}
const existingSlate = await Data.getSlateByName({
slatename: updates.name,
ownerId: user.id,
});
if (existingSlate) {
return res.status(500).send({
decorator: "COLLECTION_NAME_TAKEN",
error: true,
});
} else {
updates.slatename = Strings.createSlug(updates.name);
}
}
let updatedSlate = await Data.updateSlateById(updates);
if (!updatedSlate) {
return res.status(404).send({ decorator: "UPDATE_COLLECTION_FAILED", error: true });
}
if (updatedSlate.error) {
return res.status(500).send({ decorator: "UPDATE_COLLECTION_FAILED", error: true });
}
let updatedFiles;
if (slate.isPublic && !updates.isPublic) {
updatedFiles = await Utilities.removeFromPublicCollectionUpdatePrivacy({
files: slate.objects,
});
} else if (!slate.isPublic && updates.isPublic) {
updatedFiles = await Utilities.addToPublicCollectionUpdatePrivacy({ files: slate.objects });
}
SearchManager.updateFile(updatedFiles);
SearchManager.updateSlate(updatedSlate);
ViewerManager.hydratePartial(user.id, { slates: true });
return res.status(200).send({ decorator: "UPDATE_COLLECTION", collection: updatedSlate });
};

View File

@ -0,0 +1,48 @@
import * as Strings from "~/common/strings";
import * as Data from "~/node_common/data";
import * as ViewerManager from "~/node_common/managers/viewer";
import * as RequestUtilities from "~/node_common/request-utilities";
import * as Conversions from "~/common/conversions";
import SearchManager from "~/node_common/managers/search";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationExternal(req, res);
if (!userInfo) return;
const { id, key, user } = userInfo;
if (!req.body?.data?.id) {
return res.status(500).send({ decorator: "NO_FILE_ID_PROVIDED", error: true });
}
//NOTE(martina): cleans the input to remove fields they should not be changing like ownerId, createdAt, filename, size, type etc.
let updates = {
id: req.body.data.id,
name: req.body.data.name,
body: req.body.data.body,
};
const file = await Data.getFileById({ id: updates.id });
if (file.ownerId !== user.id) {
return res.status(400).send({
decorator: "NOT_FILE_OWNER_UPDATE_NOT_PERMITTED",
error: true,
});
}
let response = await Data.updateFileById(updates);
if (!response || response.error) {
return res.status(500).send({ decorator: "UPDATE_FILE_FAILED", error: true });
}
SearchManager.updateFile(response);
ViewerManager.hydratePartial(user.id, { library: true, slates: true });
return res.status(200).send({
decorator: "UPDATE_FILE",
file: response,
});
};

View File

@ -21,7 +21,6 @@ import APIDocsUploadToSlateV1 from "~/components/api-docs/v1/upload.js";
import APIDocsGetV2 from "~/components/api-docs/v2/get";
import APIDocsGetSlateV2 from "~/components/api-docs/v2/get-slate.js";
import APIDocsGetUserV2 from "~/components/api-docs/v2/get-user.js";
import APIDocsUpdateSlateV2 from "~/components/api-docs/v2/update-slate.js";
import APIDocsUpdateFileV2 from "~/components/api-docs/v2/update-file.js";
import APIDocsUploadToSlateV2 from "~/components/api-docs/v2/upload.js";
@ -29,6 +28,17 @@ import APIDocsCreateLinkV2 from "~/components/api-docs/v2/create-link.js";
import APIDocsCreateCollectionV2 from "~/components/api-docs/v2/create-collection.js";
import APIDocsUploadByCidV2 from "~/components/api-docs/v2/upload-by-cid.js";
import APIDocsUploadByUrlV2 from "~/components/api-docs/v2/upload-by-url.js";
import APIDocsGetV3 from "~/components/api-docs/v3/get";
import APIDocsGetSlateV3 from "~/components/api-docs/v3/get-slate.js";
import APIDocsUpdateSlateV3 from "~/components/api-docs/v3/update-slate.js";
import APIDocsUpdateFileV3 from "~/components/api-docs/v3/update-file.js";
import APIDocsUploadToSlateV3 from "~/components/api-docs/v3/upload.js";
import APIDocsCreateLinkV3 from "~/components/api-docs/v3/create-link.js";
import APIDocsCreateCollectionV3 from "~/components/api-docs/v3/create-collection.js";
import APIDocsUploadByCidV3 from "~/components/api-docs/v3/upload-by-cid.js";
import APIDocsUploadByUrlV3 from "~/components/api-docs/v3/upload-by-url.js";
import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper";
const STYLES_API_KEY = css`
@ -165,7 +175,7 @@ export default class SceneSettingsDeveloper extends React.Component {
};
render() {
const tab = this.props.page.params?.tab || "v2";
const tab = this.props.page.params?.tab || "v3";
let APIKey = "YOUR-API-KEY-HERE";
let lang = this.state.language;
if (this.props.viewer.keys) {
@ -306,12 +316,13 @@ export default class SceneSettingsDeveloper extends React.Component {
<APIDocsUploadToSlate language={lang} APIKey={APIKey} slateId={slateId} />
*/}
<ScenePageHeader title="Developer Documentation" style={{ marginTop: 96 }}>
Slate is currently on v2.0 of the API. While prior versions are still supported, we
Slate is currently on v3.0 of the API. While prior versions are still supported, we
recommend using the most up to date version.
</ScenePageHeader>
<SecondaryTabGroup
tabs={[
{ title: "Version 3.0", value: { tab: "v3" } },
{ title: "Version 2.0", value: { tab: "v2" } },
{ title: "Version 1.0", value: { tab: "v1" } },
]}
@ -319,7 +330,75 @@ export default class SceneSettingsDeveloper extends React.Component {
onAction={this.props.onAction}
/>
{tab === "v2" ? (
{tab === "v3" ? (
<>
<System.H2 css={STYLES_SECTION_HEADER}>Get</System.H2>
<APIDocsGetV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
onLanguageChange={this._handleChangeLanguage}
/>
<APIDocsGetSlateV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<System.H2 css={STYLES_SECTION_HEADER}>Update</System.H2>
<APIDocsUpdateSlateV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<APIDocsUpdateFileV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<System.H2 css={STYLES_SECTION_HEADER}>Create</System.H2>
<APIDocsCreateCollectionV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<APIDocsUploadToSlateV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<APIDocsUploadByCidV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<APIDocsUploadByUrlV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<APIDocsCreateLinkV3
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
</>
) : tab === "v2" ? (
<>
<System.H2 css={STYLES_SECTION_HEADER}>Get</System.H2>
<APIDocsGetV2
@ -335,13 +414,6 @@ export default class SceneSettingsDeveloper extends React.Component {
slateId={slateId}
onLanguageChange={this._handleChangeLanguage}
/>
<APIDocsGetUserV2
cssValue={STYLES_EXAMPLE}
language={lang}
APIKey={APIKey}
userId={userId}
onLanguageChange={this._handleChangeLanguage}
/>
<System.H2 css={STYLES_SECTION_HEADER}>Update</System.H2>
<APIDocsUpdateSlateV2
cssValue={STYLES_EXAMPLE}