aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/DocServer.ts6
-rw-r--r--src/client/util/SerializationHelper.ts2
-rw-r--r--src/client/views/webcam/WebCamLogic.js6
-rw-r--r--src/debug/Viewer.tsx2
-rw-r--r--src/server/ApiManagers/DeleteManager.ts83
-rw-r--r--src/server/ApiManagers/UtilManager.ts3
-rw-r--r--src/server/RouteManager.ts2
-rw-r--r--src/server/apis/google/CredentialsLoader.ts18
-rw-r--r--src/server/index.ts9
-rw-r--r--src/server/server_Initialization.ts26
-rw-r--r--src/server/websocket.ts36
11 files changed, 123 insertions, 70 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index ac5b7a218..c6b3fa61f 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -1,4 +1,4 @@
-import * as OpenSocket from 'socket.io-client';
+import * as io from 'socket.io-client';
import { MessageStore, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent } from "./../server/Message";
import { Opt, Doc } from '../fields/Doc';
import { Utils, emptyFunction } from '../Utils';
@@ -108,7 +108,9 @@ export namespace DocServer {
export function init(protocol: string, hostname: string, port: number, identifier: string) {
_cache = {};
GUID = identifier;
- _socket = OpenSocket(`${protocol}//${hostname}:${port}`);// OpenSocket(`https://7f079dda.ngrok.io`);// if using ngrok, create a special address for the websocket
+ protocol = protocol.startsWith("https") ? "wss" : "ws";
+ _socket = io.connect(`${protocol}://${hostname}:${port}`);
+ // io.connect(`https://7f079dda.ngrok.io`);// if using ngrok, create a special address for the websocket
_GetCachedRefField = _GetCachedRefFieldImpl;
_GetRefField = _GetRefFieldImpl;
diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts
index ad0309fa7..19b217726 100644
--- a/src/client/util/SerializationHelper.ts
+++ b/src/client/util/SerializationHelper.ts
@@ -91,7 +91,7 @@ export function Deserializable(constructor: { new(...args: any[]): any } | strin
if (typeof constructor === "string") {
return Object.assign((ctor: { new(...args: any[]): any }) => {
addToMap(constructor, ctor);
- }, { withFields: (fields: string[]) => Deserializable.withFields(fields, name, afterDeserialize) });
+ }, { withFields: (fields: string[]) => Deserializable.withFields(fields, constructor, afterDeserialize) });
}
addToMap(constructor.name, constructor);
}
diff --git a/src/client/views/webcam/WebCamLogic.js b/src/client/views/webcam/WebCamLogic.js
index f542fb983..c847b8656 100644
--- a/src/client/views/webcam/WebCamLogic.js
+++ b/src/client/views/webcam/WebCamLogic.js
@@ -104,9 +104,9 @@ export function initialize(roomName, handlerUI) {
navigator.mediaDevices.getUserMedia({
- audio: true,
- video: true
- })
+ audio: true,
+ video: true
+ })
.then(gotStream)
.catch(function (e) {
alert('getUserMedia() error: ' + e.name);
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index 6ce39d533..ddddee3be 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -96,7 +96,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> {
content = (
<div>
Document ({this.props.field[Id]})
- <div style={{ paddingLeft: "25px" }}>
+ <div style={{ paddingLeft: "25px" }}>
{fields}
</div>
</div>
diff --git a/src/server/ApiManagers/DeleteManager.ts b/src/server/ApiManagers/DeleteManager.ts
index 7fbb37658..dcb21c30d 100644
--- a/src/server/ApiManagers/DeleteManager.ts
+++ b/src/server/ApiManagers/DeleteManager.ts
@@ -3,7 +3,7 @@ import { Method, _permission_denied } from "../RouteManager";
import { WebSocket } from "../websocket";
import { Database } from "../database";
import rimraf = require("rimraf");
-import { filesDirectory } from "..";
+import { filesDirectory, AdminPriviliges } from "..";
import { DashUploadUtils } from "../DashUploadUtils";
import { mkdirSync } from "fs";
import RouteSubscriber from "../RouteSubscriber";
@@ -15,38 +15,71 @@ export default class DeleteManager extends ApiManager {
register({
method: Method.GET,
subscription: new RouteSubscriber("delete").add("target?"),
- secureHandler: async ({ req, res, isRelease }) => {
- if (isRelease) {
- return _permission_denied(res, "Cannot perform a delete operation outside of the development environment!");
- }
-
+ secureHandler: async ({ req, res, isRelease, user: { id } }) => {
const { target } = req.params;
- const { doDelete } = WebSocket;
-
- if (!target) {
- await doDelete();
- } else {
- let all = false;
- switch (target) {
- case "all":
- all = true;
- case "database":
- await doDelete(false);
- if (!all) break;
- case "files":
- rimraf.sync(filesDirectory);
- mkdirSync(filesDirectory);
- await DashUploadUtils.buildFileDirectories();
- break;
- default:
- await Database.Instance.dropSchema(target);
+ if (isRelease && process.env.PASSWORD) {
+ if (AdminPriviliges.get(id)) {
+ AdminPriviliges.delete(id);
+ } else {
+ return res.redirect(`/admin/delete${target ? `:${target}` : ``}`);
}
}
+ this.doDelete(target);
res.redirect("/home");
}
});
+ register({
+ method: Method.GET,
+ subscription: new RouteSubscriber("admin").add("previous_target"),
+ secureHandler: ({ res }) => res.render("admin.pug", { title: "Enter Administrator Password" })
+ })
+
+ register({
+ method: Method.POST,
+ subscription: new RouteSubscriber("admin").add("previous_target"),
+ secureHandler: async ({ req, res, isRelease, user: { id } }) => {
+ const { PASSWORD } = process.env;
+ if (!(isRelease && PASSWORD)) {
+ return res.redirect("/home");
+ }
+ const { password } = req.body;
+ const { previous_target } = req.params;
+ let redirect: string;
+ if (password === PASSWORD) {
+ AdminPriviliges.set(id, true);
+ redirect = `/${previous_target.replace(":", "/")}`;
+ } else {
+ redirect = `/admin/${previous_target}`;
+ }
+ res.redirect(redirect);
+ }
+ })
+
+ }
+
+
+ private doDelete = async (target?: string) => {
+ if (!target) {
+ await WebSocket.doDelete();
+ } else {
+ let all = false;
+ switch (target) {
+ case "all":
+ all = true;
+ case "database":
+ await WebSocket.doDelete(false);
+ if (!all) break;
+ case "files":
+ rimraf.sync(filesDirectory);
+ mkdirSync(filesDirectory);
+ await DashUploadUtils.buildFileDirectories();
+ break;
+ default:
+ await Database.Instance.dropSchema(target);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts
index aec523cd0..e2cd88726 100644
--- a/src/server/ApiManagers/UtilManager.ts
+++ b/src/server/ApiManagers/UtilManager.ts
@@ -1,8 +1,6 @@
import ApiManager, { Registration } from "./ApiManager";
import { Method } from "../RouteManager";
import { exec } from 'child_process';
-import RouteSubscriber from "../RouteSubscriber";
-import { red } from "colors";
// import { IBM_Recommender } from "../../client/apis/IBM_Recommender";
// import { Recommender } from "../Recommender";
@@ -34,7 +32,6 @@ export default class UtilManager extends ApiManager {
// }
// });
-
register({
method: Method.GET,
subscription: "/pull",
diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts
index b23215996..9a87ada6f 100644
--- a/src/server/RouteManager.ts
+++ b/src/server/RouteManager.ts
@@ -205,5 +205,5 @@ export function _permission_denied(res: Response, message?: string) {
if (message) {
res.statusMessage = message;
}
- res.status(STATUS.PERMISSION_DENIED).send("Permission Denied!");
+ res.status(STATUS.PERMISSION_DENIED).send(`Permission Denied! ${message}`);
}
diff --git a/src/server/apis/google/CredentialsLoader.ts b/src/server/apis/google/CredentialsLoader.ts
index e3f4d167b..09db4fc60 100644
--- a/src/server/apis/google/CredentialsLoader.ts
+++ b/src/server/apis/google/CredentialsLoader.ts
@@ -1,4 +1,6 @@
-import { readFile } from "fs";
+import { readFile, readFileSync } from "fs";
+import { pathFromRoot } from "../../ActionUtilities";
+import { SecureContextOptions } from "tls";
export namespace GoogleCredentialsLoader {
@@ -27,3 +29,17 @@ export namespace GoogleCredentialsLoader {
}
}
+
+export namespace SSLCredentialsLoader {
+
+ export let Credentials: SecureContextOptions = {};
+
+ export async function loadCredentials() {
+ const { serverName } = process.env;
+ const cert = (suffix: string) => readFileSync(pathFromRoot(`./${serverName}${suffix}`)).toString();
+ Credentials.key = cert(".key");
+ Credentials.cert = cert(".crt");
+ Credentials.ca = cert("-ca.crt");
+ }
+
+}
diff --git a/src/server/index.ts b/src/server/index.ts
index 7ac032ed3..65a9f10a7 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -11,9 +11,8 @@ import * as qs from 'query-string';
import UtilManager from './ApiManagers/UtilManager';
import { SearchManager } from './ApiManagers/SearchManager';
import UserManager from './ApiManagers/UserManager';
-import { WebSocket } from './websocket';
import DownloadManager from './ApiManagers/DownloadManager';
-import { GoogleCredentialsLoader } from './apis/google/CredentialsLoader';
+import { GoogleCredentialsLoader, SSLCredentialsLoader } from './apis/google/CredentialsLoader';
import DeleteManager from "./ApiManagers/DeleteManager";
import PDFManager from "./ApiManagers/PDFManager";
import UploadManager from "./ApiManagers/UploadManager";
@@ -26,6 +25,7 @@ import { DashSessionAgent } from "./DashSession/DashSessionAgent";
import SessionManager from "./ApiManagers/SessionManager";
import { AppliedSessionAgent } from "./DashSession/Session/agents/applied_session_agent";
+export const AdminPriviliges: Map<string, boolean> = new Map();
export const onWindows = process.platform === "win32";
export let sessionAgent: AppliedSessionAgent;
export const publicDirectory = path.resolve(__dirname, "public");
@@ -41,6 +41,7 @@ async function preliminaryFunctions() {
await DashUploadUtils.buildFileDirectories();
await Logger.initialize();
await GoogleCredentialsLoader.loadCredentials();
+ SSLCredentialsLoader.loadCredentials();
GoogleApiServerUtils.processProjectCredentials();
if (process.env.DB !== "MEM") {
await log_execution({
@@ -121,10 +122,6 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
});
logRegistrationOutcome();
-
- // initialize the web socket (bidirectional communication: if a user changes
- // a field on one client, that change must be broadcast to all other clients)
- WebSocket.initialize(isRelease);
}
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index f572ec906..ab91721b2 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -10,6 +10,7 @@ import { Database } from './database';
import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/AuthenticationManager';
const MongoStore = require('connect-mongo')(session);
import RouteManager from './RouteManager';
+import { WebSocket } from './websocket';
import * as webpack from 'webpack';
const config = require('../../webpack.config');
const compiler = webpack(config);
@@ -22,8 +23,9 @@ import { publicDirectory } from '.';
import { logPort, pathFromRoot, } from './ActionUtilities';
import { blue, yellow } from 'colors';
import * as cors from "cors";
-import { createServer, Server as SecureServer } from "https";
-import { Server } from "http";
+import { createServer, Server as HttpsServer } from "https";
+import { Server as HttpServer } from "http";
+import { SSLCredentialsLoader } from './apis/google/CredentialsLoader';
/* RouteSetter is a wrapper around the server that prevents the server
from being exposed. */
@@ -53,23 +55,17 @@ export default async function InitializeServer(routeSetter: RouteSetter) {
const { serverPort } = process.env;
const resolved = isRelease && serverPort ? Number(serverPort) : 1050;
- let server: Server | SecureServer;
+ let server: HttpServer | HttpsServer;
if (isRelease) {
- server = createServer({
- key: fs.readFileSync(pathFromRoot(`./${process.env.serverName}.key`)),
- cert: fs.readFileSync(pathFromRoot(`./${process.env.serverName}.crt`))
- }, app);
- (server as SecureServer).listen(resolved, () => {
- logPort("server", resolved);
- console.log();
- });
+ server = createServer(SSLCredentialsLoader.Credentials, app).listen(resolved, () => logPort("server", resolved));
} else {
- server = app.listen(resolved, () => {
- logPort("server", resolved);
- console.log();
- });
+ server = app.listen(resolved, () => logPort("server", resolved));
}
+ // initialize the web socket (bidirectional communication: if a user changes
+ // a field on one client, that change must be broadcast to all other clients)
+ WebSocket.initialize(isRelease, app);
+
disconnect = async () => new Promise<Error>(resolve => server.close(resolve));
return isRelease;
}
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index 9ab3d2611..1abfe2327 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -1,18 +1,21 @@
+import * as fs from 'fs';
+import { logPort } from './ActionUtilities';
import { Utils } from "../Utils";
import { MessageStore, Transferable, Types, Diff, YoutubeQueryInput, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent, RoomMessage } from "./Message";
import { Client } from "./Client";
import { Socket } from "socket.io";
import { Database } from "./database";
import { Search } from "./Search";
-import * as io from 'socket.io';
+import * as sio from 'socket.io';
import YoutubeApi from "./apis/youtube/youtubeApiSample";
-import { GoogleCredentialsLoader } from "./apis/google/CredentialsLoader";
-import { logPort } from "./ActionUtilities";
+import { GoogleCredentialsLoader, SSLCredentialsLoader } from "./apis/google/CredentialsLoader";
import { timeMap } from "./ApiManagers/UserManager";
import { green } from "colors";
import { networkInterfaces } from "os";
import executeImport from "../scraping/buxton/final/BuxtonImporter";
import { DocumentsCollection } from "./IDatabase";
+import { createServer } from "https";
+import * as express from "express";
export namespace WebSocket {
@@ -20,12 +23,26 @@ export namespace WebSocket {
const clients: { [key: string]: Client } = {};
export const socketMap = new Map<SocketIO.Socket, string>();
export let disconnect: Function;
+ const defaultPort = 4321;
- export function initialize(isRelease: boolean) {
- const endpoint = io();
- endpoint.on("connection", function (socket: Socket) {
- _socket = socket;
+ export function initialize(isRelease: boolean, app: express.Express) {
+ let io: sio.Server;
+ const log = (port: number) => {
+ logPort("websocket", port);
+ console.log();
+ }
+ if (isRelease) {
+ const { socketPort } = process.env;
+ const resolved = socketPort ? Number(socketPort) : defaultPort;
+ const socketEndpoint = createServer(SSLCredentialsLoader.Credentials, app).listen(resolved, () => log(resolved));
+ io = sio(socketEndpoint, SSLCredentialsLoader.Credentials as any);
+ } else {
+ io = sio().listen(defaultPort);
+ log(defaultPort);
+ }
+ io.on("connection", function (socket: Socket) {
+ _socket = socket;
socket.use((_packet, next) => {
const userEmail = socketMap.get(socket);
if (userEmail) {
@@ -121,11 +138,6 @@ export namespace WebSocket {
socket.disconnect(true);
};
});
-
- const { socketPort } = process.env;
- const resolved = isRelease && socketPort ? Number(socketPort) : 4321;
- endpoint.listen(resolved);
- logPort("websocket", resolved);
}
function processGesturePoints(socket: Socket, content: GestureContent) {