import * as express from 'express' 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, Transferable } from "./Message"; import { Client } from './Client'; import { Socket } from 'socket.io'; import { Utils } from '../Utils'; import { ObservableMap } from 'mobx'; import { FieldId, Field } from '../fields/Field'; import { Database } from './database'; import * as io from 'socket.io' 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 const serverPort = 4321; import * as expressValidator from 'express-validator'; import expressFlash = require('express-flash'); import flash = require('connect-flash'); import * as bodyParser from 'body-parser'; import * as session from 'express-session'; import * as cookieParser from 'cookie-parser'; import * as mobileDetect from 'mobile-detect'; import c = require("crypto"); const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); import { DashUserModel } from './authentication/models/user_model'; import * as fs from 'fs'; import * as request from 'request' import { RouteStore } from './RouteStore'; import { exec } from 'child_process' const download = (url: string, dest: fs.PathLike) => { request.get(url).pipe(fs.createWriteStream(dest)); } const mongoUrl = 'mongodb://localhost:27017/Dash'; mongoose.connect(mongoUrl) mongoose.connection.on('connected', function () { console.log("connected"); }) // SESSION MANAGEMENT AND AUTHENTICATION MIDDLEWARE // ORDER OF IMPORTS MATTERS app.use(cookieParser()); app.use(session({ secret: "64d6866242d3b5a5503c675b32c9605e4e90478e9b77bcf2bc", resave: true, cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 }, saveUninitialized: true, store: new MongoStore({ url: 'mongodb://localhost:27017/Dash' }) })); app.use(flash()); app.use(expressFlash()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(expressValidator()); app.use(passport.initialize()); app.use(passport.session()); app.use((req, res, next) => { res.locals.user = req.user; next(); }); app.get("/hello", (req, res) => { res.send("

Hello

"); }) enum Method { 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 handler the action to invoke, recieving a DashUserModel and, as expected, the Express.Request and Express.Response * @param onRejection an optional callback invoked on return if no user is found to be logged in * @param subscribers the forward slash prepended path names (reference and add to RouteStore.ts) that will all invoke the given @param handler */ function addSecureRoute(method: Method, handler: (user: DashUserModel, res: express.Response, req: express.Request) => void, onRejection: (res: express.Response) => any = (res) => res.redirect(RouteStore.logout), ...subscribers: string[] ) { let abstracted = (req: express.Request, res: express.Response) => { const dashUser: DashUserModel = req.user; if (!dashUser) return onRejection(res); handler(dashUser, res, req); } subscribers.forEach(route => { switch (method) { case Method.GET: app.get(route, abstracted); break; case Method.POST: app.post(route, abstracted); break; } }); } // STATIC FILE SERVING let FieldStore: ObservableMap = new ObservableMap(); app.use(express.static(__dirname + RouteStore.public)); app.use(RouteStore.images, express.static(__dirname + RouteStore.public)) app.get("/pull", (req, res) => { exec('"C:\\Program Files\\Git\\git-bash.exe" -c "git pull"', (err, stdout, stderr) => { if (err) { res.send(err.message); return; } res.redirect("/"); }) }); // GETTERS // anyone attempting to navigate to localhost at this port will // first have to login addSecureRoute( Method.GET, (user, res) => res.redirect(RouteStore.home), undefined, RouteStore.root ); addSecureRoute( Method.GET, (user, res, req) => { let detector = new mobileDetect(req.headers['user-agent'] || ""); if (detector.mobile() != null) { res.sendFile(path.join(__dirname, '../../deploy/mobile/image.html')); } else { res.sendFile(path.join(__dirname, '../../deploy/index.html')); } }, undefined, RouteStore.home, RouteStore.openDocumentWithId ); addSecureRoute( Method.GET, (user, res) => res.send(user.userDocumentId || ""), undefined, RouteStore.getUserDocumentId, ); addSecureRoute( Method.GET, (user, res) => { res.send(JSON.stringify({ id: user.id, email: user.email })); }, undefined, RouteStore.getCurrUser ); // SETTERS addSecureRoute( Method.POST, (user, res, req) => { 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); }); }, undefined, RouteStore.upload ); // AUTHENTICATION // Sign Up app.get(RouteStore.signup, getSignup); app.post(RouteStore.signup, postSignup); // Log In app.get(RouteStore.login, getLogin); app.post(RouteStore.login, postLogin); // Log Out app.get(RouteStore.logout, getLogout); // FORGOT PASSWORD EMAIL HANDLING app.get(RouteStore.forgot, getForgot) app.post(RouteStore.forgot, postForgot) // RESET PASSWORD EMAIL HANDLING app.get(RouteStore.reset, getReset); app.post(RouteStore.reset, postReset); app.use(RouteStore.corsProxy, (req, res) => { req.pipe(request(req.url.substring(1))).pipe(res); }); app.get(RouteStore.delete, (req, res) => { deleteFields().then(() => res.redirect(RouteStore.home)); }); app.get(RouteStore.deleteAll, (req, res) => { deleteAll().then(() => res.redirect(RouteStore.home)); }); app.use(wdm(compiler, { publicPath: config.output.publicPath })) app.use(whm(compiler)) // start the Express server app.listen(port, () => { console.log(`server started at http://localhost:${port}`); }) const server = io(); interface Map { [key: string]: Client; } let clients: Map = {} server.on("connection", function (socket: Socket) { console.log("a user has connected") Utils.Emit(socket, MessageStore.Foo, "handshooken") Utils.AddServerHandler(socket, MessageStore.Bar, barReceived) Utils.AddServerHandler(socket, MessageStore.SetField, (args) => setField(socket, args)) Utils.AddServerHandlerCallback(socket, MessageStore.GetField, getField) Utils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields) Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields) }) function deleteFields() { return Database.Instance.deleteAll(); } function deleteAll() { return Database.Instance.deleteAll().then(() => { return Database.Instance.deleteAll('sessions') }).then(() => { return Database.Instance.deleteAll('users') }); } function barReceived(guid: String) { clients[guid.toString()] = new Client(guid.toString()); } function getField([id, callback]: [string, (result: any) => void]) { Database.Instance.getDocument(id, (result: any) => { if (result) { callback(result) } else { callback(undefined) } }) } function getFields([ids, callback]: [string[], (result: any) => void]) { Database.Instance.getDocuments(ids, callback); } function setField(socket: Socket, newValue: Transferable) { Database.Instance.update(newValue._id, newValue, () => { socket.broadcast.emit(MessageStore.SetField.Message, newValue); }) } server.listen(serverPort); console.log(`listening on port ${serverPort}`);