aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2020-01-02 18:33:14 -0800
committerSam Wilkins <samwilkins333@gmail.com>2020-01-02 18:33:14 -0800
commite85521e0be77eb01ca34a9346a760c5f7c656a4e (patch)
tree5bf3ea39163319eba23380c5546163544ae2fc85 /src
parent31a71334538560917f056c9e80a82bea4b1000e4 (diff)
connected index to session
Diffstat (limited to 'src')
-rw-r--r--src/server/ApiManagers/DeleteManager.ts8
-rw-r--r--src/server/ApiManagers/DownloadManager.ts6
-rw-r--r--src/server/ApiManagers/GeneralGoogleManager.ts6
-rw-r--r--src/server/ApiManagers/GooglePhotosManager.ts4
-rw-r--r--src/server/ApiManagers/PDFManager.ts2
-rw-r--r--src/server/ApiManagers/SearchManager.ts6
-rw-r--r--src/server/ApiManagers/UploadManager.ts8
-rw-r--r--src/server/ApiManagers/UserManager.ts10
-rw-r--r--src/server/ApiManagers/UtilManager.ts8
-rw-r--r--src/server/Initialization.ts2
-rw-r--r--src/server/RouteManager.ts16
-rw-r--r--src/server/index.ts35
-rw-r--r--src/server/session.ts41
13 files changed, 83 insertions, 69 deletions
diff --git a/src/server/ApiManagers/DeleteManager.ts b/src/server/ApiManagers/DeleteManager.ts
index 71818c673..88dfa6a64 100644
--- a/src/server/ApiManagers/DeleteManager.ts
+++ b/src/server/ApiManagers/DeleteManager.ts
@@ -10,7 +10,7 @@ export default class DeleteManager extends ApiManager {
register({
method: Method.GET,
subscription: "/delete",
- onValidation: async ({ res, isRelease }) => {
+ secureHandler: async ({ res, isRelease }) => {
if (isRelease) {
return _permission_denied(res, deletionPermissionError);
}
@@ -22,7 +22,7 @@ export default class DeleteManager extends ApiManager {
register({
method: Method.GET,
subscription: "/deleteAll",
- onValidation: async ({ res, isRelease }) => {
+ secureHandler: async ({ res, isRelease }) => {
if (isRelease) {
return _permission_denied(res, deletionPermissionError);
}
@@ -35,7 +35,7 @@ export default class DeleteManager extends ApiManager {
register({
method: Method.GET,
subscription: "/deleteWithAux",
- onValidation: async ({ res, isRelease }) => {
+ secureHandler: async ({ res, isRelease }) => {
if (isRelease) {
return _permission_denied(res, deletionPermissionError);
}
@@ -47,7 +47,7 @@ export default class DeleteManager extends ApiManager {
register({
method: Method.GET,
subscription: "/deleteWithGoogleCredentials",
- onValidation: async ({ res, isRelease }) => {
+ secureHandler: async ({ res, isRelease }) => {
if (isRelease) {
return _permission_denied(res, deletionPermissionError);
}
diff --git a/src/server/ApiManagers/DownloadManager.ts b/src/server/ApiManagers/DownloadManager.ts
index d9808704b..1bb84f374 100644
--- a/src/server/ApiManagers/DownloadManager.ts
+++ b/src/server/ApiManagers/DownloadManager.ts
@@ -33,7 +33,7 @@ export default class DownloadManager extends ApiManager {
register({
method: Method.GET,
subscription: new RouteSubscriber("imageHierarchyExport").add('docId'),
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const id = req.params.docId;
const hierarchy: Hierarchy = {};
await buildHierarchyRecursive(id, hierarchy);
@@ -44,7 +44,7 @@ export default class DownloadManager extends ApiManager {
register({
method: Method.GET,
subscription: new RouteSubscriber("downloadId").add("docId"),
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
return BuildAndDispatchZip(res, async zip => {
const { id, docs, files } = await getDocs(req.params.docId);
const docString = JSON.stringify({ id, docs });
@@ -59,7 +59,7 @@ export default class DownloadManager extends ApiManager {
register({
method: Method.GET,
subscription: new RouteSubscriber("serializeDoc").add("docId"),
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const { docs, files } = await getDocs(req.params.docId);
res.send({ docs, files: Array.from(files) });
}
diff --git a/src/server/ApiManagers/GeneralGoogleManager.ts b/src/server/ApiManagers/GeneralGoogleManager.ts
index 3617779d5..a5240edbc 100644
--- a/src/server/ApiManagers/GeneralGoogleManager.ts
+++ b/src/server/ApiManagers/GeneralGoogleManager.ts
@@ -19,7 +19,7 @@ export default class GeneralGoogleManager extends ApiManager {
register({
method: Method.GET,
subscription: "/readGoogleAccessToken",
- onValidation: async ({ user, res }) => {
+ secureHandler: async ({ user, res }) => {
const token = await GoogleApiServerUtils.retrieveAccessToken(user.id);
if (!token) {
return res.send(GoogleApiServerUtils.generateAuthenticationUrl());
@@ -31,7 +31,7 @@ export default class GeneralGoogleManager extends ApiManager {
register({
method: Method.POST,
subscription: "/writeGoogleAccessToken",
- onValidation: async ({ user, req, res }) => {
+ secureHandler: async ({ user, req, res }) => {
res.send(await GoogleApiServerUtils.processNewUser(user.id, req.body.authenticationCode));
}
});
@@ -39,7 +39,7 @@ export default class GeneralGoogleManager extends ApiManager {
register({
method: Method.POST,
subscription: new RouteSubscriber("googleDocs").add("sector", "action"),
- onValidation: async ({ req, res, user }) => {
+ secureHandler: async ({ req, res, user }) => {
const sector: GoogleApiServerUtils.Service = req.params.sector as GoogleApiServerUtils.Service;
const action: GoogleApiServerUtils.Action = req.params.action as GoogleApiServerUtils.Action;
const endpoint = await GoogleApiServerUtils.GetEndpoint(GoogleApiServerUtils.Service[sector], user.id);
diff --git a/src/server/ApiManagers/GooglePhotosManager.ts b/src/server/ApiManagers/GooglePhotosManager.ts
index e2539f120..107542ce2 100644
--- a/src/server/ApiManagers/GooglePhotosManager.ts
+++ b/src/server/ApiManagers/GooglePhotosManager.ts
@@ -41,7 +41,7 @@ export default class GooglePhotosManager extends ApiManager {
register({
method: Method.POST,
subscription: "/googlePhotosMediaUpload",
- onValidation: async ({ user, req, res }) => {
+ secureHandler: async ({ user, req, res }) => {
const { media } = req.body;
const token = await GoogleApiServerUtils.retrieveAccessToken(user.id);
if (!token) {
@@ -82,7 +82,7 @@ export default class GooglePhotosManager extends ApiManager {
register({
method: Method.POST,
subscription: "/googlePhotosMediaDownload",
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const contents: { mediaItems: MediaItem[] } = req.body;
let failed = 0;
if (contents) {
diff --git a/src/server/ApiManagers/PDFManager.ts b/src/server/ApiManagers/PDFManager.ts
index 7e862631d..0136b758e 100644
--- a/src/server/ApiManagers/PDFManager.ts
+++ b/src/server/ApiManagers/PDFManager.ts
@@ -17,7 +17,7 @@ export default class PDFManager extends ApiManager {
register({
method: Method.GET,
subscription: new RouteSubscriber("thumbnail").add("filename"),
- onValidation: ({ req, res }) => getOrCreateThumbnail(req.params.filename, res)
+ secureHandler: ({ req, res }) => getOrCreateThumbnail(req.params.filename, res)
});
}
diff --git a/src/server/ApiManagers/SearchManager.ts b/src/server/ApiManagers/SearchManager.ts
index 1ea4d8a50..75ccfe2a8 100644
--- a/src/server/ApiManagers/SearchManager.ts
+++ b/src/server/ApiManagers/SearchManager.ts
@@ -16,7 +16,7 @@ export class SearchManager extends ApiManager {
register({
method: Method.GET,
subscription: new RouteSubscriber("solr").add("action"),
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const { action } = req.params;
if (["start", "stop"].includes(action)) {
const status = req.params.action === "start";
@@ -30,7 +30,7 @@ export class SearchManager extends ApiManager {
register({
method: Method.GET,
subscription: "/textsearch",
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const q = req.query.q;
if (q === undefined) {
res.send([]);
@@ -50,7 +50,7 @@ export class SearchManager extends ApiManager {
register({
method: Method.GET,
subscription: "/search",
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const solrQuery: any = {};
["q", "fq", "start", "rows", "hl", "hl.fl"].forEach(key => solrQuery[key] = req.query[key]);
if (solrQuery.q === undefined) {
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index da1f83b75..74f45ae62 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -41,7 +41,7 @@ export default class UploadManager extends ApiManager {
register({
method: Method.POST,
subscription: "/upload",
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const form = new formidable.IncomingForm();
form.uploadDir = pathToDirectory(Directory.parsed_files);
form.keepExtensions = true;
@@ -62,7 +62,7 @@ export default class UploadManager extends ApiManager {
register({
method: Method.POST,
subscription: "/uploadDoc",
- onValidation: ({ req, res }) => {
+ secureHandler: ({ req, res }) => {
const form = new formidable.IncomingForm();
form.keepExtensions = true;
// let path = req.body.path;
@@ -166,7 +166,7 @@ export default class UploadManager extends ApiManager {
register({
method: Method.POST,
subscription: "/inspectImage",
- onValidation: async ({ req, res }) => {
+ secureHandler: async ({ req, res }) => {
const { source } = req.body;
if (typeof source === "string") {
const { serverAccessPaths } = await DashUploadUtils.UploadImage(source);
@@ -179,7 +179,7 @@ export default class UploadManager extends ApiManager {
register({
method: Method.POST,
subscription: "/uploadURI",
- onValidation: ({ req, res }) => {
+ secureHandler: ({ req, res }) => {
const uri = req.body.uri;
const filename = req.body.name;
if (!uri || !filename) {
diff --git a/src/server/ApiManagers/UserManager.ts b/src/server/ApiManagers/UserManager.ts
index 0f7d14320..f2ef22961 100644
--- a/src/server/ApiManagers/UserManager.ts
+++ b/src/server/ApiManagers/UserManager.ts
@@ -16,7 +16,7 @@ export default class UserManager extends ApiManager {
register({
method: Method.GET,
subscription: "/getUsers",
- onValidation: async ({ res }) => {
+ secureHandler: async ({ res }) => {
const cursor = await Database.Instance.query({}, { email: 1, userDocumentId: 1 }, "users");
const results = await cursor.toArray();
res.send(results.map(user => ({ email: user.email, userDocumentId: user.userDocumentId })));
@@ -26,20 +26,20 @@ export default class UserManager extends ApiManager {
register({
method: Method.GET,
subscription: "/getUserDocumentId",
- onValidation: ({ res, user }) => res.send(user.userDocumentId)
+ secureHandler: ({ res, user }) => res.send(user.userDocumentId)
});
register({
method: Method.GET,
subscription: "/getCurrentUser",
- onValidation: ({ res, user }) => res.send(JSON.stringify(user)),
- onUnauthenticated: ({ res }) => res.send(JSON.stringify({ id: "__guest__", email: "" }))
+ secureHandler: ({ res, user }) => res.send(JSON.stringify(user)),
+ publicHandler: ({ res }) => res.send(JSON.stringify({ id: "__guest__", email: "" }))
});
register({
method: Method.GET,
subscription: "/activity",
- onValidation: ({ res }) => {
+ secureHandler: ({ res }) => {
const now = Date.now();
const activeTimes: ActivityUnit[] = [];
diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts
index 2f1bd956f..a0d0d0f4b 100644
--- a/src/server/ApiManagers/UtilManager.ts
+++ b/src/server/ApiManagers/UtilManager.ts
@@ -12,7 +12,7 @@ export default class UtilManager extends ApiManager {
register({
method: Method.GET,
subscription: new RouteSubscriber("environment").add("key"),
- onValidation: ({ req, res }) => {
+ secureHandler: ({ req, res }) => {
const { key } = req.params;
const value = process.env[key];
if (!value) {
@@ -25,7 +25,7 @@ export default class UtilManager extends ApiManager {
register({
method: Method.GET,
subscription: "/pull",
- onValidation: async ({ res }) => {
+ secureHandler: async ({ res }) => {
return new Promise<void>(resolve => {
exec('"C:\\Program Files\\Git\\git-bash.exe" -c "git pull"', err => {
if (err) {
@@ -42,7 +42,7 @@ export default class UtilManager extends ApiManager {
register({
method: Method.GET,
subscription: "/buxton",
- onValidation: async ({ res }) => {
+ secureHandler: async ({ res }) => {
const cwd = './src/scraping/buxton';
const onResolved = (stdout: string) => { console.log(stdout); res.redirect("/"); };
@@ -56,7 +56,7 @@ export default class UtilManager extends ApiManager {
register({
method: Method.GET,
subscription: "/version",
- onValidation: ({ res }) => {
+ secureHandler: ({ res }) => {
return new Promise<void>(resolve => {
exec('"C:\\Program Files\\Git\\bin\\git.exe" rev-parse HEAD', (err, stdout) => {
if (err) {
diff --git a/src/server/Initialization.ts b/src/server/Initialization.ts
index b58bc3e70..465e7ea63 100644
--- a/src/server/Initialization.ts
+++ b/src/server/Initialization.ts
@@ -18,7 +18,7 @@ import * as whm from 'webpack-hot-middleware';
import * as fs from 'fs';
import * as request from 'request';
import RouteSubscriber from './RouteSubscriber';
-import { publicDirectory, ExitHandlers } from '.';
+import { publicDirectory } from '.';
import { logPort, } from './ActionUtilities';
import { timeMap } from './ApiManagers/UserManager';
import { blue, yellow } from 'colors';
diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts
index 9e84b3687..25259bd88 100644
--- a/src/server/RouteManager.ts
+++ b/src/server/RouteManager.ts
@@ -14,16 +14,16 @@ export interface CoreArguments {
isRelease: boolean;
}
-export type OnValidation = (core: CoreArguments & { user: DashUserModel }) => any | Promise<any>;
-export type OnUnauthenticated = (core: CoreArguments) => any | Promise<any>;
-export type OnError = (core: CoreArguments & { error: any }) => any | Promise<any>;
+export type SecureHandler = (core: CoreArguments & { user: DashUserModel }) => any | Promise<any>;
+export type PublicHandler = (core: CoreArguments) => any | Promise<any>;
+export type ErrorHandler = (core: CoreArguments & { error: any }) => any | Promise<any>;
export interface RouteInitializer {
method: Method;
subscription: string | RouteSubscriber | (string | RouteSubscriber)[];
- onValidation: OnValidation;
- onUnauthenticated?: OnUnauthenticated;
- onError?: OnError;
+ secureHandler: SecureHandler;
+ publicHandler?: PublicHandler;
+ errorHandler?: ErrorHandler;
}
const registered = new Map<string, Set<Method>>();
@@ -69,7 +69,7 @@ export default class RouteManager {
if (malformedCount) {
console.log(`please ensure all routes adhere to ^\/$|^\/[A-Za-z]+(\/\:[A-Za-z]+)*$`);
}
- process.exit(0);
+ process.exit(1);
} else {
console.log(green("all server routes have been successfully registered:"));
Array.from(registered.keys()).sort().forEach(route => console.log(cyan(route)));
@@ -82,7 +82,7 @@ export default class RouteManager {
* @param initializer
*/
addSupervisedRoute = (initializer: RouteInitializer): void => {
- const { method, subscription, onValidation, onUnauthenticated, onError } = initializer;
+ const { method, subscription, secureHandler: onValidation, publicHandler: onUnauthenticated, errorHandler: onError } = initializer;
const isRelease = this._isRelease;
const supervised = async (req: express.Request, res: express.Response) => {
const { user, originalUrl: target } = req;
diff --git a/src/server/index.ts b/src/server/index.ts
index c26e0ec19..597198c04 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -7,7 +7,7 @@ const serverPort = 4321;
import { DashUploadUtils } from './DashUploadUtils';
import RouteSubscriber from './RouteSubscriber';
import initializeServer from './Initialization';
-import RouteManager, { Method, _success, _permission_denied, _error, _invalid, OnUnauthenticated } from './RouteManager';
+import RouteManager, { Method, _success, _permission_denied, _error, _invalid, PublicHandler } from './RouteManager';
import * as qs from 'query-string';
import UtilManager from './ApiManagers/UtilManager';
import { SearchManager, SolrManager } from './ApiManagers/SearchManager';
@@ -29,8 +29,6 @@ import { Session } from "./session";
export const publicDirectory = path.resolve(__dirname, "public");
export const filesDirectory = path.resolve(publicDirectory, "files");
-export const ExitHandlers = new Array<() => void>();
-
/**
* These are the functions run before the server starts
* listening. Anything that must be complete
@@ -80,29 +78,30 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
addSupervisedRoute({
method: Method.GET,
subscription: "/",
- onValidation: ({ res }) => res.redirect("/home")
+ secureHandler: ({ res }) => res.redirect("/home")
});
addSupervisedRoute({
method: Method.GET,
subscription: "/serverHeartbeat",
- onValidation: ({ res }) => res.send(true)
+ secureHandler: ({ res }) => res.send(true)
});
addSupervisedRoute({
method: Method.GET,
- subscription: "/shutdown",
- onValidation: async ({ res }) => {
- WebSocket.disconnect();
- await disconnect();
- await Database.disconnect();
- SolrManager.SetRunning(false);
- res.send("Server successfully shut down.");
- process.exit(0);
+ subscription: "/kill",
+ secureHandler: ({ res }) => {
+ const { send } = process;
+ if (send) {
+ res.send("Server successfully killed.");
+ send({ action: "kill" });
+ } else {
+ res.send("Server worker does not have a viable send protocol. Did not attempt to kill server.");
+ }
}
});
- const serve: OnUnauthenticated = ({ req, res }) => {
+ const serve: PublicHandler = ({ req, res }) => {
const detector = new mobileDetect(req.headers['user-agent'] || "");
const filename = detector.mobile() !== null ? 'mobile/image.html' : 'index.html';
res.sendFile(path.join(__dirname, '../../deploy/' + filename));
@@ -111,8 +110,8 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
addSupervisedRoute({
method: Method.GET,
subscription: ["/home", new RouteSubscriber("doc").add("docId")],
- onValidation: serve,
- onUnauthenticated: ({ req, ...remaining }) => {
+ secureHandler: serve,
+ publicHandler: ({ req, ...remaining }) => {
const { originalUrl: target } = req;
const sharing = qs.parse(qs.extract(req.originalUrl), { sort: false }).sharing === "true";
const docAccess = target.startsWith("/doc/");
@@ -129,7 +128,7 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
WebSocket.initialize(serverPort, isRelease);
}
-async function start() {
+async function launch() {
await log_execution({
startMessage: "\nstarting execution of preliminary functions",
endMessage: "completed preliminary functions\n",
@@ -138,4 +137,4 @@ async function start() {
await initializeServer({ serverPort: 1050, routeSetter });
}
-Session.initialize(start); \ No newline at end of file
+Session.initialize(launch); \ No newline at end of file
diff --git a/src/server/session.ts b/src/server/session.ts
index dd3edccff..1fed9746e 100644
--- a/src/server/session.ts
+++ b/src/server/session.ts
@@ -18,15 +18,24 @@ export namespace Session {
const masterIdentifier = yellow("__master__");
const workerIdentifier = magenta("__worker__");
+ function killAll() {
+ execSync(onWindows ? "taskkill /f /im node.exe" : "killall -9 node");
+ }
+
+ function log(message?: any, ...optionalParams: any[]) {
+ const identifier = `${isMaster ? masterIdentifier : workerIdentifier}:`;
+ console.log(identifier, message, ...optionalParams);
+ }
+
export async function initialize(work: Function) {
let listening = false;
let active: Worker;
if (isMaster) {
process.on("uncaughtException", error => {
if (error.message !== "Channel closed") {
- console.log(`${masterIdentifier}: ${red(error.message)}`);
+ log(red(error.message));
if (error.stack) {
- console.log(`${masterIdentifier}:\n${red(error.stack)}`);
+ log(`\n${red(error.stack)}`);
}
}
});
@@ -36,30 +45,36 @@ export namespace Session {
active.process.kill();
}
active = fork();
- active.on("message", ({ update }) => {
- if (update) {
- console.log(`${workerIdentifier}: ${update}`);
+ active.on("message", ({ lifecycle, action }) => {
+ if (action) {
+ console.log(`${workerIdentifier}: action requested (${action})`);
+ switch (action) {
+ case "kill":
+ log(red("An authorized user has ended the server from the /kill route"));
+ }
+ } else if (lifecycle) {
+ console.log(`${workerIdentifier}: lifecycle phase (${lifecycle})`);
}
});
};
spawn();
on("exit", ({ process: { pid } }, code, signal) => {
const prompt = `Server worker with process id ${pid} has exited with code ${code}${signal === null ? "" : `, having encountered signal ${signal}`}.`;
- console.log(`${masterIdentifier}: ${cyan(prompt)}`);
+ log(cyan(prompt));
spawn();
});
const restart = () => {
listening = false;
const prompt = `Server worker with process id ${active.process.pid} has been manually killed.`;
- console.log(`${masterIdentifier}: ${cyan(prompt)}`);
+ log(cyan(prompt));
spawn();
};
const { registerCommand } = new InputManager({ identifier });
- registerCommand("exit", [], () => execSync(onWindows ? "taskkill /f /im node.exe" : "killall -9 node"));
+ registerCommand("exit", [], killAll);
registerCommand("restart", [], restart);
} else {
- const notifyMaster = (update: string) => process.send?.({ update });
- notifyMaster(green("initializing..."));
+ const logLifecycleEvent = (lifecycle: string) => process.send?.({ lifecycle });
+ logLifecycleEvent(green("initializing..."));
const activeExit = async (error: Error) => {
if (!listening) {
return;
@@ -70,8 +85,8 @@ export namespace Session {
if (_socket) {
Utils.Emit(_socket, MessageStore.ConnectionTerminated, "Manual");
}
- notifyMaster(red(`Crash event detected @ ${new Date().toUTCString()}`));
- notifyMaster(red(error.message));
+ logLifecycleEvent(red(`Crash event detected @ ${new Date().toUTCString()}`));
+ logLifecycleEvent(red(error.message));
process.exit(1);
};
process.on('uncaughtException', activeExit);
@@ -81,7 +96,7 @@ export namespace Session {
try {
await get(heartbeat);
if (!listening) {
- notifyMaster(green("server is now successfully listening..."));
+ logLifecycleEvent(green("server is now successfully listening..."));
}
listening = true;
resolve();