aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/ActionUtilities.ts79
-rw-r--r--src/server/ApiManagers/ApiManager.ts4
-rw-r--r--src/server/ApiManagers/DeleteManager.ts14
-rw-r--r--src/server/ApiManagers/DownloadManager.ts6
-rw-r--r--src/server/ApiManagers/MongoStore.js21
-rw-r--r--src/server/ApiManagers/SearchManager.ts9
-rw-r--r--src/server/ApiManagers/SessionManager.ts26
-rw-r--r--src/server/ApiManagers/UtilManager.ts31
-rw-r--r--src/server/DashSession/Session/agents/applied_session_agent.ts23
-rw-r--r--src/server/DashSession/Session/agents/monitor.ts48
-rw-r--r--src/server/DashSession/Session/agents/process_message_router.ts12
-rw-r--r--src/server/DashSession/Session/agents/promisified_ipc_manager.ts51
-rw-r--r--src/server/DashSession/Session/agents/server_worker.ts46
-rw-r--r--src/server/DashSession/Session/utilities/repl.ts76
-rw-r--r--src/server/DashSession/Session/utilities/session_config.ts104
-rw-r--r--src/server/DashSession/Session/utilities/utilities.ts43
-rw-r--r--src/server/DashStats.ts5
-rw-r--r--src/server/DashUploadUtils.ts8
-rw-r--r--src/server/GarbageCollector.ts70
-rw-r--r--src/server/MemoryDatabase.ts37
-rw-r--r--src/server/PdfTypes.ts20
-rw-r--r--src/server/ProcessFactory.ts54
-rw-r--r--src/server/RouteSubscriber.ts5
-rw-r--r--src/server/SharedMediaTypes.ts31
-rw-r--r--src/server/apis/google/CredentialsLoader.ts24
-rw-r--r--src/server/apis/google/GoogleApiServerUtils.ts8
-rw-r--r--src/server/apis/google/SharedTypes.ts13
-rw-r--r--src/server/apis/youtube/youtubeApiSample.d.ts2
-rw-r--r--src/server/authentication/DashUserModel.ts8
-rw-r--r--src/server/authentication/Passport.ts25
-rw-r--r--src/server/database.ts1
-rw-r--r--src/server/index.ts48
-rw-r--r--src/server/updateProtos.ts6
-rw-r--r--src/server/websocket.ts40
34 files changed, 499 insertions, 499 deletions
diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts
index 6f5b9272a..520ebb42e 100644
--- a/src/server/ActionUtilities.ts
+++ b/src/server/ActionUtilities.ts
@@ -16,29 +16,30 @@ export function pathFromRoot(relative?: string) {
return path.resolve(projectRoot, relative);
}
-export async function fileDescriptorFromStream(path: string) {
- const logStream = createWriteStream(path);
- return new Promise<number>(resolve => logStream.on('open', resolve));
+export async function fileDescriptorFromStream(filePath: string) {
+ const logStream = createWriteStream(filePath);
+ return new Promise<number>(resolve => {
+ logStream.on('open', resolve);
+ });
}
-export const command_line = (command: string, fromDirectory?: string) => {
- return new Promise<string>((resolve, reject) => {
+export const commandLine = (command: string, fromDirectory?: string) =>
+ new Promise<string>((resolve, reject) => {
const options: ExecOptions = {};
if (fromDirectory) {
options.cwd = fromDirectory ? path.resolve(projectRoot, fromDirectory) : projectRoot;
}
exec(command, options, (err, stdout) => (err ? reject(err) : resolve(stdout)));
});
-};
-export const read_text_file = (relativePath: string) => {
+export const readTextFile = (relativePath: string) => {
const target = path.resolve(__dirname, relativePath);
return new Promise<string>((resolve, reject) => {
readFile(target, (err, data) => (err ? reject(err) : resolve(data.toString())));
});
};
-export const write_text_file = (relativePath: string, contents: any) => {
+export const writeTextFile = (relativePath: string, contents: any) => {
const target = path.resolve(__dirname, relativePath);
return new Promise<void>((resolve, reject) => {
writeFile(target, contents, err => (err ? reject(err) : resolve()));
@@ -55,39 +56,38 @@ export interface LogData<T> {
color?: Color;
}
+function logHelper(content: string, color: Color | string) {
+ if (typeof color === 'string') {
+ console.log(color, content);
+ } else {
+ console.log(color(content));
+ }
+}
+
let current = Math.ceil(Math.random() * 20);
export async function logExecution<T>({ startMessage, endMessage, action, color }: LogData<T>): Promise<T | undefined> {
- let result: T | undefined = undefined,
- error: Error | null = null;
+ let result: T | undefined;
+ let error: Error | null = null;
const resolvedColor = color || `\x1b[${31 + (++current % 6)}m%s\x1b[0m`;
- log_helper(`${startMessage}...`, resolvedColor);
+ logHelper(`${startMessage}...`, resolvedColor);
try {
result = await action();
} catch (e: any) {
error = e;
} finally {
- log_helper(typeof endMessage === 'string' ? endMessage : endMessage({ result, error }), resolvedColor);
+ logHelper(typeof endMessage === 'string' ? endMessage : endMessage({ result, error }), resolvedColor);
}
return result;
}
-
-function log_helper(content: string, color: Color | string) {
- if (typeof color === 'string') {
- console.log(color, content);
- } else {
- console.log(color(content));
- }
-}
-
export function logPort(listener: string, port: number) {
console.log(`${listener} listening on port ${yellow(String(port))}`);
}
export function msToTime(duration: number) {
- const milliseconds = Math.floor((duration % 1000) / 100),
- seconds = Math.floor((duration / 1000) % 60),
- minutes = Math.floor((duration / (1000 * 60)) % 60),
- hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
+ const milliseconds = Math.floor((duration % 1000) / 100);
+ const seconds = Math.floor((duration / 1000) % 60);
+ const minutes = Math.floor((duration / (1000 * 60)) % 60);
+ const hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
const hoursS = hours < 10 ? '0' + hours : hours;
const minutesS = minutes < 10 ? '0' + minutes : minutes;
@@ -96,21 +96,32 @@ export function msToTime(duration: number) {
return hoursS + ':' + minutesS + ':' + secondsS + '.' + milliseconds;
}
-export const createIfNotExists = async (path: string) => {
- if (await new Promise<boolean>(resolve => exists(path, resolve))) {
+export const createIfNotExists = async (filePath: string) => {
+ if (
+ await new Promise<boolean>(resolve => {
+ exists(filePath, resolve);
+ })
+ ) {
return true;
}
- return new Promise<boolean>(resolve => mkdir(path, error => resolve(error === null)));
+ return new Promise<boolean>(resolve => {
+ mkdir(filePath, error => resolve(error === null));
+ });
};
export async function Prune(rootDirectory: string): Promise<boolean> {
// const error = await new Promise<Error>(resolve => rimraf(rootDirectory).then(resolve));
- await new Promise<void>(resolve => rimraf(rootDirectory).then(() => resolve()));
+ await new Promise<void>(resolve => {
+ rimraf(rootDirectory).then(() => resolve());
+ });
// return error === null;
return true;
}
-export const Destroy = (mediaPath: string) => new Promise<boolean>(resolve => unlink(mediaPath, error => resolve(error === null)));
+export const Destroy = (mediaPath: string) =>
+ new Promise<boolean>(resolve => {
+ unlink(mediaPath, error => resolve(error === null));
+ });
export namespace Email {
const smtpTransport = nodemailer.createTransport({
@@ -137,9 +148,9 @@ export namespace Email {
const failures: DispatchFailure[] = [];
await Promise.all(
to.map(async recipient => {
- let error: Error | null;
const resolved = attachments ? ('length' in attachments ? attachments : [attachments]) : undefined;
- if ((error = await Email.dispatch({ to: recipient, subject, content, attachments: resolved })) !== null) {
+ const error = await Email.dispatch({ to: recipient, subject, content, attachments: resolved });
+ if (error !== null) {
failures.push({
recipient,
error,
@@ -158,6 +169,8 @@ export namespace Email {
text: `Hello ${to.split('@')[0]},\n\n${content}`,
attachments,
} as MailOptions;
- return new Promise<Error | null>(resolve => smtpTransport.sendMail(mailOptions, resolve));
+ return new Promise<Error | null>(resolve => {
+ smtpTransport.sendMail(mailOptions, resolve);
+ });
}
}
diff --git a/src/server/ApiManagers/ApiManager.ts b/src/server/ApiManagers/ApiManager.ts
index 27e9de065..f55495b2e 100644
--- a/src/server/ApiManagers/ApiManager.ts
+++ b/src/server/ApiManagers/ApiManager.ts
@@ -1,4 +1,4 @@
-import { RouteInitializer } from "../RouteManager";
+import { RouteInitializer } from '../RouteManager';
export type Registration = (initializer: RouteInitializer) => void;
@@ -8,4 +8,4 @@ export default abstract class ApiManager {
public register(register: Registration) {
this.initialize(register);
}
-} \ No newline at end of file
+}
diff --git a/src/server/ApiManagers/DeleteManager.ts b/src/server/ApiManagers/DeleteManager.ts
index 9a9b807ae..9ad334c1b 100644
--- a/src/server/ApiManagers/DeleteManager.ts
+++ b/src/server/ApiManagers/DeleteManager.ts
@@ -1,12 +1,12 @@
-import ApiManager, { Registration } from './ApiManager';
-import { Method, _permissionDenied } from '../RouteManager';
-import { WebSocket } from '../websocket';
-import { Database } from '../database';
+import { mkdirSync } from 'fs';
import { rimraf } from 'rimraf';
-import { filesDirectory } from '..';
+import { filesDirectory } from '../SocketData';
import { DashUploadUtils } from '../DashUploadUtils';
-import { mkdirSync } from 'fs';
+import { Method } from '../RouteManager';
import RouteSubscriber from '../RouteSubscriber';
+import { Database } from '../database';
+import { WebSocket } from '../websocket';
+import ApiManager, { Registration } from './ApiManager';
export default class DeleteManager extends ApiManager {
protected initialize(register: Registration): void {
@@ -24,9 +24,11 @@ export default class DeleteManager extends ApiManager {
switch (target) {
case 'all':
all = true;
+ // eslint-disable-next-line no-fallthrough
case 'database':
await WebSocket.doDelete(false);
if (!all) break;
+ // eslint-disable-next-line no-fallthrough
case 'files':
rimraf.sync(filesDirectory);
mkdirSync(filesDirectory);
diff --git a/src/server/ApiManagers/DownloadManager.ts b/src/server/ApiManagers/DownloadManager.ts
index b105c825c..5ee21fb44 100644
--- a/src/server/ApiManagers/DownloadManager.ts
+++ b/src/server/ApiManagers/DownloadManager.ts
@@ -153,7 +153,7 @@ async function writeHierarchyRecursive(file: Archiver.Archiver, hierarchy: Hiera
}
}
-async function getDocs(id: string) {
+async function getDocs(docId: string) {
const files = new Set<string>();
const docs: { [id: string]: any } = {};
const fn = (doc: any): string[] => {
@@ -209,8 +209,8 @@ async function getDocs(id: string) {
}
return ids;
};
- await Database.Instance.visit([id], fn);
- return { id, docs, files };
+ await Database.Instance.visit([docId], fn);
+ return { id: docId, docs, files };
}
export default class DownloadManager extends ApiManager {
diff --git a/src/server/ApiManagers/MongoStore.js b/src/server/ApiManagers/MongoStore.js
index 28515fee4..5d91c2805 100644
--- a/src/server/ApiManagers/MongoStore.js
+++ b/src/server/ApiManagers/MongoStore.js
@@ -1,10 +1,9 @@
-'use strict';
-var __createBinding =
+const __createBinding =
(this && this.__createBinding) ||
(Object.create
? function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
+ let desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = {
enumerable: true,
@@ -19,25 +18,25 @@ var __createBinding =
if (k2 === undefined) k2 = k;
o[k2] = m[k];
});
-var __setModuleDefault =
+const __setModuleDefault =
(this && this.__setModuleDefault) ||
(Object.create
? function (o, v) {
Object.defineProperty(o, 'default', { enumerable: true, value: v });
}
: function (o, v) {
- o['default'] = v;
+ o.default = v;
});
-var __importStar =
+const __importStar =
(this && this.__importStar) ||
function (mod) {
if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+ const result = {};
+ if (mod != null) for (const k in mod) if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
-var __importDefault =
+const __importDefault =
(this && this.__importDefault) ||
function (mod) {
return mod && mod.__esModule ? mod : { default: mod };
@@ -246,7 +245,7 @@ class MongoStore extends session.Store {
*/
set(sid, session, callback = noop) {
(async () => {
- var _a;
+ let _a;
try {
debug(`MongoStore#set=${sid}`);
// Removing the lastModified prop from the session object before update
@@ -306,7 +305,7 @@ class MongoStore extends session.Store {
}
touch(sid, session, callback = noop) {
(async () => {
- var _a;
+ let _a;
try {
debug(`MongoStore#touch=${sid}`);
const updateFields = {};
diff --git a/src/server/ApiManagers/SearchManager.ts b/src/server/ApiManagers/SearchManager.ts
index 1b1db5809..f43ed6ac9 100644
--- a/src/server/ApiManagers/SearchManager.ts
+++ b/src/server/ApiManagers/SearchManager.ts
@@ -1,3 +1,4 @@
+/* eslint-disable no-use-before-define */
import { exec } from 'child_process';
import { cyan, green, red, yellow } from 'colors';
import { logExecution } from '../ActionUtilities';
@@ -17,8 +18,10 @@ export class SearchManager extends ApiManager {
switch (action) {
case 'start':
case 'stop':
- const status = req.params.action === 'start';
- SolrManager.SetRunning(status);
+ {
+ const status = req.params.action === 'start';
+ SolrManager.SetRunning(status);
+ }
break;
case 'update':
await SolrManager.update();
@@ -95,7 +98,7 @@ export namespace SolrManager {
if (doc.__type !== 'Doc') {
return;
}
- const fields = doc.fields;
+ const { fields } = doc;
if (!fields) {
return;
}
diff --git a/src/server/ApiManagers/SessionManager.ts b/src/server/ApiManagers/SessionManager.ts
index c3139896f..bebe50a62 100644
--- a/src/server/ApiManagers/SessionManager.ts
+++ b/src/server/ApiManagers/SessionManager.ts
@@ -9,20 +9,18 @@ const permissionError = 'You are not authorized!';
export default class SessionManager extends ApiManager {
private secureSubscriber = (root: string, ...params: string[]) => new RouteSubscriber(root).add('session_key', ...params);
- private authorizedAction = (handler: SecureHandler) => {
- return (core: AuthorizedCore) => {
- const {
- req: { params },
- res,
- } = core;
- if (!process.env.MONITORED) {
- return res.send('This command only makes sense in the context of a monitored session.');
- }
- if (params.session_key !== process.env.session_key) {
- return _permissionDenied(res, permissionError);
- }
- return handler(core);
- };
+ private authorizedAction = (handler: SecureHandler) => (core: AuthorizedCore) => {
+ const {
+ req: { params },
+ res,
+ } = core;
+ if (!process.env.MONITORED) {
+ return res.send('This command only makes sense in the context of a monitored session.');
+ }
+ if (params.session_key !== process.env.session_key) {
+ return _permissionDenied(res, permissionError);
+ }
+ return handler(core);
};
protected initialize(register: Registration): void {
diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts
index e657866ce..8ad421a30 100644
--- a/src/server/ApiManagers/UtilManager.ts
+++ b/src/server/ApiManagers/UtilManager.ts
@@ -1,6 +1,7 @@
-import ApiManager, { Registration } from "./ApiManager";
-import { Method } from "../RouteManager";
import { exec } from 'child_process';
+import ApiManager, { Registration } from './ApiManager';
+import { Method } from '../RouteManager';
+
// import { IBM_Recommender } from "../../client/apis/IBM_Recommender";
// import { Recommender } from "../Recommender";
@@ -8,9 +9,7 @@ import { exec } from 'child_process';
// recommender.testModel();
export default class UtilManager extends ApiManager {
-
protected initialize(register: Registration): void {
-
// register({
// method: Method.POST,
// subscription: "/IBMAnalysis",
@@ -33,26 +32,25 @@ export default class UtilManager extends ApiManager {
register({
method: Method.GET,
- subscription: "/pull",
- secureHandler: async ({ res }) => {
- return new Promise<void>(resolve => {
+ subscription: '/pull',
+ secureHandler: async ({ res }) =>
+ new Promise<void>(resolve => {
exec('"C:\\Program Files\\Git\\git-bash.exe" -c "git pull"', err => {
if (err) {
res.send(err.message);
return;
}
- res.redirect("/");
+ res.redirect('/');
resolve();
});
- });
- }
+ }),
});
register({
method: Method.GET,
- subscription: "/version",
- secureHandler: ({ res }) => {
- return new Promise<void>(resolve => {
+ subscription: '/version',
+ secureHandler: ({ res }) =>
+ new Promise<void>(resolve => {
exec('"C:\\Program Files\\Git\\bin\\git.exe" rev-parse HEAD', (err, stdout) => {
if (err) {
res.send(err.message);
@@ -61,10 +59,7 @@ export default class UtilManager extends ApiManager {
res.send(stdout);
});
resolve();
- });
- }
+ }),
});
-
}
-
-} \ No newline at end of file
+}
diff --git a/src/server/DashSession/Session/agents/applied_session_agent.ts b/src/server/DashSession/Session/agents/applied_session_agent.ts
index 2037e93e5..c42ba95cc 100644
--- a/src/server/DashSession/Session/agents/applied_session_agent.ts
+++ b/src/server/DashSession/Session/agents/applied_session_agent.ts
@@ -1,13 +1,13 @@
-import * as _cluster from "cluster";
-import { Monitor } from "./monitor";
-import { ServerWorker } from "./server_worker";
+import * as _cluster from 'cluster';
+import { Monitor } from './monitor';
+import { ServerWorker } from './server_worker';
+
const cluster = _cluster as any;
const isMaster = cluster.isPrimary;
export type ExitHandler = (reason: Error | boolean) => void | Promise<void>;
export abstract class AppliedSessionAgent {
-
// the following two methods allow the developer to create a custom
// session and use the built in customization options for each thread
protected abstract initializeMonitor(monitor: Monitor): Promise<string>;
@@ -18,15 +18,15 @@ export abstract class AppliedSessionAgent {
public killSession = (reason: string, graceful = true, errorCode = 0) => {
const target = cluster.default.isPrimary ? this.sessionMonitor : this.serverWorker;
target.killSession(reason, graceful, errorCode);
- }
+ };
private sessionMonitorRef: Monitor | undefined;
public get sessionMonitor(): Monitor {
if (!cluster.default.isPrimary) {
- this.serverWorker.emit("kill", {
+ this.serverWorker.emit('kill', {
graceful: false,
- reason: "Cannot access the session monitor directly from the server worker thread.",
- errorCode: 1
+ reason: 'Cannot access the session monitor directly from the server worker thread.',
+ errorCode: 1,
});
throw new Error();
}
@@ -36,7 +36,7 @@ export abstract class AppliedSessionAgent {
private serverWorkerRef: ServerWorker | undefined;
public get serverWorker(): ServerWorker {
if (isMaster) {
- throw new Error("Cannot access the server worker directly from the session monitor thread");
+ throw new Error('Cannot access the server worker directly from the session monitor thread');
}
return this.serverWorkerRef!;
}
@@ -52,8 +52,7 @@ export abstract class AppliedSessionAgent {
this.serverWorkerRef = await this.initializeServerWorker();
}
} else {
- throw new Error("Cannot launch a session thread more than once per process.");
+ throw new Error('Cannot launch a session thread more than once per process.');
}
}
-
-} \ No newline at end of file
+}
diff --git a/src/server/DashSession/Session/agents/monitor.ts b/src/server/DashSession/Session/agents/monitor.ts
index a6fde4356..6cdad46c2 100644
--- a/src/server/DashSession/Session/agents/monitor.ts
+++ b/src/server/DashSession/Session/agents/monitor.ts
@@ -1,21 +1,19 @@
-import { ExitHandler } from './applied_session_agent';
-import { Configuration, configurationSchema, defaultConfig, Identifiers, colorMapping } from '../utilities/session_config';
-import Repl, { ReplAction } from '../utilities/repl';
+import { ExecOptions, exec } from 'child_process';
import * as _cluster from 'cluster';
import { Worker } from 'cluster';
-import { manage, MessageHandler, ErrorLike } from './promisified_ipc_manager';
-import { red, cyan, white, yellow, blue } from 'colors';
-import { exec, ExecOptions } from 'child_process';
-import { validate, ValidationError } from 'jsonschema';
-import { Utilities } from '../utilities/utilities';
+import { blue, cyan, red, white, yellow } from 'colors';
import { readFileSync } from 'fs';
+import { ValidationError, validate } from 'jsonschema';
+import Repl, { ReplAction } from '../utilities/repl';
+import { Configuration, Identifiers, colorMapping, configurationSchema, defaultConfig } from '../utilities/session_config';
+import { Utilities } from '../utilities/utilities';
+import { ExitHandler } from './applied_session_agent';
import IPCMessageReceiver from './process_message_router';
+import { ErrorLike, MessageHandler, manage } from './promisified_ipc_manager';
import { ServerWorker } from './server_worker';
+
const cluster = _cluster as any;
-const isWorker = cluster.isWorker;
-const setupMaster = cluster.setupPrimary;
-const on = cluster.on;
-const fork = cluster.fork;
+const { isWorker, setupMaster, on, fork } = cluster;
/**
* Validates and reads the configuration file, accordingly builds a child process factory
@@ -41,9 +39,8 @@ export class Monitor extends IPCMessageReceiver {
} else if (++Monitor.count > 1) {
console.error(red('cannot create more than one monitor.'));
process.exit(1);
- } else {
- return new Monitor();
}
+ return new Monitor();
}
private constructor() {
@@ -128,25 +125,25 @@ export class Monitor extends IPCMessageReceiver {
this.repl.registerCommand(basename, argPatterns, action);
};
- public exec = (command: string, options?: ExecOptions) => {
- return new Promise<void>(resolve => {
+ public exec = (command: string, options?: ExecOptions) =>
+ new Promise<void>(resolve => {
exec(command, { ...options, encoding: 'utf8' }, (error, stdout, stderr) => {
if (error) {
this.execLog(red(`unable to execute ${white(command)}`));
error.message.split('\n').forEach(line => line.length && this.execLog(red(`(error) ${line}`)));
} else {
- let outLines: string[], errorLines: string[];
- if ((outLines = stdout.split('\n').filter(line => line.length)).length) {
+ const outLines = stdout.split('\n').filter(line => line.length);
+ if (outLines.length) {
outLines.forEach(line => line.length && this.execLog(cyan(`(stdout) ${line}`)));
}
- if ((errorLines = stderr.split('\n').filter(line => line.length)).length) {
+ const errorLines = stderr.split('\n').filter(line => line.length);
+ if (errorLines.length) {
errorLines.forEach(line => line.length && this.execLog(yellow(`(stderr) ${line}`)));
}
}
resolve();
});
});
- };
/**
* Generates a blue UTC string associated with the time
@@ -226,12 +223,10 @@ export class Monitor extends IPCMessageReceiver {
const newPollingIntervalSeconds = Math.floor(Number(args[1]));
if (newPollingIntervalSeconds < 0) {
this.mainLog(red('the polling interval must be a non-negative integer'));
- } else {
- if (newPollingIntervalSeconds !== this.config.polling.intervalSeconds) {
- this.config.polling.intervalSeconds = newPollingIntervalSeconds;
- if (args[2] === 'true') {
- Monitor.IPCManager.emit('updatePollingInterval', { newPollingIntervalSeconds });
- }
+ } else if (newPollingIntervalSeconds !== this.config.polling.intervalSeconds) {
+ this.config.polling.intervalSeconds = newPollingIntervalSeconds;
+ if (args[2] === 'true') {
+ Monitor.IPCManager.emit('updatePollingInterval', { newPollingIntervalSeconds });
}
}
});
@@ -297,6 +292,7 @@ export class Monitor extends IPCMessageReceiver {
};
}
+// eslint-disable-next-line no-redeclare
export namespace Monitor {
export enum IntrinsicEvents {
KeyGenerated = 'key_generated',
diff --git a/src/server/DashSession/Session/agents/process_message_router.ts b/src/server/DashSession/Session/agents/process_message_router.ts
index 0745ea455..3e2b7d8d0 100644
--- a/src/server/DashSession/Session/agents/process_message_router.ts
+++ b/src/server/DashSession/Session/agents/process_message_router.ts
@@ -1,7 +1,6 @@
-import { MessageHandler, PromisifiedIPCManager, HandlerMap } from "./promisified_ipc_manager";
+import { MessageHandler, PromisifiedIPCManager, HandlerMap } from './promisified_ipc_manager';
export default abstract class IPCMessageReceiver {
-
protected static IPCManager: PromisifiedIPCManager;
protected handlers: HandlerMap = {};
@@ -18,7 +17,7 @@ export default abstract class IPCMessageReceiver {
} else {
handlers.push(handler);
}
- }
+ };
/**
* Unregister a given listener at this message.
@@ -31,11 +30,10 @@ export default abstract class IPCMessageReceiver {
handlers.splice(index, 1);
}
}
- }
+ };
- /**
+ /**
* Unregister all listeners at this message.
*/
public clearMessageListeners = (...names: string[]) => names.map(name => delete this.handlers[name]);
-
-} \ No newline at end of file
+}
diff --git a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
index 76e218977..99b4d4de3 100644
--- a/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
+++ b/src/server/DashSession/Session/agents/promisified_ipc_manager.ts
@@ -1,13 +1,14 @@
-import { Utilities } from '../utilities/utilities';
import { ChildProcess } from 'child_process';
+import { Utilities } from '../utilities/utilities';
/**
- * Convenience constructor
- * @param target the process / worker to which to attach the specialized listeners
+ * Specifies a general message format for this API
*/
-export function manage(target: IPCTarget, handlers?: HandlerMap) {
- return new PromisifiedIPCManager(target, handlers);
-}
+export type Message<T = any> = {
+ name: string;
+ args?: T;
+};
+export type MessageHandler<T = any> = (args: T) => any | Promise<any>;
/**
* Captures the logic to execute upon receiving a message
@@ -22,15 +23,10 @@ export type HandlerMap = { [name: string]: MessageHandler[] };
*/
export type IPCTarget = NodeJS.Process | ChildProcess;
-/**
- * Specifies a general message format for this API
- */
-export type Message<T = any> = {
- name: string;
- args?: T;
-};
-export type MessageHandler<T = any> = (args: T) => any | Promise<any>;
-
+interface Metadata {
+ isResponse: boolean;
+ id: string;
+}
/**
* When a message is emitted, it is embedded with private metadata
* to facilitate the resolution of promises, etc.
@@ -38,10 +34,6 @@ export type MessageHandler<T = any> = (args: T) => any | Promise<any>;
interface InternalMessage extends Message {
metadata: Metadata;
}
-interface Metadata {
- isResponse: boolean;
- id: string;
-}
/**
* Allows for the transmission of the error's key features over IPC.
@@ -95,7 +87,7 @@ export class PromisifiedIPCManager {
}
return new Promise<Response<T>>(resolve => {
const messageId = Utilities.guid();
- type InternalMessageHandler = (message: any /* MessageListener*/) => any | Promise<any>;
+ type InternalMessageHandler = (message: any /* MessageListener */) => any | Promise<any>;
const responseHandler: InternalMessageHandler = ({ metadata: { id, isResponse }, args }) => {
if (isResponse && id === messageId) {
this.target.removeListener('message', responseHandler);
@@ -118,8 +110,8 @@ export class PromisifiedIPCManager {
* completion response for each of the pending messages, allowing their
* promises in the caller to resolve.
*/
- public destroy = () => {
- return new Promise<void>(async resolve => {
+ public destroy = () =>
+ new Promise<void>(async resolve => {
if (this.callerIsTarget) {
this.destroyHelper();
} else {
@@ -127,7 +119,6 @@ export class PromisifiedIPCManager {
}
resolve();
});
- };
/**
* Dispatches the dummy responses and sets the isDestroyed flag to true.
@@ -168,12 +159,20 @@ export class PromisifiedIPCManager {
error = e;
}
if (!this.isDestroyed && this.target.send) {
- const metadata = { id, isResponse: true };
+ const metadataRes = { id, isResponse: true };
const response: Response = { results, error };
- const message = { name, args: response, metadata };
+ const messageRes = { name, args: response, metadata: metadataRes };
delete this.pendingMessages[id];
- this.target.send(message);
+ this.target.send(messageRes);
}
}
};
}
+
+/**
+ * Convenience constructor
+ * @param target the process / worker to which to attach the specialized listeners
+ */
+export function manage(target: IPCTarget, handlers?: HandlerMap) {
+ return new PromisifiedIPCManager(target, handlers);
+}
diff --git a/src/server/DashSession/Session/agents/server_worker.ts b/src/server/DashSession/Session/agents/server_worker.ts
index d8b3ee80b..85e1b31d6 100644
--- a/src/server/DashSession/Session/agents/server_worker.ts
+++ b/src/server/DashSession/Session/agents/server_worker.ts
@@ -1,10 +1,10 @@
-import cluster from "cluster";
-import { green, red, white, yellow } from "colors";
-import { get } from "request-promise";
-import { ExitHandler } from "./applied_session_agent";
-import { Monitor } from "./monitor";
-import IPCMessageReceiver from "./process_message_router";
-import { ErrorLike, manage } from "./promisified_ipc_manager";
+import cluster from 'cluster';
+import { green, red, white, yellow } from 'colors';
+import { get } from 'request-promise';
+import { ExitHandler } from './applied_session_agent';
+import { Monitor } from './monitor';
+import IPCMessageReceiver from './process_message_router';
+import { ErrorLike, manage } from './promisified_ipc_manager';
/**
* Effectively, each worker repairs the connection to the server by reintroducing a consistent state
@@ -23,18 +23,17 @@ export class ServerWorker extends IPCMessageReceiver {
private isInitialized = false;
public static Create(work: Function) {
if (cluster.isPrimary) {
- console.error(red("cannot create a worker on the monitor process."));
+ console.error(red('cannot create a worker on the monitor process.'));
process.exit(1);
} else if (++ServerWorker.count > 1) {
- ServerWorker.IPCManager.emit("kill", {
- reason: "cannot create more than one worker on a given worker process.",
+ ServerWorker.IPCManager.emit('kill', {
+ reason: 'cannot create more than one worker on a given worker process.',
graceful: false,
- errorCode: 1
+ errorCode: 1,
});
process.exit(1);
- } else {
- return new ServerWorker(work);
}
+ return new ServerWorker(work);
}
/**
@@ -48,7 +47,7 @@ export class ServerWorker extends IPCMessageReceiver {
* server worker (child process). This will also kill
* this process (child process).
*/
- public killSession = (reason: string, graceful = true, errorCode = 0) => this.emit<never>("kill", { reason, graceful, errorCode });
+ public killSession = (reason: string, graceful = true, errorCode = 0) => this.emit<never>('kill', { reason, graceful, errorCode });
/**
* A convenience wrapper to tell the session monitor (parent process)
@@ -60,7 +59,7 @@ export class ServerWorker extends IPCMessageReceiver {
super();
this.configureInternalHandlers();
ServerWorker.IPCManager = manage(process, this.handlers);
- this.lifecycleNotification(green(`initializing process... ${white(`[${process.execPath} ${process.execArgv.join(" ")}]`)}`));
+ this.lifecycleNotification(green(`initializing process... ${white(`[${process.execPath} ${process.execArgv.join(' ')}]`)}`));
const { pollingRoute, serverPort, pollingIntervalSeconds, pollingFailureTolerance } = process.env;
this.serverPort = Number(serverPort);
@@ -78,8 +77,10 @@ export class ServerWorker extends IPCMessageReceiver {
*/
protected configureInternalHandlers = () => {
// updates the local values of variables to the those sent from master
- this.on("updatePollingInterval", ({ newPollingIntervalSeconds }) => this.pollingIntervalSeconds = newPollingIntervalSeconds);
- this.on("manualExit", async ({ isSessionEnd }) => {
+ this.on('updatePollingInterval', ({ newPollingIntervalSeconds }) => {
+ this.pollingIntervalSeconds = newPollingIntervalSeconds;
+ });
+ this.on('manualExit', async ({ isSessionEnd }) => {
await ServerWorker.IPCManager.destroy();
await this.executeExitHandlers(isSessionEnd);
process.exit(0);
@@ -91,7 +92,7 @@ export class ServerWorker extends IPCMessageReceiver {
const appropriateError = reason instanceof Error ? reason : new Error(`unhandled rejection: ${reason}`);
this.proactiveUnplannedExit(appropriateError);
});
- }
+ };
/**
* Execute the list of functions registered to be called
@@ -102,7 +103,7 @@ export class ServerWorker extends IPCMessageReceiver {
/**
* Notify master thread (which will log update in the console) of initialization via IPC.
*/
- public lifecycleNotification = (event: string) => this.emit("lifecycle", { event });
+ public lifecycleNotification = (event: string) => this.emit('lifecycle', { event });
/**
* Called whenever the process has a reason to terminate, either through an uncaught exception
@@ -120,11 +121,11 @@ export class ServerWorker extends IPCMessageReceiver {
this.lifecycleNotification(red(error.message));
await ServerWorker.IPCManager.destroy();
process.exit(1);
- }
+ };
/**
* This monitors the health of the server by submitting a get request to whatever port / route specified
- * by the configuration every n seconds, where n is also given by the configuration.
+ * by the configuration every n seconds, where n is also given by the configuration.
*/
private pollServer = async (): Promise<void> => {
await new Promise<void>(resolve => {
@@ -156,6 +157,5 @@ export class ServerWorker extends IPCMessageReceiver {
});
// controlled, asynchronous infinite recursion achieves a persistent poll that does not submit a new request until the previous has completed
this.pollServer();
- }
-
+ };
}
diff --git a/src/server/DashSession/Session/utilities/repl.ts b/src/server/DashSession/Session/utilities/repl.ts
index 643141286..5d9f15e4c 100644
--- a/src/server/DashSession/Session/utilities/repl.ts
+++ b/src/server/DashSession/Session/utilities/repl.ts
@@ -1,5 +1,5 @@
-import { createInterface, Interface } from "readline";
-import { red, green, white } from "colors";
+import { createInterface, Interface } from 'readline';
+import { red, green, white } from 'colors';
export interface Configuration {
identifier: () => string | string;
@@ -32,76 +32,82 @@ export default class Repl {
this.interface = createInterface(process.stdin, process.stdout).on('line', this.considerInput);
}
- private resolvedIdentifier = () => typeof this.identifier === "string" ? this.identifier : this.identifier();
+ private resolvedIdentifier = () => (typeof this.identifier === 'string' ? this.identifier : this.identifier());
private usage = (command: string, validCommand: boolean) => {
if (validCommand) {
const formatted = white(command);
- const patterns = green(this.commandMap.get(command)!.map(({ argPatterns }) => `${formatted} ${argPatterns.join(" ")}`).join('\n'));
+ const patterns = green(
+ this.commandMap
+ .get(command)!
+ .map(({ argPatterns }) => `${formatted} ${argPatterns.join(' ')}`)
+ .join('\n')
+ );
return `${this.resolvedIdentifier()}\nthe given arguments do not match any registered patterns for ${formatted}\nthe list of valid argument patterns is given by:\n${patterns}`;
- } else {
- const resolved = this.keys;
- if (resolved) {
- return resolved;
- }
- const members: string[] = [];
- const keys = this.commandMap.keys();
- let next: IteratorResult<string>;
- while (!(next = keys.next()).done) {
- members.push(next.value);
- }
- return `${this.resolvedIdentifier()} commands: { ${members.sort().join(", ")} }`;
}
- }
+ const resolved = this.keys;
+ if (resolved) {
+ return resolved;
+ }
+ const members: string[] = [];
+ const keys = this.commandMap.keys();
+ let next: IteratorResult<string>;
+ // eslint-disable-next-line no-cond-assign
+ while (!(next = keys.next()).done) {
+ members.push(next.value);
+ }
+ return `${this.resolvedIdentifier()} commands: { ${members.sort().join(', ')} }`;
+ };
private success = (command: string) => `${this.resolvedIdentifier()} completed local execution of ${white(command)}`;
public registerCommand = (basename: string, argPatterns: (RegExp | string)[], action: ReplAction) => {
const existing = this.commandMap.get(basename);
- const converted = argPatterns.map(input => input instanceof RegExp ? input : new RegExp(input));
+ const converted = argPatterns.map(input => (input instanceof RegExp ? input : new RegExp(input)));
const registration = { argPatterns: converted, action };
if (existing) {
existing.push(registration);
} else {
this.commandMap.set(basename, [registration]);
}
- }
+ };
private invalid = (command: string, validCommand: boolean) => {
- console.log(red(typeof this.onInvalid === "string" ? this.onInvalid : this.onInvalid(command, validCommand)));
+ console.log(red(typeof this.onInvalid === 'string' ? this.onInvalid : this.onInvalid(command, validCommand)));
this.busy = false;
- }
+ };
private valid = (command: string) => {
- console.log(green(typeof this.onValid === "string" ? this.onValid : this.onValid(command)));
+ console.log(green(typeof this.onValid === 'string' ? this.onValid : this.onValid(command)));
this.busy = false;
- }
+ };
- private considerInput = async (line: string) => {
+ private considerInput = async (lineIn: string) => {
if (this.busy) {
- console.log(red("Busy"));
+ console.log(red('Busy'));
return;
}
this.busy = true;
- line = line.trim();
+ let line = lineIn.trim();
if (this.isCaseSensitive) {
line = line.toLowerCase();
}
const [command, ...args] = line.split(/\s+/g);
if (!command) {
- return this.invalid(command, false);
+ this.invalid(command, false);
+ return;
}
const registered = this.commandMap.get(command);
if (registered) {
const { length } = args;
const candidates = registered.filter(({ argPatterns: { length: count } }) => count === length);
- for (const { argPatterns, action } of candidates) {
+ candidates.forEach(({ argPatterns, action }: { argPatterns: any; action: any }) => {
const parsed: string[] = [];
let matched = true;
if (length) {
for (let i = 0; i < length; i++) {
- let matches: RegExpExecArray | null;
- if ((matches = argPatterns[i].exec(args[i])) === null) {
+ const matches = argPatterns[i].exec(args[i]);
+ if (matches === null) {
matched = false;
break;
}
@@ -110,19 +116,17 @@ export default class Repl {
}
if (!length || matched) {
const result = action(parsed);
- const resolve = () => this.valid(`${command} ${parsed.join(" ")}`);
+ const resolve = () => this.valid(`${command} ${parsed.join(' ')}`);
if (result instanceof Promise) {
result.then(resolve);
} else {
resolve();
}
- return;
}
- }
+ });
this.invalid(command, true);
} else {
this.invalid(command, false);
}
- }
-
-} \ No newline at end of file
+ };
+}
diff --git a/src/server/DashSession/Session/utilities/session_config.ts b/src/server/DashSession/Session/utilities/session_config.ts
index 266759929..b42c1a3c7 100644
--- a/src/server/DashSession/Session/utilities/session_config.ts
+++ b/src/server/DashSession/Session/utilities/session_config.ts
@@ -1,85 +1,85 @@
-import { Schema } from "jsonschema";
-import { yellow, red, cyan, green, blue, magenta, Color, grey, gray, white, black } from "colors";
+import { Schema } from 'jsonschema';
+import { yellow, red, cyan, green, blue, magenta, Color, grey, gray, white, black } from 'colors';
const colorPattern = /black|red|green|yellow|blue|magenta|cyan|white|gray|grey/;
const identifierProperties: Schema = {
- type: "object",
+ type: 'object',
properties: {
text: {
- type: "string",
- minLength: 1
+ type: 'string',
+ minLength: 1,
},
color: {
- type: "string",
- pattern: colorPattern
- }
- }
+ type: 'string',
+ pattern: colorPattern,
+ },
+ },
};
const portProperties: Schema = {
- type: "number",
+ type: 'number',
minimum: 443,
- maximum: 65535
+ maximum: 65535,
};
export const configurationSchema: Schema = {
- id: "/configuration",
- type: "object",
+ id: '/configuration',
+ type: 'object',
properties: {
- showServerOutput: { type: "boolean" },
+ showServerOutput: { type: 'boolean' },
ports: {
- type: "object",
+ type: 'object',
properties: {
server: portProperties,
- socket: portProperties
+ socket: portProperties,
},
- required: ["server"],
- additionalProperties: true
+ required: ['server'],
+ additionalProperties: true,
},
identifiers: {
- type: "object",
+ type: 'object',
properties: {
master: identifierProperties,
worker: identifierProperties,
- exec: identifierProperties
- }
+ exec: identifierProperties,
+ },
},
polling: {
- type: "object",
+ type: 'object',
additionalProperties: false,
properties: {
intervalSeconds: {
- type: "number",
+ type: 'number',
minimum: 1,
- maximum: 86400
+ maximum: 86400,
},
route: {
- type: "string",
- pattern: /\/[a-zA-Z]*/g
+ type: 'string',
+ pattern: /\/[a-zA-Z]*/g,
},
failureTolerance: {
- type: "number",
+ type: 'number',
minimum: 0,
- }
- }
+ },
+ },
},
- }
+ },
};
-type ColorLabel = "yellow" | "red" | "cyan" | "green" | "blue" | "magenta" | "grey" | "gray" | "white" | "black";
+type ColorLabel = 'yellow' | 'red' | 'cyan' | 'green' | 'blue' | 'magenta' | 'grey' | 'gray' | 'white' | 'black';
export const colorMapping: Map<ColorLabel, Color> = new Map([
- ["yellow", yellow],
- ["red", red],
- ["cyan", cyan],
- ["green", green],
- ["blue", blue],
- ["magenta", magenta],
- ["grey", grey],
- ["gray", gray],
- ["white", white],
- ["black", black]
+ ['yellow', yellow],
+ ['red', red],
+ ['cyan', cyan],
+ ['green', green],
+ ['blue', blue],
+ ['magenta', magenta],
+ ['grey', grey],
+ ['gray', gray],
+ ['white', white],
+ ['black', black],
]);
interface Identifier {
@@ -108,22 +108,22 @@ export const defaultConfig: Configuration = {
showServerOutput: false,
identifiers: {
master: {
- text: "__monitor__",
- color: "yellow"
+ text: '__monitor__',
+ color: 'yellow',
},
worker: {
- text: "__server__",
- color: "magenta"
+ text: '__server__',
+ color: 'magenta',
},
exec: {
- text: "__exec__",
- color: "green"
- }
+ text: '__exec__',
+ color: 'green',
+ },
},
ports: { server: 1050 },
polling: {
- route: "/",
+ route: '/',
intervalSeconds: 30,
- failureTolerance: 0
- }
-}; \ No newline at end of file
+ failureTolerance: 0,
+ },
+};
diff --git a/src/server/DashSession/Session/utilities/utilities.ts b/src/server/DashSession/Session/utilities/utilities.ts
index eb8de9d7e..a2ba29c67 100644
--- a/src/server/DashSession/Session/utilities/utilities.ts
+++ b/src/server/DashSession/Session/utilities/utilities.ts
@@ -1,31 +1,16 @@
-import { v4 } from "uuid";
+import { v4 } from 'uuid';
export namespace Utilities {
-
export function guid() {
return v4();
}
- /**
- * At any arbitrary layer of nesting within the configuration objects, any single value that
- * is not specified by the configuration is given the default counterpart. If, within an object,
- * one peer is given by configuration and two are not, the one is preserved while the two are given
- * the default value.
- * @returns the composition of all of the assigned objects, much like Object.assign(), but with more
- * granularity in the overwriting of nested objects
- */
- export function preciseAssign(target: any, ...sources: any[]): any {
- for (const source of sources) {
- preciseAssignHelper(target, source);
- }
- return target;
- }
-
export function preciseAssignHelper(target: any, source: any) {
- Array.from(new Set([...Object.keys(target), ...Object.keys(source)])).map(property => {
- let targetValue: any, sourceValue: any;
- if (sourceValue = source[property]) {
- if (typeof sourceValue === "object" && typeof (targetValue = target[property]) === "object") {
+ Array.from(new Set([...Object.keys(target), ...Object.keys(source)])).forEach(property => {
+ const targetValue = target[property];
+ const sourceValue = source[property];
+ if (sourceValue) {
+ if (typeof sourceValue === 'object' && typeof targetValue === 'object') {
preciseAssignHelper(targetValue, sourceValue);
} else {
target[property] = sourceValue;
@@ -34,4 +19,18 @@ export namespace Utilities {
});
}
-} \ No newline at end of file
+ /**
+ * At any arbitrary layer of nesting within the configuration objects, any single value that
+ * is not specified by the configuration is given the default counterpart. If, within an object,
+ * one peer is given by configuration and two are not, the one is preserved while the two are given
+ * the default value.
+ * @returns the composition of all of the assigned objects, much like Object.assign(), but with more
+ * granularity in the overwriting of nested objects
+ */
+ export function preciseAssign(target: any, ...sources: any[]): any {
+ sources.forEach(source => {
+ preciseAssignHelper(target, source);
+ });
+ return target;
+ }
+}
diff --git a/src/server/DashStats.ts b/src/server/DashStats.ts
index 485ab9f99..808d2c6f2 100644
--- a/src/server/DashStats.ts
+++ b/src/server/DashStats.ts
@@ -1,7 +1,6 @@
import { cyan, magenta } from 'colors';
import { Response } from 'express';
import * as fs from 'fs';
-import SocketIO from 'socket.io';
import { socketMap, timeMap, userOperations } from './SocketData';
/**
@@ -242,7 +241,7 @@ export namespace DashStats {
* @param username the username in the format of "username@domain.com logged in"
* @param socket the websocket associated with the current connection
*/
- export function logUserLogin(username: string | undefined, socket: SocketIO.Socket) {
+ export function logUserLogin(username: string | undefined) {
if (!(username === undefined)) {
const currentDate = new Date();
console.log(magenta(`User ${username.split(' ')[0]} logged in at: ${currentDate.toISOString()}`));
@@ -267,7 +266,7 @@ export namespace DashStats {
* @param username the username in the format of "username@domain.com logged in"
* @param socket the websocket associated with the current connection.
*/
- export function logUserLogout(username: string | undefined, socket: SocketIO.Socket) {
+ export function logUserLogout(username: string | undefined) {
if (!(username === undefined)) {
const currentDate = new Date();
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index 3d8325da9..08cea1de5 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -186,8 +186,8 @@ export namespace DashUploadUtils {
const image = await request.get(source, { encoding: null });
const { /* data, */ error } = await new Promise<{ data: any; error: any }>(resolve => {
// eslint-disable-next-line no-new
- new ExifImage({ image }, (error, data) => {
- const reason = (error as any)?.code;
+ new ExifImage({ image }, (exifError, data) => {
+ const reason = (exifError as any)?.code;
resolve({ data, error: reason });
});
});
@@ -506,8 +506,8 @@ export namespace DashUploadUtils {
if (fExists(fileKey, Directory.pdfs) && fExists(textFilename, Directory.text)) {
fs.unlink(file.filepath, () => {});
return new Promise<Upload.FileResponse>(res => {
- const textFilename = `${fileKey.substring(0, fileKey.length - 4)}.txt`;
- const readStream = createReadStream(serverPathToFile(Directory.text, textFilename));
+ const pdfTextFilename = `${fileKey.substring(0, fileKey.length - 4)}.txt`;
+ const readStream = createReadStream(serverPathToFile(Directory.text, pdfTextFilename));
let rawText = '';
readStream
.on('data', chunk => {
diff --git a/src/server/GarbageCollector.ts b/src/server/GarbageCollector.ts
index 423c719c2..041f65592 100644
--- a/src/server/GarbageCollector.ts
+++ b/src/server/GarbageCollector.ts
@@ -1,11 +1,15 @@
+/* eslint-disable no-await-in-loop */
+/* eslint-disable no-continue */
+/* eslint-disable no-cond-assign */
+/* eslint-disable no-restricted-syntax */
import * as fs from 'fs';
import * as path from 'path';
import { Database } from './database';
import { Search } from './Search';
-
function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) {
for (const key in doc) {
+ // eslint-disable-next-line no-prototype-builtins
if (!doc.hasOwnProperty(key)) {
continue;
}
@@ -13,22 +17,22 @@ function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) {
if (field === undefined || field === null) {
continue;
}
- if (field.__type === "proxy" || field.__type === "prefetch_proxy") {
+ if (field.__type === 'proxy' || field.__type === 'prefetch_proxy') {
ids.push(field.fieldId);
- } else if (field.__type === "list") {
+ } else if (field.__type === 'list') {
addDoc(field.fields, ids, files);
- } else if (typeof field === "string") {
- const re = /"(?:dataD|d)ocumentId"\s*:\s*"([\w\-]*)"/g;
+ } else if (typeof field === 'string') {
+ const re = /"(?:dataD|d)ocumentId"\s*:\s*"([\w-]*)"/g;
let match: string[] | null;
while ((match = re.exec(field)) !== null) {
ids.push(match[1]);
}
- } else if (field.__type === "RichTextField") {
+ } else if (field.__type === 'RichTextField') {
const re = /"href"\s*:\s*"(.*?)"/g;
let match: string[] | null;
while ((match = re.exec(field.Data)) !== null) {
const urlString = match[1];
- const split = new URL(urlString).pathname.split("doc/");
+ const split = new URL(urlString).pathname.split('doc/');
if (split.length > 1) {
ids.push(split[split.length - 1]);
}
@@ -36,7 +40,7 @@ function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) {
const re2 = /"src"\s*:\s*"(.*?)"/g;
while ((match = re2.exec(field.Data)) !== null) {
const urlString = match[1];
- const pathname = new URL(urlString).pathname;
+ const { pathname } = new URL(urlString);
const ext = path.extname(pathname);
const fileName = path.basename(pathname, ext);
let exts = files[fileName];
@@ -45,9 +49,9 @@ function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) {
}
exts.push(ext);
}
- } else if (["audio", "image", "video", "pdf", "web", "map"].includes(field.__type)) {
+ } else if (['audio', 'image', 'video', 'pdf', 'web', 'map'].includes(field.__type)) {
const url = new URL(field.url);
- const pathname = url.pathname;
+ const { pathname } = url;
const ext = path.extname(pathname);
const fileName = path.basename(pathname, ext);
let exts = files[fileName];
@@ -60,12 +64,12 @@ function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) {
}
async function GarbageCollect(full: boolean = true) {
- console.log("start GC");
+ console.log('start GC');
const start = Date.now();
// await new Promise(res => setTimeout(res, 3000));
const cursor = await Database.Instance.query({}, { userDocumentId: 1 }, 'users');
const users = await cursor.toArray();
- const ids: string[] = [...users.map((user:any) => user.userDocumentId), ...users.map((user:any) => user.sharingDocumentId), ...users.map((user:any) => user.linkDatabaseId)];
+ const ids: string[] = [...users.map((user: any) => user.userDocumentId), ...users.map((user: any) => user.sharingDocumentId), ...users.map((user: any) => user.linkDatabaseId)];
const visited = new Set<string>();
const files: { [name: string]: string[] } = {};
@@ -76,9 +80,11 @@ async function GarbageCollect(full: boolean = true) {
if (!fetchIds.length) {
continue;
}
- const docs = await new Promise<{ [key: string]: any }[]>(res => Database.Instance.getDocuments(fetchIds, res));
+ const docs = await new Promise<{ [key: string]: any }[]>(res => {
+ Database.Instance.getDocuments(fetchIds, res);
+ });
for (const doc of docs) {
- const id = doc.id;
+ const { id } = doc;
if (doc === undefined) {
console.log(`Couldn't find field with Id ${id}`);
continue;
@@ -95,19 +101,27 @@ async function GarbageCollect(full: boolean = true) {
const notToDelete = Array.from(visited);
const toDeleteCursor = await Database.Instance.query({ _id: { $nin: notToDelete } }, { _id: 1 });
- const toDelete: string[] = (await toDeleteCursor.toArray()).map((doc:any) => doc._id);
+ const toDelete: string[] = (await toDeleteCursor.toArray()).map((doc: any) => doc._id);
toDeleteCursor.close();
if (!full) {
- await Database.Instance.updateMany({ _id: { $nin: notToDelete } }, { $set: { "deleted": true } });
- await Database.Instance.updateMany({ _id: { $in: notToDelete } }, { $unset: { "deleted": true } });
- console.log(await Search.updateDocuments(
- notToDelete.map<any>(id => ({
- id, deleted: { set: null }
- }))
- .concat(toDelete.map(id => ({
- id, deleted: { set: true }
- })))));
- console.log("Done with partial GC");
+ await Database.Instance.updateMany({ _id: { $nin: notToDelete } }, { $set: { deleted: true } });
+ await Database.Instance.updateMany({ _id: { $in: notToDelete } }, { $unset: { deleted: true } });
+ console.log(
+ await Search.updateDocuments(
+ notToDelete
+ .map<any>(id => ({
+ id,
+ deleted: { set: null },
+ }))
+ .concat(
+ toDelete.map(id => ({
+ id,
+ deleted: { set: true },
+ }))
+ )
+ )
+ );
+ console.log('Done with partial GC');
console.log(`Took ${(Date.now() - start) / 1000} seconds`);
} else {
let i = 0;
@@ -123,15 +137,15 @@ async function GarbageCollect(full: boolean = true) {
console.log(`${deleted} documents deleted`);
await Search.deleteDocuments(toDelete);
- console.log("Cleared search documents");
+ console.log('Cleared search documents');
- const folder = "./src/server/public/files/";
+ const folder = './src/server/public/files/';
fs.readdir(folder, (_, fileList) => {
const filesToDelete = fileList.filter(file => {
const ext = path.extname(file);
let base = path.basename(file, ext);
const existsInDb = (base in files || (base = base.substring(0, base.length - 2)) in files) && files[base].includes(ext);
- return file !== ".gitignore" && !existsInDb;
+ return file !== '.gitignore' && !existsInDb;
});
console.log(`Deleting ${filesToDelete.length} files`);
filesToDelete.forEach(file => {
diff --git a/src/server/MemoryDatabase.ts b/src/server/MemoryDatabase.ts
index b74332bf5..1432d91c4 100644
--- a/src/server/MemoryDatabase.ts
+++ b/src/server/MemoryDatabase.ts
@@ -3,16 +3,15 @@ import { DocumentsCollection, IDatabase } from './IDatabase';
import { Transferable } from './Message';
export class MemoryDatabase implements IDatabase {
-
private db: { [collectionName: string]: { [id: string]: any } } = {};
private getCollection(collectionName: string) {
const collection = this.db[collectionName];
if (collection) {
return collection;
- } else {
- return this.db[collectionName] = {};
}
+ this.db[collectionName] = {};
+ return {};
}
public getCollectionNames() {
@@ -21,15 +20,15 @@ export class MemoryDatabase implements IDatabase {
public update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateResult) => void, _upsert?: boolean, collectionName = DocumentsCollection): Promise<void> {
const collection = this.getCollection(collectionName);
- const set = "$set";
+ const set = '$set';
if (set in value) {
let currentVal = collection[id] ?? (collection[id] = {});
const val = value[set];
for (const key in val) {
- const keys = key.split(".");
+ const keys = key.split('.');
for (let i = 0; i < keys.length - 1; i++) {
const k = keys[i];
- if (typeof currentVal[k] === "object") {
+ if (typeof currentVal[k] === 'object') {
currentVal = currentVal[k];
} else {
currentVal[k] = {};
@@ -45,7 +44,7 @@ export class MemoryDatabase implements IDatabase {
return Promise.resolve(undefined);
}
- public updateMany(query: any, update: any, collectionName = DocumentsCollection): Promise<mongodb.UpdateResult> {
+ public updateMany(/* query: any, update: any, collectionName = DocumentsCollection */): Promise<mongodb.UpdateResult> {
throw new Error("Can't updateMany a MemoryDatabase");
}
@@ -54,7 +53,9 @@ export class MemoryDatabase implements IDatabase {
}
public delete(query: any, collectionName?: string): Promise<mongodb.DeleteResult>;
+ // eslint-disable-next-line no-dupe-class-members
public delete(id: string, collectionName?: string): Promise<mongodb.DeleteResult>;
+ // eslint-disable-next-line no-dupe-class-members
public delete(id: any, collectionName = DocumentsCollection): Promise<mongodb.DeleteResult> {
const i = id.id ?? id;
delete this.getCollection(collectionName)[i];
@@ -75,7 +76,7 @@ export class MemoryDatabase implements IDatabase {
}
public insert(value: any, collectionName = DocumentsCollection): Promise<void> {
- const id = value.id;
+ const { id } = value;
this.getCollection(collectionName)[id] = value;
return Promise.resolve();
}
@@ -93,14 +94,18 @@ export class MemoryDatabase implements IDatabase {
const count = Math.min(ids.length, 1000);
const index = ids.length - count;
const fetchIds = ids.splice(index, count).filter(id => !visited.has(id));
- if (!fetchIds.length) {
- continue;
- }
- const docs = await new Promise<{ [key: string]: any }[]>(res => this.getDocuments(fetchIds, res, collectionName));
- for (const doc of docs) {
- const id = doc.id;
- visited.add(id);
- ids.push(...(await fn(doc)));
+ if (fetchIds.length) {
+ // eslint-disable-next-line no-await-in-loop
+ const docs = await new Promise<{ [key: string]: any }[]>(res => {
+ this.getDocuments(fetchIds, res, collectionName);
+ });
+ // eslint-disable-next-line no-restricted-syntax
+ for (const doc of docs) {
+ const { id } = doc;
+ visited.add(id);
+ // eslint-disable-next-line no-await-in-loop
+ ids.push(...(await fn(doc)));
+ }
}
}
}
diff --git a/src/server/PdfTypes.ts b/src/server/PdfTypes.ts
index e87f08e1d..fb435a677 100644
--- a/src/server/PdfTypes.ts
+++ b/src/server/PdfTypes.ts
@@ -1,21 +1,19 @@
-export interface ParsedPDF {
- numpages: number;
- numrender: number;
- info: PDFInfo;
- metadata: PDFMetadata;
- version: string; //https://mozilla.github.io/pdf.js/getting_started/
- text: string;
-}
-
export interface PDFInfo {
PDFFormatVersion: string;
IsAcroFormPresent: boolean;
IsXFAPresent: boolean;
[key: string]: any;
}
-
export interface PDFMetadata {
parse(): void;
get(name: string): string;
has(name: string): boolean;
-} \ No newline at end of file
+}
+export interface ParsedPDF {
+ numpages: number;
+ numrender: number;
+ info: PDFInfo;
+ metadata: PDFMetadata;
+ version: string; // https://mozilla.github.io/pdf.js/getting_started/
+ text: string;
+}
diff --git a/src/server/ProcessFactory.ts b/src/server/ProcessFactory.ts
index f69eda4c3..3791b0e1e 100644
--- a/src/server/ProcessFactory.ts
+++ b/src/server/ProcessFactory.ts
@@ -1,44 +1,42 @@
-import { ChildProcess, spawn, StdioOptions } from "child_process";
-import { existsSync, mkdirSync } from "fs";
-import { Stream } from "stream";
+import { ChildProcess, spawn, StdioOptions } from 'child_process';
+import { existsSync, mkdirSync } from 'fs';
+import { rimraf } from 'rimraf';
+import { Stream } from 'stream';
import { fileDescriptorFromStream, pathFromRoot } from './ActionUtilities';
-import { rimraf } from "rimraf";
-
-export namespace ProcessFactory {
-
- export type Sink = "pipe" | "ipc" | "ignore" | "inherit" | Stream | number | null | undefined;
-
- export async function createWorker(command: string, args?: readonly string[], stdio?: StdioOptions | "logfile", detached = true): Promise<ChildProcess> {
- if (stdio === "logfile") {
- const log_fd = await Logger.create(command, args);
- stdio = ["ignore", log_fd, log_fd];
- }
- const child = spawn(command, args ?? [], { detached, stdio });
- child.unref();
- return child;
- }
-
-}
export namespace Logger {
-
- const logPath = pathFromRoot("./logs");
+ const logPath = pathFromRoot('./logs');
export async function initialize() {
if (existsSync(logPath)) {
if (!process.env.SPAWNED) {
- await new Promise<any>(resolve => rimraf(logPath).then(resolve));
+ await new Promise<any>(resolve => {
+ rimraf(logPath).then(resolve);
+ });
}
}
mkdirSync(logPath);
}
- export async function create(command: string, args?: readonly string[]): Promise<number> {
- return fileDescriptorFromStream(generate_log_path(command, args));
+ function generateLogPath(command: string, args?: readonly string[]) {
+ return pathFromRoot(`./logs/${command}-${args?.length}-${new Date().toUTCString()}.log`);
}
- function generate_log_path(command: string, args?: readonly string[]) {
- return pathFromRoot(`./logs/${command}-${args?.length}-${new Date().toUTCString()}.log`);
+ export async function create(command: string, args?: readonly string[]): Promise<number> {
+ return fileDescriptorFromStream(generateLogPath(command, args));
}
+}
+export namespace ProcessFactory {
+ export type Sink = 'pipe' | 'ipc' | 'ignore' | 'inherit' | Stream | number | null | undefined;
-} \ No newline at end of file
+ export async function createWorker(command: string, args?: readonly string[], stdio?: StdioOptions | 'logfile', detached = true): Promise<ChildProcess> {
+ if (stdio === 'logfile') {
+ const logFd = await Logger.create(command, args);
+ // eslint-disable-next-line no-param-reassign
+ stdio = ['ignore', logFd, logFd];
+ }
+ const child = spawn(command, args ?? [], { detached, stdio });
+ child.unref();
+ return child;
+ }
+}
diff --git a/src/server/RouteSubscriber.ts b/src/server/RouteSubscriber.ts
index a1cf7c1c4..b923805a8 100644
--- a/src/server/RouteSubscriber.ts
+++ b/src/server/RouteSubscriber.ts
@@ -18,9 +18,8 @@ export default class RouteSubscriber {
public get build() {
let output = this._root;
if (this.requestParameters.length) {
- output = `${output}/:${this.requestParameters.join("/:")}`;
+ output = `${output}/:${this.requestParameters.join('/:')}`;
}
return output;
}
-
-} \ No newline at end of file
+}
diff --git a/src/server/SharedMediaTypes.ts b/src/server/SharedMediaTypes.ts
index 7db1c2dae..0a961f570 100644
--- a/src/server/SharedMediaTypes.ts
+++ b/src/server/SharedMediaTypes.ts
@@ -22,24 +22,17 @@ export namespace Upload {
return 'duration' in uploadResponse;
}
+ export interface AccessPathInfo {
+ [suffix: string]: { client: string; server: string };
+ }
export interface FileInformation {
accessPaths: AccessPathInfo;
rawText?: string;
duration?: number;
}
-
- export type FileResponse<T extends FileInformation = FileInformation> = { source: File; result: T | Error };
-
- export type ImageInformation = FileInformation & InspectionResults;
-
- export type VideoInformation = FileInformation & VideoResults;
-
- export interface AccessPathInfo {
- [suffix: string]: { client: string; server: string };
- }
-
- export interface VideoResults {
- duration: number;
+ export interface EnrichedExifData {
+ data: ExifData & ExifData['gps'];
+ error?: string;
}
export interface InspectionResults {
source: string;
@@ -51,9 +44,13 @@ export namespace Upload {
nativeHeight: number;
filename?: string;
}
-
- export interface EnrichedExifData {
- data: ExifData & ExifData['gps'];
- error?: string;
+ export interface VideoResults {
+ duration: number;
}
+
+ export type FileResponse<T extends FileInformation = FileInformation> = { source: File; result: T | Error };
+
+ export type ImageInformation = FileInformation & InspectionResults;
+
+ export type VideoInformation = FileInformation & VideoResults;
}
diff --git a/src/server/apis/google/CredentialsLoader.ts b/src/server/apis/google/CredentialsLoader.ts
index ef1f9a91e..46dc00b8a 100644
--- a/src/server/apis/google/CredentialsLoader.ts
+++ b/src/server/apis/google/CredentialsLoader.ts
@@ -1,10 +1,9 @@
-import { readFile, readFileSync } from "fs";
-import { pathFromRoot } from "../../ActionUtilities";
-import { SecureContextOptions } from "tls";
-import { blue, red } from "colors";
+import { readFile, readFileSync } from 'fs';
+import { SecureContextOptions } from 'tls';
+import { blue, red } from 'colors';
+import { pathFromRoot } from '../../ActionUtilities';
export namespace GoogleCredentialsLoader {
-
export interface InstalledCredentials {
client_id: string;
project_id: string;
@@ -28,18 +27,16 @@ export namespace GoogleCredentialsLoader {
});
});
}
-
}
export namespace SSL {
-
export let Credentials: SecureContextOptions = {};
export let Loaded = false;
const suffixes = {
- privateKey: ".key",
- certificate: ".crt",
- caBundle: "-ca.crt"
+ privateKey: '.key',
+ certificate: '.crt',
+ caBundle: '-ca.crt',
};
export async function loadCredentials() {
@@ -57,11 +54,10 @@ export namespace SSL {
}
export function exit() {
- console.log(red("Running this server in release mode requires the following SSL credentials in the project root:"));
- const serverName = process.env.serverName ? process.env.serverName : "{process.env.serverName}";
+ console.log(red('Running this server in release mode requires the following SSL credentials in the project root:'));
+ const serverName = process.env.serverName ? process.env.serverName : '{process.env.serverName}';
Object.values(suffixes).forEach(suffix => console.log(blue(`${serverName}${suffix}`)));
- console.log(red("Please ensure these files exist and restart, or run this in development mode."));
+ console.log(red('Please ensure these files exist and restart, or run this in development mode.'));
process.exit(0);
}
-
}
diff --git a/src/server/apis/google/GoogleApiServerUtils.ts b/src/server/apis/google/GoogleApiServerUtils.ts
index 55e5fd7c0..d3acc968b 100644
--- a/src/server/apis/google/GoogleApiServerUtils.ts
+++ b/src/server/apis/google/GoogleApiServerUtils.ts
@@ -57,12 +57,12 @@ export namespace GoogleApiServerUtils {
* global, intentionally unauthenticated worker OAuth2 client instance.
*/
export function processProjectCredentials(): void {
- const { client_secret, client_id, redirect_uris } = GoogleCredentialsLoader.ProjectCredentials;
+ const { client_secret: clientSecret, client_id: clientId, redirect_uris: redirectUris } = GoogleCredentialsLoader.ProjectCredentials;
// initialize the global authorization client
oAuthOptions = {
- clientId: client_id,
- clientSecret: client_secret,
- redirectUri: redirect_uris[0],
+ clientId,
+ clientSecret,
+ redirectUri: redirectUris[0],
};
worker = generateClient();
}
diff --git a/src/server/apis/google/SharedTypes.ts b/src/server/apis/google/SharedTypes.ts
index 9ad6130b6..f5e0e2e2b 100644
--- a/src/server/apis/google/SharedTypes.ts
+++ b/src/server/apis/google/SharedTypes.ts
@@ -1,9 +1,3 @@
-export interface NewMediaItemResult {
- uploadToken: string;
- status: { code: number, message: string };
- mediaItem: MediaItem;
-}
-
export interface MediaItem {
id: string;
description: string;
@@ -17,5 +11,10 @@ export interface MediaItem {
};
filename: string;
}
+export interface NewMediaItemResult {
+ uploadToken: string;
+ status: { code: number; message: string };
+ mediaItem: MediaItem;
+}
-export type MediaItemCreationResult = { newMediaItemResults: NewMediaItemResult[] }; \ No newline at end of file
+export type MediaItemCreationResult = { newMediaItemResults: NewMediaItemResult[] };
diff --git a/src/server/apis/youtube/youtubeApiSample.d.ts b/src/server/apis/youtube/youtubeApiSample.d.ts
index 427f54608..97c3f0b54 100644
--- a/src/server/apis/youtube/youtubeApiSample.d.ts
+++ b/src/server/apis/youtube/youtubeApiSample.d.ts
@@ -1,2 +1,2 @@
declare const YoutubeApi: any;
-export = YoutubeApi; \ No newline at end of file
+export = YoutubeApi;
diff --git a/src/server/authentication/DashUserModel.ts b/src/server/authentication/DashUserModel.ts
index 3bc21ecb6..a288bfeab 100644
--- a/src/server/authentication/DashUserModel.ts
+++ b/src/server/authentication/DashUserModel.ts
@@ -73,9 +73,9 @@ userSchema.pre('save', function save(next) {
user.password,
salt,
() => {},
- (err: mongoose.Error, hash: string) => {
- if (err) {
- return next(err);
+ (cryptErr: mongoose.Error, hash: string) => {
+ if (cryptErr) {
+ return next(cryptErr);
}
user.password = hash;
next();
@@ -97,7 +97,7 @@ const comparePassword: comparePasswordFunction = function (this: DashUserModel,
userSchema.methods.comparePassword = comparePassword;
-const User = mongoose.model('User', userSchema);
+const User: any = mongoose.model('User', userSchema);
export function initializeGuest() {
new User({
email: 'guest',
diff --git a/src/server/authentication/Passport.ts b/src/server/authentication/Passport.ts
index a9cf6698b..a5222e531 100644
--- a/src/server/authentication/Passport.ts
+++ b/src/server/authentication/Passport.ts
@@ -1,6 +1,6 @@
import * as passport from 'passport';
import * as passportLocal from 'passport-local';
-import { DashUserModel, default as User } from './DashUserModel';
+import User, { DashUserModel } from './DashUserModel';
const LocalStrategy = passportLocal.Strategy;
@@ -11,22 +11,25 @@ passport.serializeUser<any, any>((req, user, done) => {
passport.deserializeUser<any, any>((id, done) => {
User.findById(id)
.exec()
- .then(user => done(undefined, user));
+ .then((user: any) => done(undefined, user));
});
// AUTHENTICATE JUST WITH EMAIL AND PASSWORD
passport.use(
new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => {
User.findOne({ email: email.toLowerCase() })
- .then(user => {
- if (!user) return done(undefined, false, { message: 'Invalid email or password' }); // invalid email
- (user as any as DashUserModel).comparePassword(password, (error: Error, isMatch: boolean) => {
- if (error) return done(error);
- if (!isMatch) return done(undefined, false, { message: 'Invalid email or password' }); // invalid password
- // valid authentication HERE
- return done(undefined, user);
- });
+ .then((user: any) => {
+ if (!user) {
+ done(undefined, false, { message: 'Invalid email or password' }); // invalid email
+ } else {
+ (user as any as DashUserModel).comparePassword(password, (error: Error, isMatch: boolean) => {
+ if (error) return done(error);
+ if (!isMatch) return done(undefined, false, { message: 'Invalid email or password' }); // invalid password
+ // valid authentication HERE
+ return done(undefined, user);
+ });
+ }
})
- .catch(error => done(error));
+ .catch((error: any) => done(error));
})
);
diff --git a/src/server/database.ts b/src/server/database.ts
index 3a28dc87e..ff5635b2c 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -58,6 +58,7 @@ export namespace Database {
}
}
+ // eslint-disable-next-line @typescript-eslint/no-shadow
export class Database implements IDatabase {
private MongoClient = mongodb.MongoClient;
private currentWrites: { [id: string]: Promise<void> } = {};
diff --git a/src/server/index.ts b/src/server/index.ts
index 5a86f36d9..4374a72b7 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1,15 +1,14 @@
import { yellow } from 'colors';
+// eslint-disable-next-line import/no-extraneous-dependencies
import * as dotenv from 'dotenv';
import * as mobileDetect from 'mobile-detect';
import * as path from 'path';
-import * as qs from 'query-string';
import { logExecution } from './ActionUtilities';
import { AdminPrivileges, resolvedPorts } from './SocketData';
import DataVizManager from './ApiManagers/DataVizManager';
import DeleteManager from './ApiManagers/DeleteManager';
import DownloadManager from './ApiManagers/DownloadManager';
import GeneralGoogleManager from './ApiManagers/GeneralGoogleManager';
-//import GooglePhotosManager from './ApiManagers/GooglePhotosManager';
import { SearchManager } from './ApiManagers/SearchManager';
import SessionManager from './ApiManagers/SessionManager';
import UploadManager from './ApiManagers/UploadManager';
@@ -26,8 +25,11 @@ import { Logger } from './ProcessFactory';
import RouteManager, { Method, PublicHandler } from './RouteManager';
import RouteSubscriber from './RouteSubscriber';
import initializeServer from './server_Initialization';
+// import GooglePhotosManager from './ApiManagers/GooglePhotosManager';
+
dotenv.config();
export const onWindows = process.platform === 'win32';
+// eslint-disable-next-line import/no-mutable-exports
export let sessionAgent: AppliedSessionAgent;
/**
@@ -60,8 +62,18 @@ async function preliminaryFunctions() {
* that will manage the registration of new routes
* with the server
*/
-function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }: RouteManager) {
- const managers = [new SessionManager(), new UserManager(), new UploadManager(), new DownloadManager(), new SearchManager(), new DeleteManager(), new UtilManager(), new GeneralGoogleManager(), /* new GooglePhotosManager(),*/ new DataVizManager()];
+function routeSetter({ addSupervisedRoute, logRegistrationOutcome }: RouteManager) {
+ const managers = [
+ new SessionManager(),
+ new UserManager(),
+ new UploadManager(),
+ new DownloadManager(),
+ new SearchManager(),
+ new DeleteManager(),
+ new UtilManager(),
+ new GeneralGoogleManager(),
+ /* new GooglePhotosManager(), */ new DataVizManager(),
+ ];
// initialize API Managers
console.log(yellow('\nregistering server routes...'));
@@ -102,6 +114,7 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
});
const serve: PublicHandler = ({ req, res }) => {
+ // eslint-disable-next-line new-cap
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));
@@ -116,9 +129,8 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
secureHandler: ({ res, isRelease }) => {
const { PASSWORD } = process.env;
if (!(isRelease && PASSWORD)) {
- return res.redirect('/home');
- }
- res.render('admin.pug', { title: 'Enter Administrator Password' });
+ res.redirect('/home');
+ } else res.render('admin.pug', { title: 'Enter Administrator Password' });
},
});
@@ -128,18 +140,19 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
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) {
- AdminPrivileges.set(id, true);
- redirect = `/${previous_target.replace(':', '/')}`;
+ res.redirect('/home');
} else {
- redirect = `/admin/${previous_target}`;
+ const { password } = req.body;
+ const { previous_target: previousTarget } = req.params;
+ let redirect: string;
+ if (password === PASSWORD) {
+ AdminPrivileges.set(id, true);
+ redirect = `/${previousTarget.replace(':', '/')}`;
+ } else {
+ redirect = `/admin/${previousTarget}`;
+ }
+ res.redirect(redirect);
}
- res.redirect(redirect);
},
});
@@ -149,7 +162,6 @@ function routeSetter({ isRelease, addSupervisedRoute, logRegistrationOutcome }:
secureHandler: serve,
publicHandler: ({ req, res, ...remaining }) => {
const { originalUrl: target } = req;
- const sharing = qs.parse(qs.extract(req.originalUrl), { sort: false }).sharing === 'true';
const docAccess = target.startsWith('/doc/');
// since this is the public handler, there's no meaning of '/home' to speak of
// since there's no user logged in, so the only viable operation
diff --git a/src/server/updateProtos.ts b/src/server/updateProtos.ts
index 2f3772a77..72a44ebf4 100644
--- a/src/server/updateProtos.ts
+++ b/src/server/updateProtos.ts
@@ -6,15 +6,15 @@ const protos = ['text', 'image', 'web', 'collection', 'kvp', 'video', 'audio', '
await Promise.all(
protos.map(
protoId =>
- new Promise(res =>
+ new Promise(res => {
Database.Instance.update(
protoId,
{
$set: { 'fields.isBaseProto': true },
},
res
- )
- )
+ );
+ })
)
);
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index cb16bce72..cece8a1b7 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -79,7 +79,7 @@ export namespace WebSocket {
timeMap[userEmail] = Date.now();
socketMap.set(socket, userEmail + ' at ' + datetime);
userOperations.set(userEmail, 0);
- DashStats.logUserLogin(userEmail, socket);
+ DashStats.logUserLogin(userEmail);
}
function getField([id, callback]: [string, (result?: Transferable) => void]) {
@@ -417,38 +417,12 @@ export namespace WebSocket {
socket.in(room).emit('message', message);
});
- socket.on('create or join', room => {
- console.log('Received request to create or join room ' + room);
-
- const clientsInRoom = socket.rooms.has(room);
- const numClients = clientsInRoom ? Object.keys(room.sockets).length : 0;
- console.log('Room ' + room + ' now has ' + numClients + ' client(s)');
-
- if (numClients === 0) {
- socket.join(room);
- console.log('Client ID ' + socket.id + ' created room ' + room);
- socket.emit('created', room, socket.id);
- } else if (numClients === 1) {
- console.log('Client ID ' + socket.id + ' joined room ' + room);
- socket.in(room).emit('join', room);
- socket.join(room);
- socket.emit('joined', room, socket.id);
- socket.in(room).emit('ready');
- } else {
- // max two clients
- socket.emit('full', room);
- }
- });
-
socket.on('ipaddr', () => {
- const ifaces = networkInterfaces();
- for (const dev in ifaces) {
- ifaces[dev]?.forEach(details => {
- if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
- socket.emit('ipaddr', details.address);
- }
- });
- }
+ networkInterfaces().keys?.forEach(dev => {
+ if (dev.family === 'IPv4' && dev.address !== '127.0.0.1') {
+ socket.emit('ipaddr', dev.address);
+ }
+ });
});
socket.on('bye', () => {
@@ -459,7 +433,7 @@ export namespace WebSocket {
const currentUser = socketMap.get(socket);
if (!(currentUser === undefined)) {
const currentUsername = currentUser.split(' ')[0];
- DashStats.logUserLogout(currentUsername, socket);
+ DashStats.logUserLogout(currentUsername);
delete timeMap[currentUsername];
}
});