diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/Client.ts | 12 | ||||
| -rw-r--r-- | src/server/Message.ts | 120 | ||||
| -rw-r--r-- | src/server/ServerUtil.ts | 118 | ||||
| -rw-r--r-- | src/server/authentication/config/passport.ts | 6 | ||||
| -rw-r--r-- | src/server/authentication/controllers/WorkspacesMenu.tsx | 4 | ||||
| -rw-r--r-- | src/server/authentication/controllers/user_controller.ts | 26 | ||||
| -rw-r--r-- | src/server/authentication/models/current_user_utils.ts | 107 | ||||
| -rw-r--r-- | src/server/authentication/models/user_model.ts | 23 | ||||
| -rw-r--r-- | src/server/database.ts | 114 | ||||
| -rw-r--r-- | src/server/index.ts | 190 | ||||
| -rw-r--r-- | src/server/public/files/.gitignore | 1 | ||||
| -rw-r--r-- | src/server/public/files/upload_e72669595eae4384a2a32196496f4f05.pdf | bin | 548616 -> 0 bytes |
12 files changed, 269 insertions, 452 deletions
diff --git a/src/server/Client.ts b/src/server/Client.ts index 6b8841658..e6f953712 100644 --- a/src/server/Client.ts +++ b/src/server/Client.ts @@ -1,15 +1,11 @@ import { computed } from "mobx"; export class Client { - constructor(guid: string) { - this.guid = guid - } + private _guid: string; - private guid: string; - - @computed - public get GUID(): string { - return this.guid + constructor(guid: string) { + this._guid = guid; } + @computed public get GUID(): string { return this._guid; } }
\ No newline at end of file diff --git a/src/server/Message.ts b/src/server/Message.ts index 05ae0f19a..bbe4ffcad 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -1,125 +1,35 @@ import { Utils } from "../Utils"; export class Message<T> { - private name: string; - private guid: string; - - get Name(): string { - return this.name; - } - - get Message(): string { - return this.guid - } + private _name: string; + private _guid: string; constructor(name: string) { - this.name = name; - this.guid = Utils.GenerateDeterministicGuid(name) + this._name = name; + this._guid = Utils.GenerateDeterministicGuid(name); } - GetValue() { - return this.Name; - } -} - -class TestMessageArgs { - hello: string = ""; -} - -export class SetFieldArgs { - field: string; - value: any; - - constructor(f: string, v: any) { - this.field = f - this.value = v - } -} - -export class GetFieldArgs { - field: string; - - constructor(f: string) { - this.field = f - } + get Name(): string { return this._name; } + get Message(): string { return this._guid; } } export enum Types { - Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html, Video, Audio, Ink, PDF, Tuple, HistogramOp -} - -export class DocumentTransfer implements Transferable { - readonly type = Types.Document - _id: string - - constructor(readonly obj: { type: Types, data: [string, string][], _id: string }) { - this._id = obj._id - } -} - -export class ImageTransfer implements Transferable { - readonly type = Types.Image - - constructor(readonly _id: string) { } -} - -export class KeyTransfer implements Transferable { - name: string - readonly _id: string - readonly type = Types.Key - - constructor(i: string, n: string) { - this.name = n - this._id = i - } -} - -export class ListTransfer implements Transferable { - type = Types.List; - - constructor(readonly _id: string) { } -} - -export class NumberTransfer implements Transferable { - readonly type = Types.Number - - constructor(readonly value: number, readonly _id: string) { } -} - -export class TextTransfer implements Transferable { - value: string - readonly _id: string - readonly type = Types.Text - - constructor(t: string, i: string) { - this.value = t - this._id = i - } -} - -export class RichTextTransfer implements Transferable { - value: string - readonly _id: string - readonly type = Types.Text - - constructor(t: string, i: string) { - this.value = t - this._id = i - } + Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, + Html, Video, Audio, Ink, PDF, Tuple, HistogramOp, Boolean, Script, } export interface Transferable { - readonly _id: string - readonly type: Types + readonly id: string; + readonly type: Types; + readonly data?: any; } export namespace MessageStore { export const Foo = new Message<string>("Foo"); export const Bar = new Message<string>("Bar"); - export const AddDocument = new Message<DocumentTransfer>("Add Document"); - export const SetField = new Message<{ _id: string, data: any, type: Types }>("Set Field") - export const GetField = new Message<string>("Get Field") - export const GetFields = new Message<string[]>("Get Fields") + export const SetField = new Message<Transferable>("Set Field"); // send Transferable (no reply) + export const GetField = new Message<string>("Get Field"); // send string 'id' get Transferable back + export const GetFields = new Message<string[]>("Get Fields"); // send string[] of 'id' get Transferable[] back export const GetDocument = new Message<string>("Get Document"); export const DeleteAll = new Message<any>("Delete All"); -}
\ No newline at end of file +} diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts index 98a7a1451..818230c1a 100644 --- a/src/server/ServerUtil.ts +++ b/src/server/ServerUtil.ts @@ -1,78 +1,60 @@ - -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 { TupleField } from '../fields/TupleField'; -import { HistogramField } from '../client/northstar/dash-fields/HistogramField'; - - +import { HistogramField } from "../client/northstar/dash-fields/HistogramField"; +import { AudioField } from "../fields/AudioField"; +import { BooleanField } from "../fields/BooleanField"; +import { HtmlField } from "../fields/HtmlField"; +import { InkField } from "../fields/InkField"; +import { PDFField } from "../fields/PDFField"; +import { ScriptField } from "../fields/ScriptField"; +import { TupleField } from "../fields/TupleField"; +import { VideoField } from "../fields/VideoField"; +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 { Transferable, Types } from "./Message"; export class ServerUtils { - public static prepend(extension: string): string { return window.location.origin + extension; } + public static prepend(extension: string): string { + return window.location.origin + extension; + } - public static FromJson(json: any): Field { - let obj = json - let data: any = obj.data - let id: string = obj._id - let type: Types = obj.type + public static FromJson(json: Transferable): Field { - if (!(data !== undefined && id && type !== undefined)) { - console.log("how did you manage to get an object that doesn't have a data or an id?") + if (!(json.data !== undefined && json.id && json.type !== undefined)) { + console.log( + "how did you manage to get an object that doesn't have a data or an id?" + ); return new TextField("Something to fill the space", Utils.GenerateGuid()); } - switch (type) { - case Types.Number: - return new NumberField(data, id, false) - case Types.Text: - return new TextField(data, id, false) - case Types.Html: - return new HtmlField(data, id, false) - case Types.Web: - return new WebField(new URL(data), id, false) - case Types.RichText: - return new RichTextField(data, id, false) - case Types.Key: - return new Key(data, id, false) - case Types.Image: - return new ImageField(new URL(data), id, false) - case Types.HistogramOp: - return HistogramField.FromJson(id, data); - case Types.PDF: - 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.Tuple: - return new TupleField(data, id, false); - case Types.Ink: - return InkField.FromJson(id, data); - case Types.Document: - let doc: Document = new Document(id, false) - let fields: [string, string][] = data as [string, string][] - fields.forEach(element => { - doc._proxies.set(element[0], element[1]); - }); - return doc + switch (json.type) { + case Types.Boolean: return new BooleanField(json.data, json.id, false); + case Types.Number: return new NumberField(json.data, json.id, false); + case Types.Text: return new TextField(json.data, json.id, false); + case Types.Html: return new HtmlField(json.data, json.id, false); + case Types.Web: return new WebField(new URL(json.data), json.id, false); + case Types.RichText: return new RichTextField(json.data, json.id, false); + case Types.Key: return new Key(json.data, json.id, false); + case Types.Image: return new ImageField(new URL(json.data), json.id, false); + case Types.HistogramOp: return HistogramField.FromJson(json.id, json.data); + case Types.PDF: return new PDFField(new URL(json.data), json.id, false); + case Types.List: return ListField.FromJson(json.id, json.data); + case Types.Script: return ScriptField.FromJson(json.id, json.data); + case Types.Audio: return new AudioField(new URL(json.data), json.id, false); + case Types.Video: return new VideoField(new URL(json.data), json.id, false); + case Types.Tuple: return new TupleField(json.data, json.id, false); + case Types.Ink: return InkField.FromJson(json.id, json.data); + case Types.Document: return Document.FromJson(json.data, json.id, false); default: - throw Error("Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here"); + throw Error( + "Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here" + ); } } -}
\ No newline at end of file +} diff --git a/src/server/authentication/config/passport.ts b/src/server/authentication/config/passport.ts index b6fe15655..d42741410 100644 --- a/src/server/authentication/config/passport.ts +++ b/src/server/authentication/config/passport.ts @@ -1,4 +1,4 @@ -import * as passport from 'passport' +import * as passport from 'passport'; import * as passportLocal from 'passport-local'; import * as mongodb from 'mongodb'; import * as _ from "lodash"; @@ -22,7 +22,7 @@ passport.deserializeUser<any, any>((id, done) => { passport.use(new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => { User.findOne({ email: email.toLowerCase() }, (error: any, user: any) => { if (error) return done(error); - if (!user) return done(undefined, false, { message: "Invalid email or password" }) // invalid email + if (!user) return done(undefined, false, { message: "Invalid email or password" }); // invalid email user.comparePassword(password, (error: Error, isMatch: boolean) => { if (error) return done(error); if (!isMatch) return done(undefined, false, { message: "Invalid email or password" }); // invalid password @@ -37,7 +37,7 @@ export let isAuthenticated = (req: Request, res: Response, next: NextFunction) = return next(); } return res.redirect(RouteStore.login); -} +}; export let isAuthorized = (req: Request, res: Response, next: NextFunction) => { const provider = req.path.split("/").slice(-1)[0]; diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx index 8e14cf98e..b08c1aebe 100644 --- a/src/server/authentication/controllers/WorkspacesMenu.tsx +++ b/src/server/authentication/controllers/WorkspacesMenu.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { observable, action, configure, reaction, computed, ObservableMap, runInAction } from 'mobx'; import { observer } from "mobx-react"; -import './WorkspacesMenu.css' +import './WorkspacesMenu.css'; import { Document } from '../../../fields/Document'; import { EditableView } from '../../../client/views/EditableView'; import { KeyStore } from '../../../fields/KeyStore'; @@ -73,7 +73,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> { <span>{i + 1} - </span> <EditableView display={"inline"} - GetValue={() => { return s.Title }} + GetValue={() => s.Title} SetValue={(title: string): boolean => { s.SetText(KeyStore.Title, title); return true; diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts index e365b8dce..1dacdf3fa 100644 --- a/src/server/authentication/controllers/user_controller.ts +++ b/src/server/authentication/controllers/user_controller.ts @@ -4,7 +4,7 @@ import * as passport from "passport"; import { IVerifyOptions } from "passport-local"; import "../config/passport"; import * as request from "express-validator"; -const flash = require("express-flash"); +import flash = require("express-flash"); import * as session from "express-session"; import * as pug from 'pug'; import * as async from 'async'; @@ -109,12 +109,12 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => { } passport.authenticate("local", (err: Error, user: DashUserModel, info: IVerifyOptions) => { - if (err) { return next(err); } + if (err) { next(err); return; } if (!user) { return res.redirect(RouteStore.signup); } req.logIn(user, (err) => { - if (err) { return next(err); } + if (err) { next(err); return; } res.redirect(RouteStore.home); }); })(req, res, next); @@ -132,14 +132,14 @@ export let getLogout = (req: Request, res: Response) => { sess.destroy((err) => { if (err) { console.log(err); } }); } res.redirect(RouteStore.login); -} +}; export let getForgot = function (req: Request, res: Response) { res.render("forgot.pug", { title: "Recover Password", user: req.user, }); -} +}; export let postForgot = function (req: Request, res: Response, next: NextFunction) { const email = req.body.email; @@ -152,13 +152,14 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio return; } done(null, buffer.toString('hex')); - }) + }); }, function (token: string, done: any) { User.findOne({ email }, function (err, user: DashUserModel) { if (!user) { // NO ACCOUNT WITH SUBMITTED EMAIL - return res.redirect(RouteStore.forgot); + res.redirect(RouteStore.forgot); + return; } user.passwordResetToken = token; user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 HOUR @@ -192,8 +193,8 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio ], function (err) { if (err) return next(err); 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) { @@ -205,7 +206,7 @@ export let getReset = function (req: Request, res: Response) { user: req.user, }); }); -} +}; export let postReset = function (req: Request, res: Response) { async.waterfall([ @@ -228,7 +229,8 @@ export let postReset = function (req: Request, res: Response) { user.save(function (err) { if (err) { - return res.redirect(RouteStore.login); + res.redirect(RouteStore.login); + return; } req.logIn(user, function (err) { if (err) { @@ -261,4 +263,4 @@ export let postReset = function (req: Request, res: Response) { ], function (err) { res.redirect(RouteStore.login); }); -}
\ No newline at end of file +};
\ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 0ac85b446..5d4479c88 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,102 +1,75 @@ -import { DashUserModel } from "./user_model"; +import { computed, observable, action, runInAction } from "mobx"; import * as rp from 'request-promise'; -import { RouteStore } from "../../RouteStore"; -import { ServerUtils } from "../../ServerUtil"; +import { Documents } from "../../../client/documents/Documents"; +import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea"; +import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil"; import { Server } from "../../../client/Server"; import { Document } from "../../../fields/Document"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; -import { Documents } from "../../../client/documents/Documents"; -import { Schema, Attribute, AttributeGroup, Catalog } from "../../../client/northstar/model/idea/idea"; -import { observable, computed, action } from "mobx"; -import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil"; +import { RouteStore } from "../../RouteStore"; +import { ServerUtils } from "../../ServerUtil"; export class CurrentUserUtils { private static curr_email: string; private static curr_id: string; - private static user_document: Document; + @observable private static user_document: Document; //TODO tfs: these should be temporary... private static mainDocId: string | undefined; - @observable private static catalog?: Catalog; - - public static get email(): string { - return this.curr_email; - } - - public static get id(): string { - return this.curr_id; - } - - public static get UserDocument(): Document { - return this.user_document; - } - public static get MainDocId(): string | undefined { - return this.mainDocId; - } - - public static set MainDocId(id: string | undefined) { - this.mainDocId = id; - } - - @computed public static get NorthstarDBCatalog(): Catalog | undefined { - return this.catalog; - } - public static set NorthstarDBCatalog(ctlog: Catalog | undefined) { - this.catalog = ctlog; - } - public static GetNorthstarSchema(name: string): Schema | undefined { - return !this.catalog || !this.catalog.schemas ? undefined : - ArrayUtil.FirstOrDefault<Schema>(this.catalog.schemas, (s: Schema) => s.displayName === name); - } - public static GetAllNorthstarColumnAttributes(schema: Schema) { - if (!schema || !schema.rootAttributeGroup) { - return []; - } - const recurs = (attrs: Attribute[], g: AttributeGroup) => { - if (g.attributes) { - attrs.push.apply(attrs, g.attributes); - if (g.attributeGroups) { - g.attributeGroups.forEach(ng => recurs(attrs, ng)); - } - } - }; - const allAttributes: Attribute[] = new Array<Attribute>(); - recurs(allAttributes, schema.rootAttributeGroup); - return allAttributes; - } + public static get email() { return this.curr_email; } + public static get id() { return this.curr_id; } + @computed public static get UserDocument() { return this.user_document; } + public static get MainDocId() { return this.mainDocId; } + public static set MainDocId(id: string | undefined) { this.mainDocId = id; } private static createUserDocument(id: string): Document { let doc = new Document(id); - doc.Set(KeyStore.Workspaces, new ListField<Document>()); - doc.Set(KeyStore.OptionalRightCollection, Documents.SchemaDocument([], { title: "Pending documents" })) + doc.Set(KeyStore.OptionalRightCollection, Documents.SchemaDocument([], { title: "Pending documents" })); return doc; } public static loadCurrentUser(): Promise<any> { - let userPromise = rp.get(ServerUtils.prepend(RouteStore.getCurrUser)).then((response) => { + let userPromise = rp.get(ServerUtils.prepend(RouteStore.getCurrUser)).then(response => { if (response) { let obj = JSON.parse(response); CurrentUserUtils.curr_id = obj.id as string; CurrentUserUtils.curr_email = obj.email as string; } else { - throw new Error("There should be a user! Why does Dash think there isn't one?") + throw new Error("There should be a user! Why does Dash think there isn't one?"); } }); let userDocPromise = rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(id => { if (id) { - return Server.GetField(id).then(field => { - if (field instanceof Document) { - this.user_document = field; - } else { - this.user_document = this.createUserDocument(id); - } - }) + return Server.GetField(id).then(field => + runInAction(() => this.user_document = field instanceof Document ? field : this.createUserDocument(id))); } else { - throw new Error("There should be a user id! Why does Dash think there isn't one?") + throw new Error("There should be a user id! Why does Dash think there isn't one?"); } }); return Promise.all([userPromise, userDocPromise]); } + + /* Northstar catalog ... really just for testing so this should eventually go away */ + @observable private static _northstarCatalog?: Catalog; + @computed public static get NorthstarDBCatalog() { return this._northstarCatalog; } + public static set NorthstarDBCatalog(ctlog: Catalog | undefined) { this._northstarCatalog = ctlog; } + + public static GetNorthstarSchema(name: string): Schema | undefined { + return !this._northstarCatalog || !this._northstarCatalog.schemas ? undefined : + ArrayUtil.FirstOrDefault<Schema>(this._northstarCatalog.schemas, (s: Schema) => s.displayName === name); + } + public static GetAllNorthstarColumnAttributes(schema: Schema) { + const recurs = (attrs: Attribute[], g?: AttributeGroup) => { + if (g && g.attributes) { + attrs.push.apply(attrs, g.attributes); + if (g.attributeGroups) { + g.attributeGroups.forEach(ng => recurs(attrs, ng)); + } + } + return attrs; + }; + return recurs([] as Attribute[], schema ? schema.rootAttributeGroup : undefined); + } }
\ 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 81580aad5..d5c84c311 100644 --- a/src/server/authentication/models/user_model.ts +++ b/src/server/authentication/models/user_model.ts @@ -2,7 +2,7 @@ import * as bcrypt from "bcrypt-nodejs"; //@ts-ignore import * as mongoose from "mongoose"; -var url = 'mongodb://localhost:27017/Dash' +var url = 'mongodb://localhost:27017/Dash'; mongoose.connect(url, { useNewUrlParser: true }); @@ -18,8 +18,8 @@ mongoose.connection.on('disconnected', function () { export type DashUserModel = mongoose.Document & { email: string, password: string, - passwordResetToken: string | undefined, - passwordResetExpires: Date | undefined, + passwordResetToken?: string, + passwordResetExpires?: Date, userDocumentId: string; @@ -67,11 +67,17 @@ const userSchema = new mongoose.Schema({ */ userSchema.pre("save", function save(next) { const user = this as DashUserModel; - if (!user.isModified("password")) { return next(); } + if (!user.isModified("password")) { + return next(); + } bcrypt.genSalt(10, (err, salt) => { - if (err) { return next(err); } + if (err) { + return next(err); + } bcrypt.hash(user.password, salt, () => void {}, (err: mongoose.Error, hash) => { - if (err) { return next(err); } + if (err) { + return next(err); + } user.password = hash; next(); }); @@ -79,9 +85,8 @@ userSchema.pre("save", function save(next) { }); const comparePassword: comparePasswordFunction = function (this: DashUserModel, candidatePassword, cb) { - bcrypt.compare(candidatePassword, this.password, (err: mongoose.Error, isMatch: boolean) => { - cb(err, isMatch); - }); + bcrypt.compare(candidatePassword, this.password, (err: mongoose.Error, isMatch: boolean) => + cb(err, isMatch)); }; userSchema.methods.comparePassword = comparePassword; diff --git a/src/server/database.ts b/src/server/database.ts index a42d29aac..7914febf8 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -1,96 +1,78 @@ -import { action, configure } from 'mobx'; import * as mongodb from 'mongodb'; -import { ObjectID } from 'mongodb'; import { Transferable } from './Message'; -import { Utils } from '../Utils'; export class Database { - public static Instance = new Database() + public static DocumentsCollection = 'documents'; + public static Instance = new Database(); private MongoClient = mongodb.MongoClient; private url = 'mongodb://localhost:27017/Dash'; + private currentWrites: { [id: string]: Promise<void> } = {}; private db?: mongodb.Db; constructor() { - this.MongoClient.connect(this.url, (err, client) => { - this.db = client.db() - }) + this.MongoClient.connect(this.url, (err, client) => this.db = client.db()); } public update(id: string, value: any, callback: () => void) { if (this.db) { let collection = this.db.collection('documents'); - collection.updateOne({ _id: id }, { $set: value }, { - upsert: true - }, (err, res) => { - if (err) { - console.log(err.message); - console.log(err.errmsg); - } - if (res) { - console.log(JSON.stringify(res.result)); - } - callback() - }); + const prom = this.currentWrites[id]; + let newProm: Promise<void>; + const run = (): Promise<void> => { + return new Promise<void>(resolve => { + collection.updateOne({ _id: id }, { $set: value }, { upsert: true } + , (err, res) => { + if (err) { + console.log(err.message); + console.log(err.errmsg); + } + // if (res) { + // console.log(JSON.stringify(res.result)); + // } + if (this.currentWrites[id] === newProm) { + delete this.currentWrites[id]; + } + resolve(); + callback(); + }); + }); + }; + newProm = prom ? prom.then(run) : run(); + this.currentWrites[id] = newProm; } } - public delete(id: string) { - if (this.db) { - let collection = this.db.collection('documents'); - collection.remove({ _id: id }); - } + public delete(id: string, collectionName = Database.DocumentsCollection) { + this.db && this.db.collection(collectionName).remove({ id: id }); } - public deleteAll(collectionName: string = 'documents'): Promise<any> { - return new Promise(res => { - if (this.db) { - let collection = this.db.collection(collectionName); - collection.deleteMany({}, res); - } - }) + public deleteAll(collectionName = Database.DocumentsCollection): Promise<any> { + return new Promise(res => + this.db && this.db.collection(collectionName).deleteMany({}, res)); } - public insert(kvpairs: any) { - if (this.db) { - let collection = this.db.collection('documents'); - collection.insertOne(kvpairs, (err: any, res: any) => { - if (err) { - // console.log(err) - return - } - }); - } + public insert(kvpairs: any, collectionName = Database.DocumentsCollection) { + this.db && this.db.collection(collectionName).insertOne(kvpairs, (err, res) => + err // && console.log(err) + ); } - public getDocument(id: string, fn: (res: any) => void) { - var result: JSON; - if (this.db) { - let collection = this.db.collection('documents'); - collection.findOne({ _id: id }, (err: any, res: any) => { - result = res - if (!result) { - fn(undefined) - } - fn(result) - }) - }; + public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = Database.DocumentsCollection) { + this.db && this.db.collection(collectionName).findOne({ id: id }, (err, result) => + fn(result ? ({ id: result._id, type: result.type, data: result.data }) : undefined)) } - public getDocuments(ids: string[], fn: (res: any) => void) { - if (this.db) { - let collection = this.db.collection('documents'); - let cursor = collection.find({ _id: { "$in": ids } }) - cursor.toArray((err, docs) => { - if (err) { - console.log(err.message); - console.log(err.errmsg); - } - fn(docs); - }) - }; + public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = Database.DocumentsCollection) { + this.db && this.db.collection(collectionName).find({ id: { "$in": ids } }).toArray((err, docs) => { + if (err) { + console.log(err.message); + console.log(err.errmsg); + } + fn(docs.map(doc => ({ id: doc._id, type: doc.type, data: doc.data }))); + }); } public print() { - console.log("db says hi!") + console.log("db says hi!"); } } diff --git a/src/server/index.ts b/src/server/index.ts index 17d7432e0..3cbe1ca76 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,49 +1,45 @@ -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 bodyParser from 'body-parser'; +import { exec } from 'child_process'; +import * as cookieParser from 'cookie-parser'; +import * as express from 'express'; +import * as session from 'express-session'; +import * as expressValidator from 'express-validator'; +import * as formidable from 'formidable'; +import * as fs from 'fs'; +import * as mobileDetect from 'mobile-detect'; +import { ObservableMap } from 'mobx'; import * as passport from 'passport'; -import { MessageStore, Transferable } from "./Message"; -import { Client } from './Client'; +import * as path from 'path'; +import * as request from 'request'; +import * as io from 'socket.io'; import { Socket } from 'socket.io'; +import * as webpack from 'webpack'; +import * as wdm from 'webpack-dev-middleware'; +import * as whm from 'webpack-hot-middleware'; +import { Field, FieldId } from '../fields/Field'; import { Utils } from '../Utils'; -import { ObservableMap } from 'mobx'; -import { FieldId, Field } from '../fields/Field'; +import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/controllers/user_controller'; +import { DashUserModel } from './authentication/models/user_model'; +import { Client } from './Client'; 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'; +import { MessageStore, Transferable } from "./Message"; +import { RouteStore } from './RouteStore'; +const app = express(); 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 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"); -}) +mongoose.connect(mongoUrl); +mongoose.connection.on('connected', () => console.log("connected")); // SESSION MANAGEMENT AND AUTHENTICATION MIDDLEWARE // ORDER OF IMPORTS MATTERS @@ -54,9 +50,7 @@ app.use(session({ resave: true, cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 }, saveUninitialized: true, - store: new MongoStore({ - url: 'mongodb://localhost:27017/Dash' - }) + store: new MongoStore({ url: 'mongodb://localhost:27017/Dash' }) })); app.use(flash()); @@ -71,9 +65,7 @@ app.use((req, res, next) => { next(); }); -app.get("/hello", (req, res) => { - res.send("<p>Hello</p>"); -}) +app.get("/hello", (req, res) => res.send("<p>Hello</p>")); enum Method { GET, @@ -95,10 +87,12 @@ function addSecureRoute(method: Method, ...subscribers: string[] ) { let abstracted = (req: express.Request, res: express.Response) => { - const dashUser: DashUserModel = req.user; - if (!dashUser) return onRejection(res); - handler(dashUser, res, req); - } + if (req.user) { + handler(req.user, res, req); + } else { + onRejection(res); + } + }; subscribers.forEach(route => { switch (method) { case Method.GET: @@ -112,21 +106,17 @@ function addSecureRoute(method: Method, } // STATIC FILE SERVING - -let FieldStore: ObservableMap<FieldId, Field> = new ObservableMap(); - app.use(express.static(__dirname + RouteStore.public)); -app.use(RouteStore.images, express.static(__dirname + RouteStore.public)) +app.use(RouteStore.images, express.static(__dirname + RouteStore.public)); -app.get("/pull", (req, res) => { +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 @@ -143,11 +133,8 @@ 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')); - } + let filename = detector.mobile() !== null ? 'mobile/image.html' : 'index.html'; + res.sendFile(path.join(__dirname, '../../deploy/' + filename)); }, undefined, RouteStore.home, @@ -163,12 +150,7 @@ addSecureRoute( addSecureRoute( Method.GET, - (user, res) => { - res.send(JSON.stringify({ - id: user.id, - email: user.email - })); - }, + (user, res) => res.send(JSON.stringify({ id: user.id, email: user.email })), undefined, RouteStore.getCurrUser ); @@ -178,17 +160,16 @@ addSecureRoute( addSecureRoute( Method.POST, (user, res, req) => { - let form = new formidable.IncomingForm() - form.uploadDir = __dirname + "/public/files/" - form.keepExtensions = true + let form = new formidable.IncomingForm(); + form.uploadDir = __dirname + "/public/files/"; + form.keepExtensions = true; // let path = req.body.path; - console.log("upload") + console.log("upload"); form.parse(req, (err, fields, files) => { - console.log("parsing") - let names: any[] = []; + console.log("parsing"); + let names: string[] = []; for (const name in files) { - let file = files[name]; - names.push(`/files/` + path.basename(file.path)); + names.push(`/files/` + path.basename(files[name].path)); } res.send(names); }); @@ -211,89 +192,74 @@ app.post(RouteStore.login, postLogin); app.get(RouteStore.logout, getLogout); // FORGOT PASSWORD EMAIL HANDLING -app.get(RouteStore.forgot, getForgot) -app.post(RouteStore.forgot, postForgot) +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.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.delete, (req, res) => + deleteFields().then(() => res.redirect(RouteStore.home))); -app.get(RouteStore.deleteAll, (req, res) => { - deleteAll().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(wdm(compiler, { publicPath: config.output.publicPath })); -app.use(whm(compiler)) +app.use(whm(compiler)); // start the Express server -app.listen(port, () => { - console.log(`server started at http://localhost:${port}`); -}) +app.listen(port, () => + console.log(`server started at http://localhost:${port}`)); const server = io(); interface Map { [key: string]: Client; } -let clients: Map = {} +let clients: Map = {}; server.on("connection", function (socket: Socket) { - console.log("a user has connected") + console.log("a user has connected"); - Utils.Emit(socket, MessageStore.Foo, "handshooken") + 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) -}) + 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') - }); +async function deleteAll() { + await Database.Instance.deleteAll(); + await Database.Instance.deleteAll('sessions'); + await 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 getField([id, callback]: [string, (result?: Transferable) => void]) { + Database.Instance.getDocument(id, (result?: Transferable) => + callback(result ? result : undefined)); } -function getFields([ids, callback]: [string[], (result: any) => void]) { +function getFields([ids, callback]: [string[], (result: Transferable[]) => 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); - }) + Database.Instance.update(newValue.id, newValue, () => + socket.broadcast.emit(MessageStore.SetField.Message, newValue)); } server.listen(serverPort); diff --git a/src/server/public/files/.gitignore b/src/server/public/files/.gitignore new file mode 100644 index 000000000..f59ec20aa --- /dev/null +++ b/src/server/public/files/.gitignore @@ -0,0 +1 @@ +*
\ No newline at end of file diff --git a/src/server/public/files/upload_e72669595eae4384a2a32196496f4f05.pdf b/src/server/public/files/upload_e72669595eae4384a2a32196496f4f05.pdf Binary files differdeleted file mode 100644 index 8e58bfddd..000000000 --- a/src/server/public/files/upload_e72669595eae4384a2a32196496f4f05.pdf +++ /dev/null |
