From 15fa57c2df3195fea4ebb9582566f6db3b67e255 Mon Sep 17 00:00:00 2001 From: "@wwwjim" Date: Fri, 23 Oct 2020 03:34:31 -0700 Subject: [PATCH] supports custom resource URIs for two upload endpoints --- common/file-utilities.js | 41 +++++++++++++----------- components/core/Application.js | 3 ++ node_common/environment.js | 7 +++-- node_common/middleware.js | 26 +++------------ pages/_/index.js | 2 ++ pages/api/data/[upload].js | 15 ++------- pages/api/data/deal/[upload].js | 12 ++----- scenes/SceneEditAccount.js | 56 ++++++++++----------------------- scenes/SceneMakeFilecoinDeal.js | 1 + server.js | 28 +++++++++++++++-- 10 files changed, 87 insertions(+), 104 deletions(-) diff --git a/common/file-utilities.js b/common/file-utilities.js index c60c4e69..d7906f78 100644 --- a/common/file-utilities.js +++ b/common/file-utilities.js @@ -1,6 +1,7 @@ import * as Actions from "~/common/actions"; import * as Store from "~/common/store"; import * as Constants from "~/common/constants"; +import * as Credentials from "~/common/credentials"; import { dispatchCustomEvent } from "~/common/custom-events"; import { encode } from "blurhash"; @@ -31,7 +32,13 @@ const encodeImageToBlurhash = async (imageUrl) => { return encode(imageData.data, imageData.width, imageData.height, 4, 4); }; -export const upload = async ({ file, context, bucketName }) => { +// NOTE(jim): We're speaking to a different server now. +const getCookie = (name) => { + var match = document.cookie.match(new RegExp("(^| )" + name + "=([^;]+)")); + if (match) return match[2]; +}; + +export const upload = async ({ file, context, bucketName, routes }) => { let formData = new FormData(); const HEIC2ANY = require("heic2any"); @@ -61,14 +68,13 @@ export const upload = async ({ file, context, bucketName }) => { new Promise((resolve, reject) => { const XHR = new XMLHttpRequest(); - window.addEventListener( - `cancel-${file.lastModified}-${file.name}`, - () => { - XHR.abort(); - } - ); + window.addEventListener(`cancel-${file.lastModified}-${file.name}`, () => { + XHR.abort(); + }); XHR.open("post", path, true); + + XHR.setRequestHeader("authorization", getCookie(Credentials.session.key)); XHR.onerror = (event) => { console.log(event); XHR.abort(); @@ -99,10 +105,7 @@ export const upload = async ({ file, context, bucketName }) => { false ); - window.removeEventListener( - `cancel-${file.lastModified}-${file.name}`, - () => XHR.abort() - ); + window.removeEventListener(`cancel-${file.lastModified}-${file.name}`, () => XHR.abort()); XHR.onloadend = (event) => { console.log("FILE UPLOAD END", event); @@ -119,10 +122,15 @@ export const upload = async ({ file, context, bucketName }) => { let res; // TODO(jim): Make this smarter. + + const storageDealRoute = + routes && routes.storageDealUpload ? routes.storageDealUpload : `/api/data/deal/`; + const generalRoute = routes && routes.upload ? routes.upload : "/api/data/"; + if (bucketName && bucketName === STAGING_DEAL_BUCKET) { - res = await _privateUploadMethod(`/api/data/deal/${file.name}`, file); + res = await _privateUploadMethod(`${storageDealRoute}${file.name}`, file); } else { - res = await _privateUploadMethod(`/api/data/${file.name}`, file); + res = await _privateUploadMethod(`${generalRoute}${file.name}`, file); } if (!res || res.error || !res.data) { @@ -176,8 +184,7 @@ export const uploadToSlate = async ({ responses, slate }) => { name: "create-alert", detail: { alert: { - message: - "We're having trouble connecting right now. Please try again later", + message: "We're having trouble connecting right now. Please try again later", }, }, }); @@ -193,9 +200,7 @@ export const uploadToSlate = async ({ responses, slate }) => { skipped = addResponse.skipped; } } - let message = `${added || 0} file${ - added !== 1 ? "s" : "" - } uploaded to slate. `; + let message = `${added || 0} file${added !== 1 ? "s" : ""} uploaded to slate. `; if (skipped) { message += `${skipped || 0} duplicate / existing file${ added !== 1 ? "s were" : " was" diff --git a/components/core/Application.js b/components/core/Application.js index c5828da1..d28644a0 100644 --- a/components/core/Application.js +++ b/components/core/Application.js @@ -303,6 +303,7 @@ export default class ApplicationPage extends React.Component { response = await FileUtilities.upload({ file: files[i], context: this, + routes: this.props.resources, }); } catch (e) { console.log(e); @@ -817,6 +818,7 @@ export default class ApplicationPage extends React.Component { onRehydrate: this.rehydrate, sceneId: current.target.id, mobile: this.state.mobile, + resources: this.props.resources, }); let sidebarElement; @@ -837,6 +839,7 @@ export default class ApplicationPage extends React.Component { onSidebarLoading: this._handleSidebarLoading, onAction: this._handleAction, onRehydrate: this.rehydrate, + resources: this.props.resources, }); } diff --git a/node_common/environment.js b/node_common/environment.js index 331eb0e2..4d172921 100644 --- a/node_common/environment.js +++ b/node_common/environment.js @@ -14,8 +14,7 @@ export const POSTGRES_ADMIN_USERNAME = process.env.POSTGRES_ADMIN_USERNAME; export const POSTGRES_HOSTNAME = process.env.POSTGRES_HOSTNAME; export const POSTGRES_DATABASE = process.env.POSTGRES_DATABASE; export const JWT_SECRET = process.env.JWT_SECRET; -export const LOCAL_PASSWORD_ROUNDS_MANUAL = - process.env.LOCAL_PASSWORD_ROUNDS_MANUAL; +export const LOCAL_PASSWORD_ROUNDS_MANUAL = process.env.LOCAL_PASSWORD_ROUNDS_MANUAL; export const LOCAL_PASSWORD_ROUNDS = process.env.LOCAL_PASSWORD_ROUNDS; // TODO(jim): @@ -34,3 +33,7 @@ export const TEXTILE_HUB_STAGING_HOST = process.env.TEXTILE_HUB_STAGING_HOST; export const SOCIAL_SLACK_WEBHOOK_KEY = process.env.SOCIAL_SLACK_WEBHOOK_KEY; export const SUPPORT_SLACK_WEBHOOK_KEY = process.env.SUPPORT_SLACK_WEBHOOK_KEY; export const TEXTILE_SLACK_WEBHOOK_KEY = process.env.TEXTILE_SLACK_WEBHOOK_KEY; + +// NOTE(jim): customize resources +export const RESOURCE_URI_UPLOAD = process.env.RESOURCE_URI_UPLOAD; +export const RESOURCE_URI_STORAGE_UPLOAD = process.env.RESOURCE_URI_STORAGE_UPLOAD; diff --git a/node_common/middleware.js b/node_common/middleware.js index af7463f1..0852f0ff 100644 --- a/node_common/middleware.js +++ b/node_common/middleware.js @@ -19,32 +19,20 @@ export const init = (middleware) => { }; export const CORS = async (req, res, next) => { - /* res.header("Access-Control-Allow-Origin", "*"); - - res.header( - "Access-Control-Allow-Methods", - "GET, POST, PATCH, PUT, DELETE, OPTIONS" - ); - - res.header( - "Access-Control-Allow-Headers", - "Origin, Accept, Content-Type, Authorization" - ); + res.header("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS"); + res.header("Access-Control-Allow-Headers", "Origin, Accept, Content-Type, Authorization"); if (req.method === "OPTIONS") { return res.status(200).end(); } - */ next(); }; export const RequireCookieAuthentication = async (req, res, next) => { if (Strings.isEmpty(req.headers.cookie)) { - return res - .status(403) - .json({ decorator: "SERVER_AUTH_USER_NO_TOKEN", error: true }); + return res.status(403).json({ decorator: "SERVER_AUTH_USER_NO_TOKEN", error: true }); } const token = req.headers.cookie.replace( @@ -60,15 +48,11 @@ export const RequireCookieAuthentication = async (req, res, next) => { }); if (!user || user.error) { - return res - .status(403) - .json({ decorator: "SERVER_AUTH_USER_NOT_FOUND", error: true }); + return res.status(403).json({ decorator: "SERVER_AUTH_USER_NOT_FOUND", error: true }); } } catch (err) { console.log(err); - return res - .status(403) - .json({ decorator: "SERVER_AUTH_USER_ERROR", error: true }); + return res.status(403).json({ decorator: "SERVER_AUTH_USER_ERROR", error: true }); } next(); diff --git a/pages/_/index.js b/pages/_/index.js index e818d275..be42aed8 100644 --- a/pages/_/index.js +++ b/pages/_/index.js @@ -8,6 +8,7 @@ export const getServerSideProps = async ({ query }) => { viewer: query.viewer, analytics: query.analytics, mobile: query.mobile, + resources: query.resources, }, }; }; @@ -19,6 +20,7 @@ export default class ApplicationPage extends React.Component { viewer={this.props.viewer} analytics={this.props.analytics} mobile={this.props.mobile} + resources={this.props.resources} /> ); } diff --git a/pages/api/data/[upload].js b/pages/api/data/[upload].js index a6925e6e..a1730b38 100644 --- a/pages/api/data/[upload].js +++ b/pages/api/data/[upload].js @@ -19,9 +19,7 @@ export default async (req, res) => { }); if (!user || user.error) { - return res - .status(403) - .send({ decorator: "UPLOAD_NOT_ALLOWED", error: true }); + return res.status(403).send({ decorator: "UPLOAD_NOT_ALLOWED", error: true }); } let response = null; @@ -35,15 +33,11 @@ export default async (req, res) => { } if (!response) { - return res - .status(413) - .send({ decorator: "SERVER_UPLOAD_ERROR", error: true }); + return res.status(413).send({ decorator: "SERVER_UPLOAD_ERROR", error: true }); } if (response.error) { - return res - .status(413) - .send({ decorator: response.decorator, error: response.error }); + return res.status(413).send({ decorator: response.decorator, error: response.error }); } const { data, ipfs } = response; @@ -52,14 +46,11 @@ export default async (req, res) => { ipfs, }); - const slateId = req.params ? req.params.b : null; - return res.status(200).send({ decorator: "SERVER_UPLOAD", data: { data: finalData, owner_user_id: user.id, - slate_id: slateId, }, }); }; diff --git a/pages/api/data/deal/[upload].js b/pages/api/data/deal/[upload].js index 1bc72d7a..e86fa782 100644 --- a/pages/api/data/deal/[upload].js +++ b/pages/api/data/deal/[upload].js @@ -22,9 +22,7 @@ export default async (req, res) => { }); if (!user || user.error) { - return res - .status(403) - .send({ decorator: "UPLOAD_NOT_ALLOWED", error: true }); + return res.status(403).send({ decorator: "UPLOAD_NOT_ALLOWED", error: true }); } let response = null; @@ -39,15 +37,11 @@ export default async (req, res) => { } if (!response) { - return res - .status(413) - .send({ decorator: "SERVER_UPLOAD_ERROR", error: true }); + return res.status(413).send({ decorator: "SERVER_UPLOAD_ERROR", error: true }); } if (response.error) { - return res - .status(413) - .send({ decorator: response.decorator, error: response.error }); + return res.status(413).send({ decorator: response.decorator, error: response.error }); } return res.status(200).send({ diff --git a/scenes/SceneEditAccount.js b/scenes/SceneEditAccount.js index ed0343ff..8d8bf7ef 100644 --- a/scenes/SceneEditAccount.js +++ b/scenes/SceneEditAccount.js @@ -38,12 +38,9 @@ export default class SceneEditAccount extends React.Component { photo: this.props.viewer.data.photo, name: this.props.viewer.data.name, deleting: false, - allow_filecoin_directory_listing: this.props.viewer - .allow_filecoin_directory_listing, - allow_automatic_data_storage: this.props.viewer - .allow_automatic_data_storage, - allow_encrypted_data_storage: this.props.viewer - .allow_encrypted_data_storage, + allow_filecoin_directory_listing: this.props.viewer.allow_filecoin_directory_listing, + allow_automatic_data_storage: this.props.viewer.allow_automatic_data_storage, + allow_encrypted_data_storage: this.props.viewer.allow_encrypted_data_storage, changingPassword: false, changingUsername: false, changingAvatar: false, @@ -78,7 +75,7 @@ export default class SceneEditAccount extends React.Component { return; } - const response = await FileUtilities.upload({ file }); + const response = await FileUtilities.upload({ file, routes: this.props.resources }); if (!response) { dispatchCustomEvent({ @@ -140,8 +137,7 @@ export default class SceneEditAccount extends React.Component { photo: this.state.photo, body: this.state.body, name: this.state.name, - allow_filecoin_directory_listing: this.state - .allow_filecoin_directory_listing, + allow_filecoin_directory_listing: this.state.allow_filecoin_directory_listing, allow_automatic_data_storage: this.state.allow_automatic_data_storage, allow_encrypted_data_storage: this.state.allow_encrypted_data_storage, }, @@ -247,19 +243,10 @@ export default class SceneEditAccount extends React.Component { description="This image will appear in various lists." /> - +
- + - Show your successful deals on a directory page where others can - retrieve them. + Show your successful deals on a directory page where others can retrieve them. - Allow Slate to make archive storage deals on your behalf to the - Filecoin Network. You will get a receipt in the Filecoin section. + Allow Slate to make archive storage deals on your behalf to the Filecoin Network. You will + get a receipt in the Filecoin section. - Force encryption on archive storage deals (only you can see retrieved - data from the Filecoin network). + Force encryption on archive storage deals (only you can see retrieved data from the + Filecoin network).
@@ -320,8 +306,7 @@ export default class SceneEditAccount extends React.Component { label="Username" description={ - This is your username on Slate. Your username is unique and used - for your profile URL{" "} + This is your username on Slate. Your username is unique and used for your profile URL{" "} {profileURL} @@ -334,10 +319,7 @@ export default class SceneEditAccount extends React.Component { />
- + Change username
@@ -363,10 +345,7 @@ export default class SceneEditAccount extends React.Component { />
- + Update information
@@ -413,10 +392,7 @@ export default class SceneEditAccount extends React.Component { />
- + Delete my account
diff --git a/scenes/SceneMakeFilecoinDeal.js b/scenes/SceneMakeFilecoinDeal.js index 454d4d0e..dd1e649c 100644 --- a/scenes/SceneMakeFilecoinDeal.js +++ b/scenes/SceneMakeFilecoinDeal.js @@ -102,6 +102,7 @@ export default class SceneMakeFilecoinDeal extends React.Component { const response = await FileUtilities.upload({ bucketName: STAGING_DEAL_BUCKET, + routes: this.props.resources, file, }); } diff --git a/server.js b/server.js index aea59b79..d13b941a 100644 --- a/server.js +++ b/server.js @@ -93,6 +93,10 @@ app.prepare().then(async () => { viewer, analytics, mobile, + resources: { + storageDealUpload: Environment.RESOURCE_URI_STORAGE_UPLOAD, + upload: Environment.RESOURCE_URI_UPLOAD, + }, }); }); @@ -119,7 +123,13 @@ app.prepare().then(async () => { // TODO(jim): Temporary workaround if (!Validations.userRoute(req.params.username)) { - return handler(req, res, req.url, { mobile }); + return handler(req, res, req.url, { + mobile, + resources: { + storageDealUpload: Environment.RESOURCE_URI_STORAGE_UPLOAD, + upload: Environment.RESOURCE_URI_UPLOAD, + }, + }); } const id = Utilities.getIdFromCookie(req); @@ -152,6 +162,10 @@ app.prepare().then(async () => { viewer, creator: Serializers.user({ ...creator, slates }), mobile, + resources: { + storageDealUpload: Environment.RESOURCE_URI_STORAGE_UPLOAD, + upload: Environment.RESOURCE_URI_UPLOAD, + }, }); }); @@ -160,7 +174,13 @@ app.prepare().then(async () => { // TODO(jim): Temporary workaround if (!Validations.userRoute(req.params.username)) { - return handler(req, res, req.url, { mobile }); + return handler(req, res, req.url, { + mobile, + resources: { + storageDealUpload: Environment.RESOURCE_URI_STORAGE_UPLOAD, + upload: Environment.RESOURCE_URI_UPLOAD, + }, + }); } const slate = await Data.getSlateByName({ @@ -208,6 +228,10 @@ app.prepare().then(async () => { creator: Serializers.user(creator), slate, mobile, + resources: { + storageDealUpload: Environment.RESOURCE_URI_STORAGE_UPLOAD, + upload: Environment.RESOURCE_URI_UPLOAD, + }, }); });