slate/pages/api/data/archive.js

209 lines
5.6 KiB
JavaScript
Raw Normal View History

import * as Data from "~/node_common/data";
import * as Utilities from "~/node_common/utilities";
import * as Social from "~/node_common/social";
import * as Strings from "~/common/strings";
import * as Logging from "~/common/logging";
import * as RequestUtilities from "~/node_common/request-utilities";
2020-09-27 04:54:39 +03:00
import { v4 as uuid } from "uuid";
import { MAX_BUCKET_COUNT, MIN_ARCHIVE_SIZE_BYTES } from "~/node_common/constants";
2020-09-27 04:54:39 +03:00
const STAGING_DEAL_BUCKET = "stage-deal";
export default async (req, res) => {
const userInfo = await RequestUtilities.checkAuthorizationInternal(req, res);
if (!userInfo) return;
const { id, user } = userInfo;
let bucketName = null;
2020-09-23 14:17:56 +03:00
if (req.body.data && req.body.data.bucketName) {
bucketName = req.body.data.bucketName;
}
const { buckets, bucketKey, bucketRoot } = await Utilities.getBucketAPIFromUserToken({
user,
bucketName,
});
if (!buckets) {
return res.status(500).send({
decorator: "SERVER_NO_BUCKET_DATA",
error: true,
});
}
// NOTE(jim): Getting the appropriate bucket key
2020-09-23 22:46:56 +03:00
let items = null;
let bucketSizeBytes = 0;
try {
const path = await buckets.listPath(bucketRoot.key, "/");
items = path.item;
bucketSizeBytes = path.item.size;
} catch (e) {
Social.sendTextileSlackMessage({
file: "/pages/api/data/archive.js",
user,
message: e.message,
code: e.code,
functionName: `buckets.listPath`,
});
2020-09-23 22:46:56 +03:00
}
if (!items) {
return res.status(500).send({
decorator: "SERVER_NO_BUCKET_DATA",
2020-09-23 22:46:56 +03:00
error: true,
});
}
Logging.log(`[ deal ] will make a deal for ${items.items.length} items`);
2020-09-23 22:46:56 +03:00
if (items.items.length < 2) {
return res.status(500).send({
decorator: "SERVER_ARCHIVE_NO_FILES",
2020-09-23 22:46:56 +03:00
error: true,
});
}
Logging.log(`[ deal ] deal size: ${Strings.bytesToSize(bucketSizeBytes)}`);
if (bucketSizeBytes < MIN_ARCHIVE_SIZE_BYTES) {
return res.status(500).send({
decorator: "SERVER_ARCHIVE_BUCKET_TOO_SMALL",
message: `Your deal size of ${Strings.bytesToSize(
bucketSizeBytes
)} is too small. You must provide at least 100MB.`,
error: true,
});
}
// NOTE(jim): Make sure that you haven't hit the MAX_BUCKET_COUNT
let userBuckets = [];
try {
userBuckets = await buckets.list();
} catch (e) {
Social.sendTextileSlackMessage({
file: "/pages/api/data/archive.js",
user: user,
message: e.message,
code: e.code,
functionName: `buckets.list`,
});
return res.status(500).send({
decorator: "SERVER_ARCHIVE_BUCKET_COUNT_VERIFICATION_FAILED",
error: true,
});
}
Logging.log(
`[ encrypted ] user has ${userBuckets.length} out of ${MAX_BUCKET_COUNT} buckets used.`
);
if (userBuckets.length >= MAX_BUCKET_COUNT) {
return res.status(500).send({
decorator: "SERVER_ARCHIVE_MAX_NUMBER_BUCKETS",
error: true,
});
}
// NOTE(jim): Either encrypt the bucket or don't encrypt the bucket.
let encryptThisDeal = false;
if (bucketName !== STAGING_DEAL_BUCKET && user.allowEncryptedDataStorage) {
encryptThisDeal = true;
}
if (req.body.data.forceEncryption) {
encryptThisDeal = true;
}
let key = bucketRoot.key;
let encryptedBucketName = null;
if (user.allowEncryptedDataStorage || req.body.data.forceEncryption) {
encryptedBucketName = req.body.data.forceEncryption
? `encrypted-deal-${uuid()}`
: `encrypted-data-${uuid()}`;
Logging.log(`[ encrypted ] making an ${encryptedBucketName} for this storage deal.`);
try {
const newBucket = await buckets.create(encryptedBucketName, true, items.cid);
key = newBucket.root.key;
} catch (e) {
Social.sendTextileSlackMessage({
file: "/pages/api/data/archive.js",
user: user,
message: e.message,
code: e.code,
functionName: `buckets.create (encrypted)`,
});
return res.status(500).send({
decorator: "SERVER_ARCHIVE_ENCRYPTION_FAILED",
error: true,
});
}
Logging.log(`[ encrypted ] ${encryptedBucketName}`);
Logging.log(`[ encrypted ] ${key}`);
} else {
const newDealBucketName = `open-deal-${uuid()}`;
2020-09-27 04:54:39 +03:00
try {
const newBucket = await buckets.create(newDealBucketName, false, items.cid);
2020-09-27 04:54:39 +03:00
key = newBucket.root.key;
} catch (e) {
Social.sendTextileSlackMessage({
file: "/pages/api/data/archive.js",
user: user,
message: e.message,
code: e.code,
functionName: `buckets.create (normal, not encrypted)`,
2020-09-27 04:54:39 +03:00
});
return res.status(500).send({
decorator: "SERVER_ARCHIVE_BUCKET_CLONING_FAILED",
2020-09-27 04:54:39 +03:00
error: true,
});
}
Logging.log(`[ normal ] ${newDealBucketName}`);
Logging.log(`[ normal ] ${key}`);
2020-09-27 04:54:39 +03:00
}
// NOTE(jim): Finally make the deal
2020-09-09 20:56:35 +03:00
let response = {};
let error = {};
try {
Logging.log(`[ deal-maker ] deal being made for ${key}`);
if (req.body.data && req.body.data.settings) {
response = await buckets.archive(key, req.body.data.settings);
} else {
response = await buckets.archive(key);
}
2020-09-09 20:56:35 +03:00
} catch (e) {
error.message = e.message;
error.code = e.code;
Logging.log(e.message);
Social.sendTextileSlackMessage({
file: "/pages/api/data/archive.js",
user: user,
message: e.message,
code: e.code,
functionName: `buckets.archive`,
});
2020-09-23 22:46:56 +03:00
return res.status(500).send({
decorator: "SERVER_ARCHIVE_DEAL_FAILED",
2020-09-23 22:46:56 +03:00
error: true,
message: e.message,
});
2020-09-09 20:56:35 +03:00
}
return res.status(200).send({
decorator: "SERVER_ARCHIVE",
2020-09-09 20:56:35 +03:00
data: { response, error },
});
};