aboutsummaryrefslogtreecommitdiff
path: root/src/server/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/index.ts')
-rw-r--r--src/server/index.ts215
1 files changed, 137 insertions, 78 deletions
diff --git a/src/server/index.ts b/src/server/index.ts
index 50ce2b14e..d7273bd88 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -21,10 +21,10 @@ import * as wdm from 'webpack-dev-middleware';
import * as whm from 'webpack-hot-middleware';
import { Utils } from '../Utils';
import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/controllers/user_controller';
-import { DashUserModel } from './authentication/models/user_model';
+import User, { DashUserModel } from './authentication/models/user_model';
import { Client } from './Client';
import { Database } from './database';
-import { MessageStore, Transferable, Types, Diff, YoutubeQueryTypes as YoutubeQueryType, YoutubeQueryInput } from "./Message";
+import { MessageStore, Transferable, Types, Diff, YoutubeQueryTypes as YoutubeQueryType, YoutubeQueryInput, SourceSpecified } from "./Message";
import { RouteStore } from './RouteStore';
import v4 = require('uuid/v4');
const app = express();
@@ -36,19 +36,16 @@ const serverPort = 4321;
import expressFlash = require('express-flash');
import flash = require('connect-flash');
import { Search } from './Search';
-import _ = require('lodash');
import * as Archiver from 'archiver';
var AdmZip = require('adm-zip');
import * as YoutubeApi from "./apis/youtube/youtubeApiSample";
import { Response } from 'express-serve-static-core';
import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils";
-import { GaxiosResponse } from 'gaxios';
-import { Opt } from '../new_fields/Doc';
-import { docs_v1 } from 'googleapis';
-import { Endpoint } from 'googleapis-common';
+import { GooglePhotosUploadUtils, DownloadUtils as UploadUtils } from './apis/google/GooglePhotosUploadUtils';
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');
const probe = require("probe-image-size");
+import * as qs from 'query-string';
const download = (url: string, dest: fs.PathLike) => request.get(url).pipe(fs.createWriteStream(dest));
let youtubeApiKey: string;
@@ -89,6 +86,7 @@ app.use(expressValidator());
app.use(passport.initialize());
app.use(passport.session());
app.use((req, res, next) => {
+ console.log(req.originalUrl);
res.locals.user = req.user;
next();
});
@@ -115,8 +113,10 @@ function addSecureRoute(method: Method,
...subscribers: string[]
) {
let abstracted = (req: express.Request, res: express.Response) => {
- if (req.user) {
- handler(req.user as any, res, req);
+ let sharing = qs.parse(qs.extract(req.originalUrl), { sort: false }).sharing === "true";
+ sharing = sharing && req.originalUrl.startsWith("/doc/");
+ if (req.user || sharing) {
+ handler(req.user, res, req);
} else {
req.session!.target = req.originalUrl;
onRejection(res, req);
@@ -157,6 +157,12 @@ app.get("/buxton", (req, res) => {
command_line('python scraper.py', cwd).then(onResolved, tryPython3);
});
+const STATUS = {
+ OK: 200,
+ BAD_REQUEST: 400,
+ EXECUTION_ERROR: 500
+};
+
const command_line = (command: string, fromDirectory?: string) => {
return new Promise<string>((resolve, reject) => {
let options: ExecOptions = {};
@@ -194,7 +200,7 @@ app.get("/version", (req, res) => {
// SEARCH
const solrURL = "http://localhost:8983/solr/#/dash";
-// GETTERS
+// GETTERSÃ¥
app.get("/search", async (req, res) => {
const solrQuery: any = {};
@@ -420,10 +426,10 @@ app.get("/thumbnail/:filename", (req, res) => {
let filename = req.params.filename;
let noExt = filename.substring(0, filename.length - ".png".length);
let pagenumber = parseInt(noExt.split('-')[1]);
- fs.exists(uploadDir + filename, (exists: boolean) => {
- console.log(`${uploadDir + filename} ${exists ? "exists" : "does not exist"}`);
+ fs.exists(uploadDirectory + filename, (exists: boolean) => {
+ console.log(`${uploadDirectory + filename} ${exists ? "exists" : "does not exist"}`);
if (exists) {
- let input = fs.createReadStream(uploadDir + filename);
+ let input = fs.createReadStream(uploadDirectory + filename);
probe(input, (err: any, result: any) => {
if (err) {
console.log(err);
@@ -434,7 +440,7 @@ app.get("/thumbnail/:filename", (req, res) => {
});
}
else {
- LoadPage(uploadDir + filename.substring(0, filename.length - noExt.split('-')[1].length - ".PNG".length - 1) + ".pdf", pagenumber, res);
+ LoadPage(uploadDirectory + filename.substring(0, filename.length - noExt.split('-')[1].length - ".PNG".length - 1) + ".pdf", pagenumber, res);
}
});
});
@@ -503,21 +509,20 @@ addSecureRoute(
res.sendFile(path.join(__dirname, '../../deploy/' + filename));
},
undefined,
- RouteStore.home,
- RouteStore.openDocumentWithId
+ RouteStore.home, RouteStore.openDocumentWithId
);
addSecureRoute(
Method.GET,
- (user, res) => res.send(user.userDocumentId || ""),
- undefined,
+ (user, res) => res.send(user.userDocumentId),
+ (res) => res.send(undefined),
RouteStore.getUserDocumentId,
);
addSecureRoute(
Method.GET,
- (user, res) => res.send(JSON.stringify({ id: user.id, email: user.email })),
- undefined,
+ (user, res) => { res.send(JSON.stringify({ id: user.id, email: user.email })); },
+ (res) => res.send(JSON.stringify({ id: "__guest__", email: "" })),
RouteStore.getCurrUser
);
@@ -556,50 +561,31 @@ class NodeCanvasFactory {
}
const pngTypes = [".png", ".PNG"];
-const pdfTypes = [".pdf", ".PDF"];
const jpgTypes = [".jpg", ".JPG", ".jpeg", ".JPEG"];
-const uploadDir = __dirname + "/public/files/";
+const uploadDirectory = __dirname + "/public/files/";
+interface FileResponse {
+ name: string;
+ path: string;
+ type: string;
+}
// SETTERS
app.post(
RouteStore.upload,
(req, res) => {
let form = new formidable.IncomingForm();
- form.uploadDir = uploadDir;
+ form.uploadDir = uploadDirectory;
form.keepExtensions = true;
- // let path = req.body.path;
- console.log("upload");
- form.parse(req, (err, fields, files) => {
- console.log("parsing");
- let names: string[] = [];
- for (const name in files) {
- const file = path.basename(files[name].path);
- const ext = path.extname(file);
- let resizers = [
- { resizer: sharp().rotate(), suffix: "_o" },
- { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }).rotate(), suffix: "_s" },
- { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }).rotate(), suffix: "_m" },
- { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }).rotate(), suffix: "_l" },
- ];
- let isImage = false;
- if (pngTypes.includes(ext)) {
- resizers.forEach(element => {
- element.resizer = element.resizer.png();
- });
- isImage = true;
- } else if (jpgTypes.includes(ext)) {
- resizers.forEach(element => {
- element.resizer = element.resizer.jpeg();
- });
- isImage = true;
- }
- if (isImage) {
- resizers.forEach(resizer => {
- fs.createReadStream(uploadDir + file).pipe(resizer.resizer).pipe(fs.createWriteStream(uploadDir + file.substring(0, file.length - ext.length) + resizer.suffix + ext));
- });
- }
- names.push(`/files/` + file);
+ form.parse(req, async (_err, _fields, files) => {
+ let results: FileResponse[] = [];
+ for (const key in files) {
+ const { type, path: location, name } = files[key];
+ const filename = path.basename(location);
+ await UploadUtils.UploadImage(uploadDirectory + filename, filename).catch(() => console.log(`Unable to process ${filename}`));
+ results.push({ name, type, path: `/files/${filename}` });
+ console.log(path.basename(name));
}
- res.send(names);
+ console.log("All files traversed!");
+ _success(res, results);
});
}
);
@@ -613,7 +599,7 @@ addSecureRoute(
res.status(401).send("incorrect parameters specified");
return;
}
- imageDataUri.outputFile(uri, uploadDir + filename).then((savedName: string) => {
+ imageDataUri.outputFile(uri, uploadDirectory + filename).then((savedName: string) => {
const ext = path.extname(savedName);
let resizers = [
{ resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" },
@@ -634,7 +620,7 @@ addSecureRoute(
}
if (isImage) {
resizers.forEach(resizer => {
- fs.createReadStream(savedName).pipe(resizer.resizer).pipe(fs.createWriteStream(uploadDir + filename + resizer.suffix + ext));
+ fs.createReadStream(savedName).pipe(resizer.resizer).pipe(fs.createWriteStream(uploadDirectory + filename + resizer.suffix + ext));
});
}
res.send("/files/" + filename + ext);
@@ -681,21 +667,31 @@ app.use(RouteStore.corsProxy, (req, res) => {
}).pipe(res);
});
-app.get(RouteStore.delete, (req, res) => {
- if (release) {
- res.send("no");
- return;
- }
- deleteFields().then(() => res.redirect(RouteStore.home));
-});
+addSecureRoute(
+ Method.GET,
+ (user, res, req) => {
+ if (release) {
+ res.send("no");
+ return;
+ }
+ deleteFields().then(() => res.redirect(RouteStore.home));
+ },
+ undefined,
+ RouteStore.delete
+);
-app.get(RouteStore.deleteAll, (req, res) => {
- if (release) {
- res.send("no");
- return;
- }
- deleteAll().then(() => res.redirect(RouteStore.home));
-});
+addSecureRoute(
+ Method.GET,
+ (user, res, req) => {
+ if (release) {
+ res.send("no");
+ return;
+ }
+ deleteAll().then(() => res.redirect(RouteStore.home));
+ },
+ undefined,
+ RouteStore.deleteAll
+);
app.use(wdm(compiler, { publicPath: config.output.publicPath }));
@@ -781,8 +777,8 @@ function setField(socket: Socket, newValue: Transferable) {
}
}
-function GetRefField([id, callback]: [string, (result?: Transferable) => void]) {
- Database.Instance.getDocument(id, callback, "newDocuments");
+function GetRefField([args, callback]: [SourceSpecified, (result?: Transferable) => void]) {
+ Database.Instance.getDocument(args.id, callback, args.mongoCollection || "newDocuments");
}
function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => void]) {
@@ -801,19 +797,19 @@ function HandleYoutubeQuery([query, callback]: [YoutubeQueryInput, (result?: any
}
}
-const credentials = path.join(__dirname, "./credentials/google_docs_credentials.json");
-const token = path.join(__dirname, "./credentials/google_docs_token.json");
+const credentialsPath = path.join(__dirname, "./credentials/google_docs_credentials.json");
+const tokenPath = path.join(__dirname, "./credentials/google_docs_token.json");
const EndpointHandlerMap = new Map<GoogleApiServerUtils.Action, GoogleApiServerUtils.ApiRouter>([
["create", (api, params) => api.create(params)],
- ["retrieve", (api, params) => api.get(params)],
+ ["retrieve", (api, params) => api.get(params, { params: "fields=inlineObjects" })],
["update", (api, params) => api.batchUpdate(params)],
]);
app.post(RouteStore.googleDocs + "/:sector/:action", (req, res) => {
let sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service;
let action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action;
- GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], { credentials, token }).then(endpoint => {
+ GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], { credentialsPath, tokenPath }).then(endpoint => {
let handler = EndpointHandlerMap.get(action);
if (endpoint && handler) {
let execute = handler(endpoint, req.body).then(
@@ -827,6 +823,69 @@ app.post(RouteStore.googleDocs + "/:sector/:action", (req, res) => {
});
});
+app.get(RouteStore.googlePhotosAccessToken, (req, res) => GoogleApiServerUtils.RetrieveAccessToken({ credentialsPath, tokenPath }).then(token => res.send(token)));
+
+const tokenError = "Unable to successfully upload bytes for all images!";
+const mediaError = "Unable to convert all uploaded bytes to media items!";
+
+app.post(RouteStore.googlePhotosMediaUpload, async (req, res) => {
+ const media: GooglePhotosUploadUtils.MediaInput[] = req.body.media;
+ await GooglePhotosUploadUtils.initialize({ uploadDirectory, credentialsPath, tokenPath });
+ const newMediaItems = await Promise.all(media.map(async element => {
+ const uploadToken = await GooglePhotosUploadUtils.DispatchGooglePhotosUpload(element.url).catch(error => {
+ console.log("Dispatching upload error!");
+ console.log(error);
+ });
+ return !uploadToken ? undefined : {
+ description: element.description,
+ simpleMediaItem: { uploadToken }
+ };
+ }));
+ if (!newMediaItems.every(item => item)) {
+ return _error(res, tokenError);
+ }
+ GooglePhotosUploadUtils.CreateMediaItems(newMediaItems, req.body.album).then(
+ result => _success(res, result.newMediaItemResults),
+ error => _error(res, mediaError, error)
+ );
+});
+
+interface MediaItem {
+ baseUrl: string;
+ filename: string;
+}
+const prefix = "google_photos_";
+
+const downloadError = "Encountered an error while executing downloads.";
+const requestError = "Unable to execute download: the body's media items were malformed.";
+
+app.post(RouteStore.googlePhotosMediaDownload, async (req, res) => {
+ const contents: { mediaItems: MediaItem[] } = req.body;
+ if (contents) {
+ const pending = contents.mediaItems.map(item =>
+ UploadUtils.UploadImage(item.baseUrl, item.filename, prefix)
+ );
+ const completed = await Promise.all(pending).catch(error => _error(res, downloadError, error));
+ Array.isArray(completed) && _success(res, completed);
+ return;
+ }
+ _invalid(res, requestError);
+});
+
+const _error = (res: Response, message: string, error?: any) => {
+ res.statusMessage = message;
+ res.status(STATUS.EXECUTION_ERROR).send(error);
+};
+
+const _success = (res: Response, body: any) => {
+ res.status(STATUS.OK).send(body);
+};
+
+const _invalid = (res: Response, message: string) => {
+ res.statusMessage = message;
+ res.status(STATUS.BAD_REQUEST).send();
+};
+
const suffixMap: { [type: string]: (string | [string, string | ((json: any) => any)]) } = {
"number": "_n",
"string": "_t",