From af25eaf2a848278a58f0993cba2e68c05da0760c Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 29 Oct 2019 20:00:54 -0400 Subject: comments and fixes for google photos server sid --- src/client/util/Import & Export/ImageUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/util/Import & Export/ImageUtils.ts') diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index c9abf38fa..914f4870a 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -3,7 +3,7 @@ import { ImageField } from "../../../new_fields/URLField"; import { Cast, StrCast } from "../../../new_fields/Types"; import { RouteStore } from "../../../server/RouteStore"; import { Docs } from "../../documents/Documents"; -import { Identified } from "../../Network"; +import { Networking } from "../../Network"; import { Id } from "../../../new_fields/FieldSymbols"; import { Utils } from "../../../Utils"; @@ -15,7 +15,7 @@ export namespace ImageUtils { return false; } const source = field.url.href; - const response = await Identified.PostToServer(RouteStore.inspectImage, { source }); + const response = await Networking.PostToServer(RouteStore.inspectImage, { source }); const { error, data } = response.exifData; document.exif = error || Docs.Get.DocumentHierarchyFromJson(data); return data !== undefined; -- cgit v1.2.3-70-g09d2 From 36ad83493d2bd58dc6fe62df6002789ccc1b06a1 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sun, 10 Nov 2019 14:56:58 -0500 Subject: no more RouteStore --- src/Utils.ts | 3 +- src/client/apis/GoogleAuthenticationManager.tsx | 5 +-- .../apis/google_docs/GoogleApiClientUtils.ts | 7 ++-- .../apis/google_docs/GooglePhotosClientUtils.ts | 5 +-- src/client/cognitive_services/CognitiveServices.ts | 3 +- src/client/util/History.ts | 3 +- .../util/Import & Export/DirectoryImportBox.tsx | 3 +- src/client/util/Import & Export/ImageUtils.ts | 7 ++-- src/client/util/SharingManager.tsx | 3 +- src/client/views/MainView.tsx | 5 +-- src/client/views/collections/CollectionSubView.tsx | 4 +- src/client/views/nodes/ImageBox.tsx | 3 +- src/client/views/nodes/VideoBox.tsx | 3 +- src/client/views/search/SearchBox.tsx | 3 +- src/mobile/ImageUpload.tsx | 3 +- src/new_fields/RichTextUtils.ts | 3 +- src/server/ApiManagers/DeleteManager.ts | 13 +++---- src/server/ApiManagers/ExportManager.ts | 5 +-- src/server/ApiManagers/PDFManager.ts | 2 +- src/server/ApiManagers/UploadManager.ts | 15 +++----- src/server/ApiManagers/UserManager.ts | 7 ++-- src/server/ApiManagers/UtilManager.ts | 7 ++++ src/server/Initialization.ts | 28 +++++++------- src/server/RouteManager.ts | 5 +-- src/server/RouteStore.ts | 45 ---------------------- src/server/RouteSubscriber.ts | 2 +- src/server/authentication/config/passport.ts | 5 +-- .../authentication/controllers/user_controller.ts | 32 +++++++-------- .../authentication/models/current_user_utils.ts | 7 ++-- src/server/index.ts | 26 ++++++------- 30 files changed, 96 insertions(+), 166 deletions(-) delete mode 100644 src/server/RouteStore.ts (limited to 'src/client/util/Import & Export/ImageUtils.ts') diff --git a/src/Utils.ts b/src/Utils.ts index 9a2f01f80..abff2eaba 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -2,7 +2,6 @@ import v4 = require('uuid/v4'); import v5 = require("uuid/v5"); import { Socket } from 'socket.io'; import { Message } from './server/Message'; -import { RouteStore } from './server/RouteStore'; export namespace Utils { @@ -46,7 +45,7 @@ export namespace Utils { } export function CorsProxy(url: string): string { - return prepend(RouteStore.corsProxy + "/") + encodeURIComponent(url); + return prepend("/corsProxy/") + encodeURIComponent(url); } export function CopyText(text: string) { diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx index 1ec9d8412..ae77c4b7b 100644 --- a/src/client/apis/GoogleAuthenticationManager.tsx +++ b/src/client/apis/GoogleAuthenticationManager.tsx @@ -4,7 +4,6 @@ import * as React from "react"; import MainViewModal from "../views/MainViewModal"; import { Opt } from "../../new_fields/Doc"; import { Networking } from "../Network"; -import { RouteStore } from "../../server/RouteStore"; import "./GoogleAuthenticationManager.scss"; const AuthenticationUrl = "https://accounts.google.com/o/oauth2/v2/auth"; @@ -31,7 +30,7 @@ export default class GoogleAuthenticationManager extends React.Component<{}> { } public fetchOrGenerateAccessToken = async () => { - let response = await Networking.FetchFromServer(RouteStore.readGoogleAccessToken); + let response = await Networking.FetchFromServer("/readGoogleAccessToken"); // if this is an authentication url, activate the UI to register the new access token if (new RegExp(AuthenticationUrl).test(response)) { this.isOpen = true; @@ -44,7 +43,7 @@ export default class GoogleAuthenticationManager extends React.Component<{}> { return; } const { access_token, avatar, name } = await Networking.PostToServer( - RouteStore.writeGoogleAccessToken, + "/writeGoogleAccessToken", { authenticationCode } ); runInAction(() => { diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts index 183679317..26c7f8d2e 100644 --- a/src/client/apis/google_docs/GoogleApiClientUtils.ts +++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts @@ -1,5 +1,4 @@ import { docs_v1, slides_v1 } from "googleapis"; -import { RouteStore } from "../../../server/RouteStore"; import { Opt } from "../../../new_fields/Doc"; import { isArray } from "util"; import { EditorState } from "prosemirror-state"; @@ -77,7 +76,7 @@ export namespace GoogleApiClientUtils { * @returns the documentId of the newly generated document, or undefined if the creation process fails. */ export const create = async (options: CreateOptions): Promise => { - const path = `${RouteStore.googleDocs}/Documents/${Actions.Create}`; + const path = `/googleDocs/Documents/${Actions.Create}`; const parameters = { requestBody: { title: options.title || `Dash Export (${new Date().toDateString()})` @@ -154,7 +153,7 @@ export namespace GoogleApiClientUtils { } export const retrieve = async (options: RetrieveOptions): Promise => { - const path = `${RouteStore.googleDocs}/Documents/${Actions.Retrieve}`; + const path = `/googleDocs/Documents/${Actions.Retrieve}`; try { const parameters = { documentId: options.documentId }; const schema: RetrievalResult = await Networking.PostToServer(path, parameters); @@ -165,7 +164,7 @@ export namespace GoogleApiClientUtils { }; export const update = async (options: UpdateOptions): Promise => { - const path = `${RouteStore.googleDocs}/Documents/${Actions.Update}`; + const path = `/googleDocs/Documents/${Actions.Update}`; const parameters = { documentId: options.documentId, requestBody: { diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index 402fc64b5..bf8897061 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -1,5 +1,4 @@ import { Utils } from "../../../Utils"; -import { RouteStore } from "../../../server/RouteStore"; import { ImageField } from "../../../new_fields/URLField"; import { Cast, StrCast } from "../../../new_fields/Types"; import { Doc, Opt, DocListCastAsync } from "../../../new_fields/Doc"; @@ -307,7 +306,7 @@ export namespace GooglePhotos { }; export const WriteMediaItemsToServer = async (body: { mediaItems: any[] }): Promise => { - const uploads = await Networking.PostToServer(RouteStore.googlePhotosMediaDownload, body); + const uploads = await Networking.PostToServer("/googlePhotosMediaDownload", body); return uploads; }; @@ -345,7 +344,7 @@ export namespace GooglePhotos { media.push({ url, description }); } if (media.length) { - const results = await Networking.PostToServer(RouteStore.googlePhotosMediaUpload, { media, album }); + const results = await Networking.PostToServer("/googlePhotosMediaUpload", { media, album }); return results; } }; diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index 08fcb4883..af5fb39fc 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -2,7 +2,6 @@ import * as request from "request-promise"; import { Doc, Field, Opt } from "../../new_fields/Doc"; import { Cast } from "../../new_fields/Types"; import { Docs } from "../documents/Documents"; -import { RouteStore } from "../../server/RouteStore"; import { Utils } from "../../Utils"; import { InkData } from "../../new_fields/InkField"; import { UndoManager } from "../util/UndoManager"; @@ -39,7 +38,7 @@ export enum Confidence { export namespace CognitiveServices { const ExecuteQuery = async (service: Service, manager: APIManager, data: D): Promise => { - return fetch(Utils.prepend(`${RouteStore.cognitiveServices}/${service}`)).then(async response => { + return fetch(Utils.prepend(`cognitiveServices/${service}`)).then(async response => { let apiKey = await response.text(); if (!apiKey) { console.log(`No API key found for ${service}: ensure index.ts has access to a .env file in your root directory`); diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 899abbe40..1c51236cb 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -1,6 +1,5 @@ import { Doc, Opt, Field } from "../../new_fields/Doc"; import { DocServer } from "../DocServer"; -import { RouteStore } from "../../server/RouteStore"; import { MainView } from "../views/MainView"; import * as qs from 'query-string'; import { Utils, OmitKeys } from "../../Utils"; @@ -26,7 +25,7 @@ export namespace HistoryUtil { // const handlers: ((state: ParsedUrl | null) => void)[] = []; function onHistory(e: PopStateEvent) { - if (window.location.pathname !== RouteStore.home) { + if (window.location.pathname !== "/home") { const url = e.state as ParsedUrl || parseUrl(window.location); if (url) { switch (url.type) { diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 2e0ba25eb..437e7766b 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -1,7 +1,6 @@ import "fs"; import React = require("react"); import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc"; -import { RouteStore } from "../../../server/RouteStore"; import { action, observable, autorun, runInAction, computed, reaction, IReactionDisposer } from "mobx"; import { FieldViewProps, FieldView } from "../../views/nodes/FieldView"; import Measure, { ContentRect } from "react-measure"; @@ -124,7 +123,7 @@ export default class DirectoryImportBox extends React.Component formData.append(Utils.GenerateGuid(), file); }); - collector.push(...(await Networking.PostFormDataToServer(RouteStore.upload, formData))); + collector.push(...(await Networking.PostFormDataToServer("/upload", formData))); runInAction(() => this.completed += batch.length); }); diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index 914f4870a..ca80f3bca 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -1,7 +1,6 @@ -import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc"; +import { Doc } from "../../../new_fields/Doc"; import { ImageField } from "../../../new_fields/URLField"; import { Cast, StrCast } from "../../../new_fields/Types"; -import { RouteStore } from "../../../server/RouteStore"; import { Docs } from "../../documents/Documents"; import { Networking } from "../../Network"; import { Id } from "../../../new_fields/FieldSymbols"; @@ -15,7 +14,7 @@ export namespace ImageUtils { return false; } const source = field.url.href; - const response = await Networking.PostToServer(RouteStore.inspectImage, { source }); + const response = await Networking.PostToServer("/inspectImage", { source }); const { error, data } = response.exifData; document.exif = error || Docs.Get.DocumentHierarchyFromJson(data); return data !== undefined; @@ -23,7 +22,7 @@ export namespace ImageUtils { export const ExportHierarchyToFileSystem = async (collection: Doc): Promise => { const a = document.createElement("a"); - a.href = Utils.prepend(`${RouteStore.imageHierarchyExport}/${collection[Id]}`); + a.href = Utils.prepend(`imageHierarchyExport/${collection[Id]}`); a.download = `Dash Export [${StrCast(collection.title)}].zip`; a.click(); }; diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 2082d6324..cc1d628b1 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -4,7 +4,6 @@ import MainViewModal from "../views/MainViewModal"; import { Doc, Opt, DocCastAsync } from "../../new_fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../new_fields/Types"; -import { RouteStore } from "../../server/RouteStore"; import * as RequestPromise from "request-promise"; import { Utils } from "../../Utils"; import "./SharingManager.scss"; @@ -104,7 +103,7 @@ export default class SharingManager extends React.Component<{}> { } populateUsers = async () => { - let userList = await RequestPromise.get(Utils.prepend(RouteStore.getUsers)); + let userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { let isCandidate = user.email !== Doc.CurrentUserEmail; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 39585113b..0c5a1003b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -12,7 +12,6 @@ import { List } from '../../new_fields/List'; import { listSpec } from '../../new_fields/Schema'; import { Cast, FieldValue, StrCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; -import { RouteStore } from '../../server/RouteStore'; import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; @@ -74,7 +73,7 @@ export class MainView extends React.Component { this._urlState = HistoryUtil.parseUrl(window.location) || {} as any; // causes errors to be generated when modifying an observable outside of an action configure({ enforceActions: "observed" }); - if (window.location.pathname !== RouteStore.home) { + if (window.location.pathname !== "/home") { let pathname = window.location.pathname.substr(1).split("/"); if (pathname.length > 1) { let type = pathname[0]; @@ -395,7 +394,7 @@ export class MainView extends React.Component { zoomToScale={emptyFunction} getScale={returnOne}> - ; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 6e8e4fa12..306f8e052 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -8,7 +8,6 @@ import { listSpec } from "../../../new_fields/Schema"; import { ScriptField } from "../../../new_fields/ScriptField"; import { Cast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; -import { RouteStore } from "../../../server/RouteStore"; import { Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { DocumentType } from "../../documents/DocumentTypes"; @@ -243,7 +242,6 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { let promises: Promise[] = []; // tslint:disable-next-line:prefer-for-of for (let i = 0; i < e.dataTransfer.items.length; i++) { - const upload = window.location.origin + RouteStore.upload; let item = e.dataTransfer.items[i]; if (item.kind === "string" && item.type.indexOf("uri") !== -1) { let str: string; @@ -268,7 +266,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { } let dropFileName = file ? file.name : "-empty-"; - let prom = fetch(upload, { + let prom = fetch(Utils.prepend("/upload"), { method: 'POST', body: formData }).then(async (res: Response) => { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 9f39eccea..07fd832be 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -12,7 +12,6 @@ import { createSchema, listSpec, makeInterface } from '../../../new_fields/Schem import { ComputedField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, FieldValue, NumCast, StrCast } from '../../../new_fields/Types'; import { AudioField, ImageField } from '../../../new_fields/URLField'; -import { RouteStore } from '../../../server/RouteStore'; import { Utils, returnOne, emptyFunction } from '../../../Utils'; import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices'; import { Docs } from '../../documents/Documents'; @@ -152,7 +151,7 @@ export class ImageBox extends DocAnnotatableComponent { if (isRelease) { return _permission_denied(res, deletionPermissionError); } await WebSocket.deleteFields(); - res.redirect(RouteStore.home); + res.redirect("/home"); } }); register({ method: Method.GET, - subscription: RouteStore.deleteAll, + subscription: "/deleteAll", onValidation: async ({ res, isRelease }) => { if (isRelease) { return _permission_denied(res, deletionPermissionError); } await WebSocket.deleteAll(); - res.redirect(RouteStore.home); + res.redirect("/home"); } }); @@ -41,7 +40,7 @@ export default class DeleteManager extends ApiManager { return _permission_denied(res, deletionPermissionError); } await Database.Auxiliary.DeleteAll(); - res.redirect(RouteStore.delete); + res.redirect("/delete"); } }); @@ -53,7 +52,7 @@ export default class DeleteManager extends ApiManager { return _permission_denied(res, deletionPermissionError); } await Database.Auxiliary.GoogleAuthenticationToken.DeleteAll(); - res.redirect(RouteStore.delete); + res.redirect("/delete"); } }); diff --git a/src/server/ApiManagers/ExportManager.ts b/src/server/ApiManagers/ExportManager.ts index d42db1056..fc6ba0d22 100644 --- a/src/server/ApiManagers/ExportManager.ts +++ b/src/server/ApiManagers/ExportManager.ts @@ -1,7 +1,6 @@ import ApiManager, { Registration } from "./ApiManager"; import { Method } from "../RouteManager"; import RouteSubscriber from "../RouteSubscriber"; -import { RouteStore } from "../RouteStore"; import * as Archiver from 'archiver'; import * as express from 'express'; import { Database } from "../database"; @@ -32,7 +31,7 @@ export default class DownloadManager extends ApiManager { */ register({ method: Method.GET, - subscription: new RouteSubscriber(RouteStore.imageHierarchyExport).add('docId'), + subscription: new RouteSubscriber("imageHierarchyExport").add('docId'), onValidation: async ({ req, res }) => { const id = req.params.docId; const hierarchy: Hierarchy = {}; @@ -43,7 +42,7 @@ export default class DownloadManager extends ApiManager { register({ method: Method.GET, - subscription: new RouteSubscriber("/downloadId").add("docId"), + subscription: new RouteSubscriber("downloadId").add("docId"), onValidation: async ({ req, res }) => { return BuildAndDispatchZip(res, async zip => { const { id, docs, files } = await getDocs(req.params.docId); diff --git a/src/server/ApiManagers/PDFManager.ts b/src/server/ApiManagers/PDFManager.ts index f328557b4..632b4965a 100644 --- a/src/server/ApiManagers/PDFManager.ts +++ b/src/server/ApiManagers/PDFManager.ts @@ -15,7 +15,7 @@ export default class PDFManager extends ApiManager { register({ method: Method.GET, - subscription: new RouteSubscriber("/thumbnail").add("filename"), + subscription: new RouteSubscriber("thumbnail").add("filename"), onValidation: ({ req, res }) => { let filename = req.params.filename; let noExt = filename.substring(0, filename.length - ".png".length); diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 38635eda5..01abdab54 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -6,7 +6,6 @@ var AdmZip = require('adm-zip'); import * as path from 'path'; import { createReadStream, createWriteStream, unlink, readFileSync } from "fs"; import { publicDirectory, filesDirectory, Partitions } from ".."; -import { RouteStore } from "../RouteStore"; import { Database } from "../database"; import { DashUploadUtils } from "../DashUploadUtils"; import { Opt } from "../../new_fields/Doc"; @@ -85,12 +84,8 @@ export default class UploadManager extends ApiManager { let dirname = path.dirname(entry.entryName) + "/"; let extname = path.extname(entry.entryName); let basename = path.basename(entry.entryName).split(".")[0]; - // zip.extractEntryTo(dirname + basename + "_o" + extname, __dirname + RouteStore.public, true, false); - // zip.extractEntryTo(dirname + basename + "_s" + extname, __dirname + RouteStore.public, true, false); - // zip.extractEntryTo(dirname + basename + "_m" + extname, __dirname + RouteStore.public, true, false); - // zip.extractEntryTo(dirname + basename + "_l" + extname, __dirname + RouteStore.public, true, false); try { - zip.extractEntryTo(entry.entryName, __dirname + RouteStore.public, true, false); + zip.extractEntryTo(entry.entryName, publicDirectory, true, false); dirname = "/" + dirname; createReadStream(publicDirectory + dirname + basename + extname).pipe(createWriteStream(publicDirectory + dirname + basename + "_o" + extname)); @@ -131,7 +126,7 @@ export default class UploadManager extends ApiManager { register({ method: Method.POST, - subscription: RouteStore.upload, + subscription: "/upload", onValidation: async ({ req, res }) => { let form = new formidable.IncomingForm(); form.uploadDir = filesDirectory; @@ -147,7 +142,7 @@ export default class UploadManager extends ApiManager { let dataBuffer = readFileSync(filesDirectory + filename); const result: ParsedPDF = await pdf(dataBuffer); await new Promise((resolve, reject) => { - const path = filesDirectory + Partitions.PdfText + "/" + filename.substring(0, filename.length - ".pdf".length) + ".txt"; + const path = filesDirectory + Partitions.pdf_text + "/" + filename.substring(0, filename.length - ".pdf".length) + ".txt"; createWriteStream(path).write(result.text, error => { if (!error) { resolve(); @@ -171,7 +166,7 @@ export default class UploadManager extends ApiManager { register({ method: Method.POST, - subscription: RouteStore.inspectImage, + subscription: "/inspectImage", onValidation: async ({ req, res }) => { const { source } = req.body; if (typeof source === "string") { @@ -184,7 +179,7 @@ export default class UploadManager extends ApiManager { register({ method: Method.POST, - subscription: RouteStore.dataUriToImage, + subscription: "/uploadURI", onValidation: ({ req, res }) => { const uri = req.body.uri; const filename = req.body.name; diff --git a/src/server/ApiManagers/UserManager.ts b/src/server/ApiManagers/UserManager.ts index fe1ce7f2b..51a434fcf 100644 --- a/src/server/ApiManagers/UserManager.ts +++ b/src/server/ApiManagers/UserManager.ts @@ -1,7 +1,6 @@ import ApiManager, { Registration } from "./ApiManager"; import { Method } from "../RouteManager"; import { WebSocket } from "../Websocket/Websocket"; -import { RouteStore } from "../RouteStore"; import { Database } from "../database"; export default class UserManager extends ApiManager { @@ -10,7 +9,7 @@ export default class UserManager extends ApiManager { register({ method: Method.GET, - subscription: RouteStore.getUsers, + subscription: "/getUsers", onValidation: async ({ res }) => { const cursor = await Database.Instance.query({}, { email: 1, userDocumentId: 1 }, "users"); const results = await cursor.toArray(); @@ -20,13 +19,13 @@ export default class UserManager extends ApiManager { register({ method: Method.GET, - subscription: RouteStore.getUserDocumentId, + subscription: "/getUserDocumentId", onValidation: ({ res, user }) => res.send(user.userDocumentId) }); register({ method: Method.GET, - subscription: RouteStore.getCurrUser, + subscription: "/getCurrentUser", onValidation: ({ res, user }) => res.send(JSON.stringify(user)), onUnauthenticated: ({ res }) => res.send(JSON.stringify({ id: "__guest__", email: "" })) }); diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts index 61cda2e9b..c1234be6c 100644 --- a/src/server/ApiManagers/UtilManager.ts +++ b/src/server/ApiManagers/UtilManager.ts @@ -2,11 +2,18 @@ import ApiManager, { Registration } from "./ApiManager"; import { Method } from "../RouteManager"; import { exec } from 'child_process'; import { command_line } from "../ActionUtilities"; +import RouteSubscriber from "../RouteSubscriber"; export default class UtilManager extends ApiManager { protected initialize(register: Registration): void { + register({ + method: Method.GET, + subscription: new RouteSubscriber("environment").add("key"), + onValidation: ({ req, res }) => res.send(process.env[req.params.key]) + }); + register({ method: Method.GET, subscription: "/pull", diff --git a/src/server/Initialization.ts b/src/server/Initialization.ts index fbb5ae7a6..306058d81 100644 --- a/src/server/Initialization.ts +++ b/src/server/Initialization.ts @@ -9,7 +9,6 @@ import flash = require('connect-flash'); import { Database } from './database'; import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/controllers/user_controller'; const MongoStore = require('connect-mongo')(session); -import { RouteStore } from './RouteStore'; import RouteManager from './RouteManager'; import * as webpack from 'webpack'; const config = require('../../webpack.config'); @@ -18,6 +17,8 @@ import * as wdm from 'webpack-dev-middleware'; import * as whm from 'webpack-hot-middleware'; import * as fs from 'fs'; import * as request from 'request'; +import RouteSubscriber from './RouteSubscriber'; +import { publicDirectory } from '.'; export type RouteSetter = (server: RouteManager) => void; export interface InitializationOptions { @@ -29,8 +30,8 @@ export default async function InitializeServer(options: InitializationOptions) { const { listenAtPort, routeSetter } = options; const server = buildWithMiddleware(express()); - server.use(express.static(__dirname + RouteStore.public)); - server.use(RouteStore.images, express.static(__dirname + RouteStore.public)); + server.use(express.static(publicDirectory)); + server.use("/images", express.static(publicDirectory)); server.use(wdm(compiler, { publicPath: config.output.publicPath })); server.use(whm(compiler)); @@ -87,24 +88,25 @@ function determineEnvironment() { } function registerAuthenticationRoutes(server: express.Express) { - server.get(RouteStore.signup, getSignup); - server.post(RouteStore.signup, postSignup); + server.get("/signup", getSignup); + server.post("/signup", postSignup); - server.get(RouteStore.login, getLogin); - server.post(RouteStore.login, postLogin); + server.get("/login", getLogin); + server.post("/login", postLogin); - server.get(RouteStore.logout, getLogout); + server.get("/logout", getLogout); - server.get(RouteStore.forgot, getForgot); - server.post(RouteStore.forgot, postForgot); + server.get("/forgotPassword", getForgot); + server.post("/forgotPassword", postForgot); - server.get(RouteStore.reset, getReset); - server.post(RouteStore.reset, postReset); + const reset = new RouteSubscriber("resetPassword").add("token").build; + server.get(reset, getReset); + server.post(reset, postReset); } function registerCorsProxy(server: express.Express) { const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; - server.use(RouteStore.corsProxy, (req, res) => { + server.use("/corsProxy", (req, res) => { req.pipe(request(decodeURIComponent(req.url.substring(1)))).on("response", res => { const headers = Object.keys(res.headers); headers.forEach(headerName => { diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index c1d38327f..3aae5734a 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -1,5 +1,4 @@ import RouteSubscriber from "./RouteSubscriber"; -import { RouteStore } from "./RouteStore"; import { DashUserModel } from "./authentication/models/user_model"; import * as express from 'express'; @@ -67,10 +66,10 @@ export default class RouteManager { if (onUnauthenticated) { await tryExecute(onUnauthenticated, core); if (!res.headersSent) { - res.redirect(RouteStore.login); + res.redirect("/login"); } } else { - res.redirect(RouteStore.login); + res.redirect("/login"); } } setTimeout(() => { diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts deleted file mode 100644 index a310d0c95..000000000 --- a/src/server/RouteStore.ts +++ /dev/null @@ -1,45 +0,0 @@ -// PREPEND ALL ROUTES WITH FORWARD SLASHES! - -export enum RouteStore { - // GENERAL - root = "/", - home = "/home", - corsProxy = "/corsProxy", - delete = "/delete", - deleteAll = "/deleteAll", - pull = "/pull", - - // UPLOAD AND STATIC FILE SERVING - public = "/public", - upload = "/upload", - dataUriToImage = "/uploadURI", - images = "/images", - inspectImage = "/inspectImage", - imageHierarchyExport = "/imageHierarchyExport", - - // USER AND WORKSPACES - getCurrUser = "/getCurrentUser", - getUsers = "/getUsers", - getUserDocumentId = "/getUserDocumentId", - updateCursor = "/updateCursor", - - openDocumentWithId = "/doc/:docId", - - // AUTHENTICATION - signup = "/signup", - login = "/login", - logout = "/logout", - forgot = "/forgotpassword", - reset = "/reset/:token", - - // APIS - cognitiveServices = "/cognitiveservices", - googleDocs = "/googleDocs", - readGoogleAccessToken = "/readGoogleAccessToken", - writeGoogleAccessToken = "/writeGoogleAccessToken", - googlePhotosMediaUpload = "/googlePhotosMediaUpload", - googlePhotosMediaDownload = "/googlePhotosMediaDownload", - googleDocsGet = "/googleDocsGet", - checkGoogle = "/checkGoogleAuthentication" - -} \ No newline at end of file diff --git a/src/server/RouteSubscriber.ts b/src/server/RouteSubscriber.ts index e49be8af5..a1cf7c1c4 100644 --- a/src/server/RouteSubscriber.ts +++ b/src/server/RouteSubscriber.ts @@ -3,7 +3,7 @@ export default class RouteSubscriber { private requestParameters: string[] = []; constructor(root: string) { - this._root = root; + this._root = `/${root}`; } add(...parameters: string[]) { diff --git a/src/server/authentication/config/passport.ts b/src/server/authentication/config/passport.ts index 8915a4abf..0b15c3a36 100644 --- a/src/server/authentication/config/passport.ts +++ b/src/server/authentication/config/passport.ts @@ -3,7 +3,6 @@ import * as passportLocal from 'passport-local'; import _ from "lodash"; import { default as User } from '../models/user_model'; import { Request, Response, NextFunction } from "express"; -import { RouteStore } from '../../RouteStore'; const LocalStrategy = passportLocal.Strategy; @@ -35,13 +34,13 @@ export let isAuthenticated = (req: Request, res: Response, next: NextFunction) = if (req.isAuthenticated()) { return next(); } - return res.redirect(RouteStore.login); + return res.redirect("/login"); }; export let isAuthorized = (req: Request, res: Response, next: NextFunction) => { const provider = req.path.split("/").slice(-1)[0]; - if (_.find((req.user as any).tokens, { kind: provider })) { + if (_.find((req.user).tokens, { kind: provider })) { next(); } else { res.redirect(`/auth/${provider}`); diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts index f5c6e1610..b2b9d33f6 100644 --- a/src/server/authentication/controllers/user_controller.ts +++ b/src/server/authentication/controllers/user_controller.ts @@ -10,10 +10,7 @@ import * as pug from 'pug'; import * as async from 'async'; import * as nodemailer from 'nodemailer'; import c = require("crypto"); -import { RouteStore } from "../../RouteStore"; import { Utils } from "../../../Utils"; -import { Schema } from "mongoose"; -import { Opt } from "../../../new_fields/Doc"; import { MailOptions } from "nodemailer/lib/stream-transport"; /** @@ -23,8 +20,7 @@ import { MailOptions } from "nodemailer/lib/stream-transport"; */ export let getSignup = (req: Request, res: Response) => { if (req.user) { - let user = req.user; - return res.redirect(RouteStore.home); + return res.redirect("/home"); } res.render("signup.pug", { title: "Sign Up", @@ -45,7 +41,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { const errors = req.validationErrors(); if (errors) { - return res.redirect(RouteStore.signup); + return res.redirect("/signup"); } const email = req.body.email as String; @@ -62,7 +58,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { User.findOne({ email }, (err, existingUser) => { if (err) { return next(err); } if (existingUser) { - return res.redirect(RouteStore.login); + return res.redirect("/login"); } user.save((err: any) => { if (err) { return next(err); } @@ -81,7 +77,7 @@ let tryRedirectToTarget = (req: Request, res: Response) => { req.session.target = undefined; res.redirect(target); } else { - res.redirect(RouteStore.home); + res.redirect("/home"); } }; @@ -93,7 +89,7 @@ let tryRedirectToTarget = (req: Request, res: Response) => { export let getLogin = (req: Request, res: Response) => { if (req.user) { req.session!.target = undefined; - return res.redirect(RouteStore.home); + return res.redirect("/home"); } res.render("login.pug", { title: "Log In", @@ -115,13 +111,13 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => { if (errors) { req.flash("errors", "Unable to login at this time. Please try again."); - return res.redirect(RouteStore.signup); + return res.redirect("/signup"); } passport.authenticate("local", (err: Error, user: DashUserModel, info: IVerifyOptions) => { if (err) { next(err); return; } if (!user) { - return res.redirect(RouteStore.signup); + return res.redirect("/signup"); } req.logIn(user, (err) => { if (err) { next(err); return; } @@ -141,7 +137,7 @@ export let getLogout = (req: Request, res: Response) => { if (sess) { sess.destroy((err) => { if (err) { console.log(err); } }); } - res.redirect(RouteStore.login); + res.redirect("/login"); }; export let getForgot = function (req: Request, res: Response) { @@ -168,7 +164,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio User.findOne({ email }, function (err, user: DashUserModel) { if (!user) { // NO ACCOUNT WITH SUBMITTED EMAIL - res.redirect(RouteStore.forgot); + res.redirect("/forgotPassword"); return; } user.passwordResetToken = token; @@ -192,7 +188,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio subject: 'Dash Password Reset', text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' + 'Please click on the following link, or paste this into your browser to complete the process:\n\n' + - 'http://' + req.headers.host + '/reset/' + token + '\n\n' + + 'http://' + req.headers.host + '/resetPassword/' + token + '\n\n' + 'If you did not request this, please ignore this email and your password will remain unchanged.\n' } as MailOptions; smtpTransport.sendMail(mailOptions, function (err: Error | null) { @@ -202,14 +198,14 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio } ], function (err) { if (err) return next(err); - res.redirect(RouteStore.forgot); + res.redirect("/forgotPassword"); }); }; export let getReset = function (req: Request, res: Response) { User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err, user: DashUserModel) { if (!user || err) { - return res.redirect(RouteStore.forgot); + return res.redirect("/forgotPassword"); } res.render("reset.pug", { title: "Reset Password", @@ -239,7 +235,7 @@ export let postReset = function (req: Request, res: Response) { user.save(function (err) { if (err) { - res.redirect(RouteStore.login); + res.redirect("/login"); return; } req.logIn(user, function (err) { @@ -271,6 +267,6 @@ export let postReset = function (req: Request, res: Response) { }); } ], function (err) { - res.redirect(RouteStore.login); + res.redirect("/login"); }); }; \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 73cac879e..5a8815983 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -11,7 +11,6 @@ import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { Cast, StrCast, PromiseValue } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; -import { RouteStore } from "../../RouteStore"; import { ScriptField } from "../../../new_fields/ScriptField"; import { ButtonBox } from "../../../client/views/nodes/ButtonBox"; import { UndoManager } from "../../../client/util/UndoManager"; @@ -198,8 +197,8 @@ export class CurrentUserUtils { return doc; } - public static loadCurrentUser() { - return rp.get(Utils.prepend(RouteStore.getCurrUser)).then(response => { + public static async loadCurrentUser() { + return rp.get(Utils.prepend("/getCurrentUser")).then(response => { if (response) { const result: { id: string, email: string } = JSON.parse(response); return result; @@ -212,7 +211,7 @@ export class CurrentUserUtils { public static async loadUserDocument({ id, email }: { id: string, email: string }) { this.curr_id = id; Doc.CurrentUserEmail = email; - await rp.get(Utils.prepend(RouteStore.getUserDocumentId)).then(id => { + await rp.get(Utils.prepend("/getUserDocumentId")).then(id => { if (id && id !== "guest") { return DocServer.GetRefField(id).then(async field => { if (field instanceof Doc) { diff --git a/src/server/index.ts b/src/server/index.ts index aec301a74..8fc402cc9 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -3,7 +3,6 @@ import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils"; import * as mobileDetect from 'mobile-detect'; import * as path from 'path'; import { Database } from './database'; -import { RouteStore } from './RouteStore'; const serverPort = 4321; import { GooglePhotosUploadUtils } from './apis/google/GooglePhotosUploadUtils'; import { Opt } from '../new_fields/Doc'; @@ -23,7 +22,7 @@ import DeleteManager from "./ApiManagers/DeleteManager"; import PDFManager from "./ApiManagers/PDFManager"; import UploadManager from "./ApiManagers/UploadManager"; -export const publicDirectory = __dirname + RouteStore.public; +export const publicDirectory = __dirname + "/public"; export const filesDirectory = publicDirectory + "/files/"; export enum Partitions { pdf_text, @@ -73,13 +72,12 @@ function routeSetter(router: RouteManager) { WebSocket.initialize(serverPort, router.isRelease); /** - * Anyone attempting to navigate to localhost at this port will - * first have to log in. + * Accessing root index redirects to home */ router.addSupervisedRoute({ method: Method.GET, - subscription: RouteStore.root, - onValidation: ({ res }) => res.redirect(RouteStore.home) + subscription: "/", + onValidation: ({ res }) => res.redirect("/home") }); const serve: OnUnauthenticated = ({ req, res }) => { @@ -90,7 +88,7 @@ function routeSetter(router: RouteManager) { router.addSupervisedRoute({ method: Method.GET, - subscription: [RouteStore.home, new RouteSubscriber("/doc").add("docId")], + subscription: ["/home", new RouteSubscriber("doc").add("docId")], onValidation: serve, onUnauthenticated: ({ req, ...remaining }) => { const { originalUrl: target } = req; @@ -110,9 +108,9 @@ function routeSetter(router: RouteManager) { router.addSupervisedRoute({ method: Method.GET, - subscription: new RouteSubscriber(RouteStore.cognitiveServices).add('requestedservice'), + subscription: new RouteSubscriber("cognitiveServices").add('requestedService'), onValidation: ({ req, res }) => { - let service = req.params.requestedservice; + let service = req.params.requestedService; res.send(ServicesApiKeyMap.get(service)); } }); @@ -125,7 +123,7 @@ function routeSetter(router: RouteManager) { router.addSupervisedRoute({ method: Method.POST, - subscription: new RouteSubscriber(RouteStore.googleDocs).add("sector", "action"), + subscription: new RouteSubscriber("googleDocs").add("sector", "action"), onValidation: async ({ req, res, user }) => { let sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service; let action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action; @@ -143,7 +141,7 @@ function routeSetter(router: RouteManager) { router.addSupervisedRoute({ method: Method.GET, - subscription: RouteStore.readGoogleAccessToken, + subscription: "/readGoogleAccessToken", onValidation: async ({ user, res }) => { const userId = user.id; const token = await GoogleApiServerUtils.retrieveAccessToken(userId); @@ -156,7 +154,7 @@ function routeSetter(router: RouteManager) { router.addSupervisedRoute({ method: Method.POST, - subscription: RouteStore.writeGoogleAccessToken, + subscription: "/writeGoogleAccessToken", onValidation: async ({ user, req, res }) => { res.send(await GoogleApiServerUtils.processNewUser(user.id, req.body.authenticationCode)); } @@ -173,7 +171,7 @@ function routeSetter(router: RouteManager) { router.addSupervisedRoute({ method: Method.POST, - subscription: RouteStore.googlePhotosMediaUpload, + subscription: "/googlePhotosMediaUpload", onValidation: async ({ user, req, res }) => { const { media } = req.body; @@ -228,7 +226,7 @@ function routeSetter(router: RouteManager) { const UploadError = (count: number) => `Unable to upload ${count} images to Dash's server`; router.addSupervisedRoute({ method: Method.POST, - subscription: RouteStore.googlePhotosMediaDownload, + subscription: "/googlePhotosMediaDownload", onValidation: async ({ req, res }) => { const contents: { mediaItems: MediaItem[] } = req.body; let failed = 0; -- cgit v1.2.3-70-g09d2 From 780240515a06d9d71a4b58a2559d8661478a560f Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 26 Nov 2019 20:34:33 -0500 Subject: cleanup after looking at changed files --- src/client/DocServer.ts | 2 -- src/client/util/ClientDiagnostics.ts | 4 ++-- src/client/util/Import & Export/ImageUtils.ts | 2 +- src/client/views/MainView.tsx | 1 - src/client/views/search/SearchBox.tsx | 2 +- src/server/ApiManagers/UserManager.ts | 1 - src/server/Initialization.ts | 1 - src/server/RouteManager.ts | 2 ++ 8 files changed, 6 insertions(+), 9 deletions(-) (limited to 'src/client/util/Import & Export/ImageUtils.ts') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 14479694c..2cec1046b 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -64,8 +64,6 @@ export namespace DocServer { } } - let connection_error = false; - export function init(protocol: string, hostname: string, port: number, identifier: string) { _cache = {}; GUID = identifier; diff --git a/src/client/util/ClientDiagnostics.ts b/src/client/util/ClientDiagnostics.ts index 6f82a47db..24f196252 100644 --- a/src/client/util/ClientDiagnostics.ts +++ b/src/client/util/ClientDiagnostics.ts @@ -13,7 +13,7 @@ export namespace ClientDiagnostics { } await fetch("/serverHeartbeat"); serverPolls--; - }, 100); + }, 1000 * 15); let executed = false; @@ -24,7 +24,7 @@ export namespace ClientDiagnostics { executed = true; clearInterval(solrHandle); } - }, 100); + }, 1000 * 15); } diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index ca80f3bca..6a9486f83 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -22,7 +22,7 @@ export namespace ImageUtils { export const ExportHierarchyToFileSystem = async (collection: Doc): Promise => { const a = document.createElement("a"); - a.href = Utils.prepend(`imageHierarchyExport/${collection[Id]}`); + a.href = Utils.prepend(`/imageHierarchyExport/${collection[Id]}`); a.download = `Dash Export [${StrCast(collection.title)}].zip`; a.click(); }; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f59da3cde..5231075a1 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -423,7 +423,6 @@ export class MainView extends React.Component { return !this.userDoc || !(sidebar instanceof Doc) ? (null) : (
-
HEY!
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 1337d3f95..ff35542ed 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -89,7 +89,7 @@ export class SearchBox extends React.Component { public static async convertDataUri(imageUri: string, returnedFilename: string) { try { - let posting = Utils.prepend("uploadURI"); + let posting = Utils.prepend("/uploadURI"); const returnedUri = await rp.post(posting, { body: { uri: imageUri, diff --git a/src/server/ApiManagers/UserManager.ts b/src/server/ApiManagers/UserManager.ts index 8edeab16d..0f7d14320 100644 --- a/src/server/ApiManagers/UserManager.ts +++ b/src/server/ApiManagers/UserManager.ts @@ -9,7 +9,6 @@ interface ActivityUnit { duration: number; } - export default class UserManager extends ApiManager { protected initialize(register: Registration): void { diff --git a/src/server/Initialization.ts b/src/server/Initialization.ts index 76acb4363..8b633a7cd 100644 --- a/src/server/Initialization.ts +++ b/src/server/Initialization.ts @@ -40,7 +40,6 @@ export default async function InitializeServer(options: InitializationOptions) { server.use("*", ({ user, originalUrl }, _res, next) => { if (!originalUrl.includes("Heartbeat")) { const userEmail = user?.email; - console.log(ConsoleColors.Cyan, originalUrl, userEmail ?? ""); if (userEmail) { timeMap[userEmail] = Date.now(); } diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index 3aae5734a..3a20d5af5 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -1,6 +1,7 @@ import RouteSubscriber from "./RouteSubscriber"; import { DashUserModel } from "./authentication/models/user_model"; import * as express from 'express'; +import { ConsoleColors } from "./ActionUtilities"; export enum Method { GET, @@ -52,6 +53,7 @@ export default class RouteManager { try { await toExecute(args); } catch (e) { + console.log(ConsoleColors.Red, target, user?.email ?? ""); if (onError) { onError({ ...core, error: e }); } else { -- cgit v1.2.3-70-g09d2 From 416541c18545cabe0c1b25d698770d7a50a9136e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Fri, 24 Jan 2020 11:56:37 -0500 Subject: finalized image upload changes, fixed exif parsing, excessive image uploading and automatically encode native dimensions --- src/client/util/Import & Export/ImageUtils.ts | 12 ++++- src/client/util/request-image-size.js | 2 +- src/client/views/collections/CollectionSubView.tsx | 13 +++-- src/client/views/nodes/ImageBox.tsx | 42 ++++++++-------- src/server/ApiManagers/UploadManager.ts | 3 +- src/server/DashUploadUtils.ts | 56 ++++++++++------------ 6 files changed, 69 insertions(+), 59 deletions(-) (limited to 'src/client/util/Import & Export/ImageUtils.ts') diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index 6a9486f83..2f4db0e17 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -14,9 +14,17 @@ export namespace ImageUtils { return false; } const source = field.url.href; - const response = await Networking.PostToServer("/inspectImage", { source }); - const { error, data } = response.exifData; + const { + contentSize, + nativeWidth, + nativeHeight, + exifData: { error, data } + } = await Networking.PostToServer("/inspectImage", { source }); document.exif = error || Docs.Get.DocumentHierarchyFromJson(data); + const proto = Doc.GetProto(document); + proto.nativeWidth = nativeWidth; + proto.nativeHeight = nativeHeight; + proto.contentSize = contentSize; return data !== undefined; }; diff --git a/src/client/util/request-image-size.js b/src/client/util/request-image-size.js index 27605d167..beb030635 100644 --- a/src/client/util/request-image-size.js +++ b/src/client/util/request-image-size.js @@ -38,7 +38,7 @@ module.exports = function requestImageSize(options) { return reject(new HttpError(res.statusCode, res.statusMessage)); } - let buffer = new Buffer([]); + let buffer = new Buffer.from([]); let size; let imageSizeError; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 063b5c5df..251828bbd 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -302,12 +302,19 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { formData.append('file', file); const dropFileName = file ? file.name : "-empty-"; promises.push(Networking.PostFormDataToServer("/upload", formData).then(results => { - results.map(action(({ clientAccessPath }: any) => { + results.map(action((result: any) => { + const { clientAccessPath, nativeWidth, nativeHeight, contentSize } = result; const full = { ...options, width: 300, title: dropFileName }; const pathname = Utils.prepend(clientAccessPath); Docs.Get.DocumentFromType(type, pathname, full).then(doc => { - doc && (Doc.GetProto(doc).fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "")); - doc && this.props.addDocument(doc); + if (doc) { + const proto = Doc.GetProto(doc); + proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, ""); + nativeWidth && (proto.nativeWidth = nativeWidth); + nativeHeight && (proto.nativeHeight = nativeHeight); + contentSize && (proto.contentSize = contentSize); + this.props.addDocument(doc); + } }); })); })); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index b7e904283..c47e656fe 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -214,26 +214,26 @@ export class ImageBox extends DocAnnotatableComponent { - requestImageSize(imgPath) - .then((size: any) => { - const rotation = NumCast(this.dataDoc.rotation) % 180; - const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; - const aspect = realsize.height / realsize.width; - if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) { - setTimeout(action(() => { - if (this.paths[NumCast(this.props.Document.curPage)] === imgPath && (!this.layoutDoc.isTemplateDoc || this.dataDoc !== this.layoutDoc)) { - this._resized = imgPath; - this.Document.height = this.Document[WidthSym]() * aspect; - this.Document.nativeHeight = realsize.height; - this.Document.nativeWidth = realsize.width; - } - }), 0); - } else this._resized = imgPath; - }) - .catch((err: any) => console.log(err)); - } + // _resized = ""; + // resize = (imgPath: string) => { + // requestImageSize(imgPath) + // .then((size: any) => { + // const rotation = NumCast(this.dataDoc.rotation) % 180; + // const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; + // const aspect = realsize.height / realsize.width; + // if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) { + // setTimeout(action(() => { + // if (this.paths[NumCast(this.props.Document.curPage)] === imgPath && (!this.layoutDoc.isTemplateDoc || this.dataDoc !== this.layoutDoc)) { + // this._resized = imgPath; + // this.Document.height = this.Document[WidthSym]() * aspect; + // this.Document.nativeHeight = realsize.height; + // this.Document.nativeWidth = realsize.width; + // } + // }), 0); + // } else this._resized = imgPath; + // }) + // .catch((err: any) => console.log(err)); + // } @action onPointerEnter = () => { @@ -306,7 +306,7 @@ export class ImageBox extends DocAnnotatableComponent
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 74f45ae62..583eaa59b 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -169,8 +169,7 @@ export default class UploadManager extends ApiManager { secureHandler: async ({ req, res }) => { const { source } = req.body; if (typeof source === "string") { - const { serverAccessPaths } = await DashUploadUtils.UploadImage(source); - return res.send(await DashUploadUtils.InspectImage(serverAccessPaths[SizeSuffix.Original])); + return res.send(await DashUploadUtils.InspectImage(source)); } res.send({}); } diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 62a702a92..b826b4882 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -1,4 +1,4 @@ -import * as fs from 'fs'; +import { unlinkSync, createWriteStream, readFileSync, rename } from 'fs'; import { Utils } from '../Utils'; import * as path from 'path'; import * as sharp from 'sharp'; @@ -28,6 +28,10 @@ export function InjectSize(filename: string, size: SizeSuffix) { return filename.substring(0, filename.length - extension.length) + size + extension; } +function isLocal() { + return /Dash-Web[\\\/]src[\\\/]server[\\\/]public[\\\/](.*)/; +} + export namespace DashUploadUtils { export interface Size { @@ -93,12 +97,12 @@ export namespace DashUploadUtils { } async function UploadPdf(absolutePath: string) { - const dataBuffer = fs.readFileSync(absolutePath); + const dataBuffer = readFileSync(absolutePath); const result: ParsedPDF = await parse(dataBuffer); const parsedName = basename(absolutePath); await new Promise((resolve, reject) => { const textFilename = `${parsedName.substring(0, parsedName.length - 4)}.txt`; - const writeStream = fs.createWriteStream(serverPathToFile(Directory.text, textFilename)); + const writeStream = createWriteStream(serverPathToFile(Directory.text, textFilename)); writeStream.write(result.text, error => error ? reject(error) : resolve()); }); return MoveParsedFile(absolutePath, Directory.pdfs); @@ -167,16 +171,22 @@ export namespace DashUploadUtils { * @param source is the path or url to the image in question */ export const InspectImage = async (source: string): Promise => { - const url = convert(source); - const exifData = await parseExifData(url); + let resolvedUrl: string; + const matches = isLocal().exec(source); + if (matches === null) { + resolvedUrl = source; + } else { + resolvedUrl = `http://localhost:1050/${matches[1].split("\\").join("/")}`; + } + const exifData = await parseExifData(resolvedUrl); const results = { exifData, - requestable: url + requestable: resolvedUrl }; const { headers } = (await new Promise((resolve, reject) => { - request.head(url, (error, res) => error ? reject(error) : resolve(res)); + request.head(resolvedUrl, (error, res) => error ? reject(error) : resolve(res)); }).catch(error => console.error(error))); - const { width: nativeWidth, height: nativeHeight }: RequestedImageSize = await requestImageSize(url); + const { width: nativeWidth, height: nativeHeight }: RequestedImageSize = await requestImageSize(resolvedUrl); return { source, contentSize: parseInt(headers[size]), @@ -191,22 +201,20 @@ export namespace DashUploadUtils { return new Promise<{ clientAccessPath: Opt }>(resolve => { const filename = basename(absolutePath); const destinationPath = serverPathToFile(destination, filename); - fs.rename(absolutePath, destinationPath, error => { + rename(absolutePath, destinationPath, error => { resolve({ clientAccessPath: error ? undefined : clientPathToFile(destination, filename) }); }); }); } export const UploadInspectedImage = async (metadata: InspectionResults, filename?: string, format?: string, prefix = ""): Promise => { - const { requestable, source, contentSize, contentType, exifData } = metadata; + const { requestable, source, ...remaining } = metadata; const resolved = filename || generate(prefix, requestable); const extension = format || sanitizeExtension(requestable || resolved); const information: ImageUploadInformation = { clientAccessPath: clientPathToFile(Directory.images, resolved), serverAccessPaths: {}, - exifData, - contentSize, - contentType, + ...remaining }; const { pngs, jpgs } = AcceptibleMedia; return new Promise(async (resolve, reject) => { @@ -226,34 +234,22 @@ export namespace DashUploadUtils { await new Promise(resolve => { const filename = InjectSize(resolved, suffix); information.serverAccessPaths[suffix] = serverPathToFile(Directory.images, filename); - request(requestable).pipe(resizer).pipe(fs.createWriteStream(serverPathToFile(Directory.images, filename))) + request(requestable).pipe(resizer).pipe(createWriteStream(serverPathToFile(Directory.images, filename))) .on('close', resolve) .on('error', reject); }); } - if (source.includes("Dash-Web")) { - await new Promise(resolve => { - fs.unlink(source, error => resolve(error === null)); - }); + if (isLocal().test(source)) { + unlinkSync(source); } resolve(information); }); }; - const convert = (url: string) => { - let resolved: string; - const matches = /Dash-Web[\\\/]src[\\\/]server[\\\/]public[\\\/](.*)/.exec(url); - if (matches === null) { - resolved = url; - } else { - resolved = `http://localhost:1050/${matches[1].split("\\").join("/")}`; - } - return resolved; - }; - const parseExifData = async (source: string): Promise => { + const image = await request.get(source, { encoding: null }); return new Promise(resolve => { - new ExifImage(source, (error, data) => { + new ExifImage({ image }, (error, data) => { let reason: Opt = undefined; if (error) { reason = (error as any).code; -- cgit v1.2.3-70-g09d2 From c5d618538d4fd9669476dc7eb66ddd45783e5fa6 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 27 Jan 2020 05:50:15 -0500 Subject: nativewidth and nativeheight extension key fix and implemented UI to manually download a remotely hosted image --- .../util/Import & Export/DirectoryImportBox.tsx | 4 ++-- src/client/util/Import & Export/ImageUtils.ts | 4 ++-- src/client/views/DocComponent.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/nodes/AudioBox.tsx | 2 +- src/client/views/nodes/ImageBox.scss | 24 ++++++++++++++----- src/client/views/nodes/ImageBox.tsx | 28 +++++++++++++++++++++- src/mobile/ImageUpload.tsx | 2 +- src/server/ApiManagers/UploadManager.ts | 14 ++++++++++- src/server/DashUploadUtils.ts | 12 +++------- 10 files changed, 69 insertions(+), 25 deletions(-) (limited to 'src/client/util/Import & Export/ImageUtils.ts') diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index c7c94abed..071015193 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -116,13 +116,13 @@ export default class DirectoryImportBox extends React.Component formData.append(Utils.GenerateGuid(), file); }); - collector.push(...(await Networking.PostFormDataToServer("/upload", formData))); + collector.push(...(await Networking.PostFormDataToServer("/uploadFormData", formData))); runInAction(() => this.completed += batch.length); }); await Promise.all(uploads.map(async ({ name, type, clientAccessPath, exifData }) => { const path = Utils.prepend(clientAccessPath); - const document = await Docs.Get.DocumentFromType(type, path, { width: 300, title: name }); + const document = await Docs.Get.DocumentFromType(type, path, { _width: 300, title: name }); const { data, error } = exifData; if (document) { Doc.GetProto(document).exif = error || Docs.Get.DocumentHierarchyFromJson(data); diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index 2f4db0e17..ff909cc6b 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -22,8 +22,8 @@ export namespace ImageUtils { } = await Networking.PostToServer("/inspectImage", { source }); document.exif = error || Docs.Get.DocumentHierarchyFromJson(data); const proto = Doc.GetProto(document); - proto.nativeWidth = nativeWidth; - proto.nativeHeight = nativeHeight; + proto["data-nativeWidth"] = nativeWidth; + proto["data-nativeHeight"] = nativeHeight; proto.contentSize = contentSize; return data !== undefined; }; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index d98301cf6..6f3eb6808 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -61,7 +61,7 @@ export function DocAnnotatableComponent

(schema _annotationKey: string = "annotations"; public set annotationKey(val: string) { this._annotationKey = val; } - public get annotationKey() { return this._annotationKey } + public get annotationKey() { return this._annotationKey; } @action.bound removeDocument(doc: Doc): boolean { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index b96b86929..80fcc33aa 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -324,7 +324,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { formData.append('file', file); const dropFileName = file ? file.name : "-empty-"; - promises.push(Networking.PostFormDataToServer("/upload", formData).then(results => { + promises.push(Networking.PostFormDataToServer("/uploadFormData", formData).then(results => { results.map(action((result: any) => { const { clientAccessPath, nativeWidth, nativeHeight, contentSize } = result; const full = { ...options, _width: 300, title: dropFileName }; diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 8ede79edc..62a479b2a 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -138,7 +138,7 @@ export class AudioBox extends DocExtendableComponent); } + @computed + private get considerDownloadIcon() { + const data = this.dataDoc[this.props.fieldKey]; + if (!(data instanceof ImageField)) { + return (null); + } + const primary = data.url.href; + if (primary.includes(window.location.origin)) { + return (null); + } + return ( + { + const { dataDoc } = this; + const [{ clientAccessPath }] = await Networking.PostToServer("/uploadRemoteImage", { sources: [primary] }); + dataDoc.originalUrl = primary; + dataDoc[this.props.fieldKey] = new ImageField(Utils.prepend(clientAccessPath)); + }} + /> + ); + } + @computed get nativeSize() { const pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; const nativeWidth = NumCast(this.dataDoc[this.props.fieldKey + "-nativeWidth"], pw); @@ -347,6 +372,7 @@ export class ImageBox extends DocAnnotatableComponent

+ {this.considerDownloadIcon} {this.considerGooglePhotosLink()}
; diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index dab4de110..1583e3d5d 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -45,7 +45,7 @@ class Uploader extends React.Component { const formData = new FormData(); formData.append("file", files[0]); - const upload = window.location.origin + "/upload"; + const upload = window.location.origin + "/uploadFormData"; this.status = "uploading image"; const res = await fetch(upload, { method: 'POST', diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 583eaa59b..a92b613b7 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -40,7 +40,7 @@ export default class UploadManager extends ApiManager { register({ method: Method.POST, - subscription: "/upload", + subscription: "/uploadFormData", secureHandler: async ({ req, res }) => { const form = new formidable.IncomingForm(); form.uploadDir = pathToDirectory(Directory.parsed_files); @@ -59,6 +59,18 @@ export default class UploadManager extends ApiManager { } }); + register({ + method: Method.POST, + subscription: "/uploadRemoteImage", + secureHandler: async ({ req, res }) => { + const { sources } = req.body; + if (Array.isArray(sources)) { + return res.send(await Promise.all(sources.map(url => DashUploadUtils.UploadImage(url)))); + } + res.send(); + } + }); + register({ method: Method.POST, subscription: "/uploadDoc", diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index b826b4882..cb7104757 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -108,13 +108,7 @@ export namespace DashUploadUtils { return MoveParsedFile(absolutePath, Directory.pdfs); } - const generate = (prefix: string, url: string) => `${prefix}upload_${Utils.GenerateGuid()}${sanitizeExtension(url)}`; - const sanitizeExtension = (source: string) => { - let extension = path.extname(source); - extension = extension.toLowerCase(); - extension = extension.split("?")[0]; - return extension; - }; + const generate = (prefix: string, extension: string) => `${prefix}upload_${Utils.GenerateGuid()}.${extension}`; /** * Uploads an image specified by the @param source to Dash's /public/files/ @@ -209,8 +203,8 @@ export namespace DashUploadUtils { export const UploadInspectedImage = async (metadata: InspectionResults, filename?: string, format?: string, prefix = ""): Promise => { const { requestable, source, ...remaining } = metadata; - const resolved = filename || generate(prefix, requestable); - const extension = format || sanitizeExtension(requestable || resolved); + const extension = remaining.contentType.toLowerCase().split("/")[1]; //format || sanitizeExtension(requestable || resolved); + const resolved = filename || generate(prefix, extension); const information: ImageUploadInformation = { clientAccessPath: clientPathToFile(Directory.images, resolved), serverAccessPaths: {}, -- cgit v1.2.3-70-g09d2