aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/Message.ts2
-rw-r--r--src/server/RouteStore.ts28
-rw-r--r--src/server/ServerUtil.ts35
-rw-r--r--src/server/authentication/config/passport.ts3
-rw-r--r--src/server/authentication/controllers/user_controller.ts47
-rw-r--r--src/server/authentication/models/user_model.ts2
-rw-r--r--src/server/database.ts4
-rw-r--r--src/server/index.ts137
8 files changed, 153 insertions, 105 deletions
diff --git a/src/server/Message.ts b/src/server/Message.ts
index 5e97a5edf..8a00f6b59 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -45,7 +45,7 @@ export class GetFieldArgs {
}
export enum Types {
- Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html, Ink, PDF
+ Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html, Video, Audio, Ink, PDF
}
export class DocumentTransfer implements Transferable {
diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts
new file mode 100644
index 000000000..ace2152d7
--- /dev/null
+++ b/src/server/RouteStore.ts
@@ -0,0 +1,28 @@
+// PREPEND ALL ROUTES WITH FORWARD SLASHES!
+
+export enum RouteStore {
+ // GENERAL
+ root = "/root",
+ home = "/home",
+ corsProxy = "/corsProxy",
+ delete = "/delete",
+
+ // UPLOAD AND STATIC FILE SERVING
+ public = "/public",
+ upload = "/upload",
+ images = "/images",
+
+ // USER AND WORKSPACES
+ addWorkspace = "/addWorkspaceId",
+ getAllWorkspaces = "/getAllWorkspaceIds",
+ getActiveWorkspace = "/getActiveWorkspaceId",
+ setActiveWorkspace = "/setActiveWorkspaceId",
+
+ // AUTHENTICATION
+ signup = "/signup",
+ login = "/login",
+ logout = "/logout",
+ forgot = "/forgotpassword",
+ reset = "/reset/:token",
+
+} \ No newline at end of file
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
index 3b9d14891..5331c9e30 100644
--- a/src/server/ServerUtil.ts
+++ b/src/server/ServerUtil.ts
@@ -1,17 +1,24 @@
-import {HtmlField} from '../fields/HtmlField';
+
+import { Field } from './../fields/Field';
+import { TextField } from './../fields/TextField';
+import { NumberField } from './../fields/NumberField';
+import { RichTextField } from './../fields/RichTextField';
+import { Key } from './../fields/Key';
+import { ImageField } from './../fields/ImageField';
+import { ListField } from './../fields/ListField';
+import { Document } from './../fields/Document';
+import { Server } from './../client/Server';
+import { Types } from './Message';
+import { Utils } from '../Utils';
+import { HtmlField } from '../fields/HtmlField';
+import { WebField } from '../fields/WebField';
+import { AudioField } from '../fields/AudioField';
+import { VideoField } from '../fields/VideoField';
import {InkField} from '../fields/InkField';
import {PDFField} from '../fields/PDFField';
-import {WebField} from '../fields/WebField';
-import {Utils} from '../Utils';
-import {Document} from './../fields/Document';
-import {Field} from './../fields/Field';
-import {ImageField} from './../fields/ImageField';
-import {Key} from './../fields/Key';
-import {ListField} from './../fields/ListField';
-import {NumberField} from './../fields/NumberField';
-import {RichTextField} from './../fields/RichTextField';
-import {TextField} from './../fields/TextField';
-import {Types} from './Message';
+
+
+
export class ServerUtils {
public static FromJson(json: any): Field {
@@ -44,6 +51,10 @@ export class ServerUtils {
return new PDFField(new URL(data), id, false)
case Types.List:
return ListField.FromJson(id, data)
+ case Types.Audio:
+ return new AudioField(new URL(data), id, false)
+ case Types.Video:
+ return new VideoField(new URL(data), id, false)
case Types.Ink:
return InkField.FromJson(id, data);
case Types.Document:
diff --git a/src/server/authentication/config/passport.ts b/src/server/authentication/config/passport.ts
index d90bedb18..b6fe15655 100644
--- a/src/server/authentication/config/passport.ts
+++ b/src/server/authentication/config/passport.ts
@@ -4,6 +4,7 @@ import * as mongodb from 'mongodb';
import * as _ from "lodash";
import { default as User } from '../models/user_model';
import { Request, Response, NextFunction } from "express";
+import { RouteStore } from '../../RouteStore';
const LocalStrategy = passportLocal.Strategy;
@@ -35,7 +36,7 @@ export let isAuthenticated = (req: Request, res: Response, next: NextFunction) =
if (req.isAuthenticated()) {
return next();
}
- return res.redirect("/login");
+ return res.redirect(RouteStore.login);
}
export let isAuthorized = (req: Request, res: Response, next: NextFunction) => {
diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts
index 7b89b5152..2cef958e8 100644
--- a/src/server/authentication/controllers/user_controller.ts
+++ b/src/server/authentication/controllers/user_controller.ts
@@ -10,18 +10,7 @@ import * as pug from 'pug';
import * as async from 'async';
import * as nodemailer from 'nodemailer';
import c = require("crypto");
-
-
-/**
- * GET /
- * Whenever a user navigates to the root of Dash
- * (doesn't specify a sub-route), redirect to login.
- * If the user is already signed in, it will effectively
- * automatically redirect them to /home instead
- */
-export let getEntry = (req: Request, res: Response) => {
- res.redirect("/login");
-}
+import { RouteStore } from "../../RouteStore";
/**
* GET /signup
@@ -31,7 +20,7 @@ export let getEntry = (req: Request, res: Response) => {
export let getSignup = (req: Request, res: Response) => {
if (req.user) {
let user = req.user;
- return res.redirect("/home");
+ return res.redirect(RouteStore.home);
}
res.render("signup.pug", {
title: "Sign Up",
@@ -56,7 +45,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => {
title: "Sign Up",
user: req.user,
});
- return res.redirect("/signup");
+ return res.redirect(RouteStore.signup);
}
const email = req.body.email;
@@ -71,7 +60,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => {
User.findOne({ email }, (err, existingUser) => {
if (err) { return next(err); }
if (existingUser) {
- return res.redirect("/login");
+ return res.redirect(RouteStore.login);
}
user.save((err) => {
if (err) { return next(err); }
@@ -79,7 +68,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => {
if (err) {
return next(err);
}
- res.redirect("/home");
+ res.redirect(RouteStore.home);
});
});
});
@@ -93,7 +82,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => {
*/
export let getLogin = (req: Request, res: Response) => {
if (req.user) {
- return res.redirect("/home");
+ return res.redirect(RouteStore.home);
}
res.render("login.pug", {
title: "Log In",
@@ -104,7 +93,7 @@ export let getLogin = (req: Request, res: Response) => {
/**
* POST /login
* Sign in using email and password.
- * On failure, redirect to login page
+ * On failure, redirect to signup page
*/
export let postLogin = (req: Request, res: Response, next: NextFunction) => {
req.assert("email", "Email is not valid").isEmail();
@@ -115,17 +104,17 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
if (errors) {
req.flash("errors", "Unable to login at this time. Please try again.");
- return res.redirect("/signup");
+ return res.redirect(RouteStore.signup);
}
passport.authenticate("local", (err: Error, user: DashUserModel, info: IVerifyOptions) => {
if (err) { return next(err); }
if (!user) {
- return res.redirect("/signup");
+ return res.redirect(RouteStore.signup);
}
req.logIn(user, (err) => {
if (err) { return next(err); }
- res.redirect("/home");
+ res.redirect(RouteStore.home);
});
})(req, res, next);
};
@@ -136,16 +125,12 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
* and destroys the user's current session.
*/
export let getLogout = (req: Request, res: Response) => {
- const dashUser: DashUserModel | undefined = req.user;
- if (dashUser) {
- dashUser.update({ $set: { didSelectSessionWorkspace: false } }, () => { })
- }
req.logout();
const sess = req.session;
if (sess) {
sess.destroy((err) => { if (err) { console.log(err); } });
}
- res.redirect('/login');
+ res.redirect(RouteStore.login);
}
export let getForgot = function (req: Request, res: Response) {
@@ -172,7 +157,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio
User.findOne({ email }, function (err, user: DashUserModel) {
if (!user) {
// NO ACCOUNT WITH SUBMITTED EMAIL
- return res.redirect('/forgot');
+ return res.redirect(RouteStore.forgot);
}
user.passwordResetToken = token;
user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 HOUR
@@ -205,14 +190,14 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio
}
], function (err) {
if (err) return next(err);
- res.redirect('/forgot');
+ res.redirect(RouteStore.forgot);
})
}
export let getReset = function (req: Request, res: Response) {
User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err, user: DashUserModel) {
if (!user || err) {
- return res.redirect('/forgot');
+ return res.redirect(RouteStore.forgot);
}
res.render("reset.pug", {
title: "Reset Password",
@@ -242,7 +227,7 @@ export let postReset = function (req: Request, res: Response) {
user.save(function (err) {
if (err) {
- return res.redirect("/login");
+ return res.redirect(RouteStore.login);
}
req.logIn(user, function (err) {
if (err) {
@@ -273,6 +258,6 @@ export let postReset = function (req: Request, res: Response) {
});
}
], function (err) {
- res.redirect('/login');
+ res.redirect(RouteStore.login);
});
} \ No newline at end of file
diff --git a/src/server/authentication/models/user_model.ts b/src/server/authentication/models/user_model.ts
index 29076ba19..3d4ed6896 100644
--- a/src/server/authentication/models/user_model.ts
+++ b/src/server/authentication/models/user_model.ts
@@ -23,6 +23,7 @@ export type DashUserModel = mongoose.Document & {
allWorkspaceIds: Array<String>,
activeWorkspaceId: String,
+ activeUsersId: String,
profile: {
name: string,
@@ -53,6 +54,7 @@ const userSchema = new mongoose.Schema({
default: []
},
activeWorkspaceId: String,
+ activeUsersId: String,
facebook: String,
twitter: String,
diff --git a/src/server/database.ts b/src/server/database.ts
index 1553dd94e..f414266e2 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -16,12 +16,12 @@ export class Database {
})
}
- public update(id: string, value: any) {
+ public update(id: string, value: any, callback: () => void) {
if (this.db) {
let collection = this.db.collection('documents');
collection.update({ _id: id }, { $set: value }, {
upsert: true
- });
+ }, callback);
}
}
diff --git a/src/server/index.ts b/src/server/index.ts
index fad30f3ad..6f6f620d8 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -3,6 +3,8 @@ const app = express()
import * as webpack from 'webpack'
import * as wdm from 'webpack-dev-middleware';
import * as whm from 'webpack-hot-middleware';
+import * as path from 'path'
+import * as formidable from 'formidable'
import * as passport from 'passport';
import { MessageStore, Message, SetFieldArgs, GetFieldArgs, Transferable } from "./Message";
import { Client } from './Client';
@@ -17,7 +19,7 @@ import * as bcrypt from "bcrypt-nodejs";
import { Document } from '../fields/Document';
import * as io from 'socket.io'
import * as passportConfig from './authentication/config/passport';
-import { getLogin, postLogin, getSignup, postSignup, getLogout, getEntry, postReset, getForgot, postForgot, getReset } from './authentication/controllers/user_controller';
+import { getLogin, postLogin, getSignup, postSignup, getLogout, postReset, getForgot, postForgot, getReset } from './authentication/controllers/user_controller';
const config = require('../../webpack.config');
const compiler = webpack(config);
const port = 1050; // default port to listen
@@ -33,10 +35,10 @@ import c = require("crypto");
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');
import { performance } from 'perf_hooks'
-import * as path from 'path'
import User, { DashUserModel } from './authentication/models/user_model';
import * as fs from 'fs';
import * as request from 'request'
+import { RouteStore } from './RouteStore';
const download = (url: string, dest: fs.PathLike) => {
request.get(url).pipe(fs.createWriteStream(dest));
@@ -61,11 +63,7 @@ app.use(session({
url: 'mongodb://localhost:27017/Dash'
})
}));
-// app.use(cookieSession({
-// name: 'authentication',
-// keys: [`${c.randomBytes(8)}`, `${c.randomBytes(8)}`, `${c.randomBytes(8)}`],
-// maxAge: 7 * 24 * 60 * 60 * 1000
-// }));
+
app.use(flash());
app.use(expressFlash());
app.use(bodyParser.json());
@@ -78,97 +76,123 @@ app.use((req, res, next) => {
next();
});
-// AUTHENTICATION ROUTING
-
enum Method {
- Get,
- Post
+ GET,
+ POST
}
+/**
+ * Please invoke this function when adding a new route to Dash's server.
+ * It ensures that any requests leading to or containing user-sensitive information
+ * does not execute unless Passport authentication detects a user logged in.
+ * @param method whether or not the request is a GET or a POST
+ * @param route the forward slash prepended path name (reference and add to RouteStore.ts)
+ * @param handler the action to invoke, recieving a DashUserModel and the expected request and response
+ * @param onRejection an optional callback invoked on return if no user is found to be logged in
+ */
function addSecureRoute(method: Method,
route: string,
handler: (user: DashUserModel, req: express.Request, res: express.Response) => void,
- nope: (res: express.Response) => any) {
- route = "/" + route;
+ onRejection: (res: express.Response) => any = (res) => res.redirect(RouteStore.logout)) {
switch (method) {
- case Method.Get:
+ case Method.GET:
app.get(route, (req, res) => {
const dashUser: DashUserModel = req.user;
- if (!dashUser) return nope(res);
+ if (!dashUser) return onRejection(res);
handler(dashUser, req, res);
});
break;
- case Method.Post:
+ case Method.POST:
app.post(route, (req, res) => {
const dashUser: DashUserModel = req.user;
- if (!dashUser) return nope(res);
+ if (!dashUser) return onRejection(res);
handler(dashUser, req, res);
});
break;
}
}
-// ***
-// Look for the definitions of these get and post
-// functions in the exports of user.ts
+// STATIC FILE SERVING
-addSecureRoute(Method.Get, "home", (user, req, res) => {
+let FieldStore: ObservableMap<FieldId, Field> = new ObservableMap();
+
+app.use(express.static(__dirname + RouteStore.public));
+app.use(RouteStore.images, express.static(__dirname + RouteStore.public))
+
+addSecureRoute(Method.POST, RouteStore.upload, (user, req, res) => {
+ let form = new formidable.IncomingForm()
+ form.uploadDir = __dirname + "/public/files/"
+ form.keepExtensions = true
+ // let path = req.body.path;
+ console.log("upload")
+ form.parse(req, (err, fields, files) => {
+ console.log("parsing")
+ let names: any[] = [];
+ for (const name in files) {
+ let file = files[name];
+ names.push(`/files/` + path.basename(file.path));
+ }
+ res.send(names);
+ });
+});
+
+// anyone attempting to navigate to localhost at this port will
+// first have to login
+addSecureRoute(Method.GET, RouteStore.root, (user, req, res) => {
+
+}, res => {
+ res.send()
+});
+
+// YAY! SHOW THEM THEIR WORKSPACES NOW
+addSecureRoute(Method.GET, RouteStore.home, (user, req, res) => {
res.sendFile(path.join(__dirname, '../../deploy/index.html'));
-}, res => res.redirect("/login"))
+});
-addSecureRoute(Method.Get, "getActiveWorkspaceId", (user, req, res) => {
+addSecureRoute(Method.GET, RouteStore.getActiveWorkspace, (user, req, res) => {
res.send(user.activeWorkspaceId || "");
-}, () => { });
+});
-addSecureRoute(Method.Get, "getAllWorkspaceIds", (user, req, res) => {
+addSecureRoute(Method.GET, RouteStore.getAllWorkspaces, (user, req, res) => {
res.send(JSON.stringify(user.allWorkspaceIds as Array<String>));
-}, () => { });
+});
-addSecureRoute(Method.Post, "setActiveWorkspaceId", (user, req) => {
+addSecureRoute(Method.POST, RouteStore.setActiveWorkspace, (user, req) => {
user.update({ $set: { activeWorkspaceId: req.body.target } }, () => { });
-}, () => { });
+});
-addSecureRoute(Method.Post, "addWorkspaceId", (user, req) => {
+addSecureRoute(Method.POST, RouteStore.addWorkspace, (user, req) => {
user.update({ $push: { allWorkspaceIds: req.body.target } }, () => { });
-}, () => { });
+});
-// anyone attempting to navigate to localhost at this port will
-// first have to login
-app.get("/", getEntry);
+// AUTHENTICATION
// Sign Up
-app.get("/signup", getSignup);
-app.post("/signup", postSignup);
+app.get(RouteStore.signup, getSignup);
+app.post(RouteStore.signup, postSignup);
// Log In
-app.get("/login", getLogin);
-app.post("/login", postLogin);
+app.get(RouteStore.login, getLogin);
+app.post(RouteStore.login, postLogin);
// Log Out
-app.get('/logout', getLogout);
-
-// ***
+app.get(RouteStore.logout, getLogout);
// FORGOT PASSWORD EMAIL HANDLING
-app.get('/forgot', getForgot)
-app.post('/forgot', postForgot)
+app.get(RouteStore.forgot, getForgot)
+app.post(RouteStore.forgot, postForgot)
// RESET PASSWORD EMAIL HANDLING
-app.get('/reset/:token', getReset);
-app.post('/reset/:token', postReset);
+app.get(RouteStore.reset, getReset);
+app.post(RouteStore.reset, postReset);
-let FieldStore: ObservableMap<FieldId, Field> = new ObservableMap();
-app.get("/hello", (req, res) => {
- res.send("<p>Hello</p>");
-})
-
-app.use("/corsProxy", (req, res) => {
+app.use(RouteStore.corsProxy, (req, res) => {
req.pipe(request(req.url.substring(1))).pipe(res);
});
-app.get("/delete", (req, res) => {
+app.get(RouteStore.delete, (req, res) => {
deleteAll();
- res.redirect("/");
+ res.redirect(RouteStore.home);
});
app.use(wdm(compiler, {
@@ -208,10 +232,6 @@ function barReceived(guid: String) {
clients[guid.toString()] = new Client(guid.toString());
}
-function addDocument(document: Document) {
-
-}
-
function getField([id, callback]: [string, (result: any) => void]) {
Database.Instance.getDocument(id, (result: any) => {
if (result) {
@@ -228,8 +248,9 @@ function getFields([ids, callback]: [string[], (result: any) => void]) {
}
function setField(socket: Socket, newValue: Transferable) {
- Database.Instance.update(newValue._id, newValue)
- socket.broadcast.emit(MessageStore.SetField.Message, newValue)
+ Database.Instance.update(newValue._id, newValue, () => {
+ socket.broadcast.emit(MessageStore.SetField.Message, newValue);
+ })
}
server.listen(serverPort);