From ff25c29c6801b1858ce6cd15a5735dba1fc67e8c Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 14 Feb 2019 00:22:11 -0500 Subject: initial signup / login implementation --- src/server/authentication/controllers/user.ts | 107 ++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/server/authentication/controllers/user.ts (limited to 'src/server/authentication/controllers/user.ts') diff --git a/src/server/authentication/controllers/user.ts b/src/server/authentication/controllers/user.ts new file mode 100644 index 000000000..590224fb0 --- /dev/null +++ b/src/server/authentication/controllers/user.ts @@ -0,0 +1,107 @@ +import { default as User, UserModel, AuthToken } from "../models/User"; +import { Request, Response, NextFunction } from "express"; +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 * as session from "express-session"; +import * as pug from 'pug'; + +/** + * GET /signup + * Signup page. + */ +export let getSignup = (req: Request, res: Response) => { + if (req.user) { + return res.redirect("/"); + } + res.render("signup.pug", { + title: "Create Account" + }); +}; + +/** + * POST /signup + * Create a new local account. + */ +export let postSignup = (req: Request, res: Response, next: NextFunction) => { + req.assert("email", "Email is not valid").isEmail(); + req.assert("password", "Password must be at least 4 characters long").len({ min: 4 }); + req.assert("confirmPassword", "Passwords do not match").equals(req.body.password); + req.sanitize("email").normalizeEmail({ gmail_remove_dots: false }); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", "Unable to facilitate sign up. Please try again."); + return res.redirect("/signup"); + } + + const user = new User({ + email: req.body.email, + password: req.body.password + }); + + User.findOne({ email: req.body.email }, (err, existingUser) => { + if (err) { return next(err); } + if (existingUser) { + req.flash("errors", "Account with that email address already exists."); + return res.redirect("/signup"); + } + user.save((err) => { + if (err) { return next(err); } + req.logIn(user, (err) => { + if (err) { + return next(err); + } + res.redirect("/"); + }); + }); + }); +}; + + +/** + * GET /login + * Login page. + */ +export let getLogin = (req: Request, res: Response) => { + if (req.user) { + return res.redirect("/"); + } + res.send("

dear lord please render

"); + // res.render("account/login", { + // title: "Login" + // }); +}; + +/** + * POST /login + * Sign in using email and password. + */ +export let postLogin = (req: Request, res: Response, next: NextFunction) => { + req.assert("email", "Email is not valid").isEmail(); + req.assert("password", "Password cannot be blank").notEmpty(); + req.sanitize("email").normalizeEmail({ gmail_remove_dots: false }); + + const errors = req.validationErrors(); + + if (errors) { + req.flash("errors", "Unable to login at this time. Please try again."); + return res.redirect("/login"); + } + + passport.authenticate("local", (err: Error, user: UserModel, info: IVerifyOptions) => { + if (err) { return next(err); } + if (!user) { + req.flash("errors", info.message); + return res.redirect("/login"); + } + req.logIn(user, (err) => { + if (err) { return next(err); } + req.flash("success", "Success! You are logged in."); + res.redirect("/"); + }); + })(req, res, next); +}; \ No newline at end of file -- cgit v1.2.3-70-g09d2 From ddd503f21dc4b3368d80b4be475817cd9a13fcd1 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 14 Feb 2019 02:47:28 -0500 Subject: getting there? --- .vscode/launch.json | 10 ++++ package-lock.json | 79 +++++++++++++++++++++++++- package.json | 3 + src/server/authentication/controllers/user.ts | 2 +- src/server/authentication/models/User.ts | 15 ++++- src/server/index.ts | 81 +++++++++++++++++---------- views/layout.pug | 2 +- 7 files changed, 157 insertions(+), 35 deletions(-) (limited to 'src/server/authentication/controllers/user.ts') diff --git a/.vscode/launch.json b/.vscode/launch.json index 9a0a9afb4..6819ffbf2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -47,5 +47,15 @@ "internalConsoleOptions": "openOnSessionStart", "protocol": "inspector" }, + { + "type": "node", + "request": "launch", + "name": "Launch via NPM", + "runtimeExecutable": "npm", + "runtimeArgs": [ + "start" + ], + "port": 9229 + } ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c983bbf7c..37d7cde0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,11 @@ "resolved": "https://registry.npmjs.org/@types/bcrypt-nodejs/-/bcrypt-nodejs-0.0.30.tgz", "integrity": "sha1-TN2WtJKTs5MhIuS34pVD415rrlg=" }, + "@types/bluebird": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.25.tgz", + "integrity": "sha512-yfhIBix+AIFTmYGtkC0Bi+XGjSkOINykqKvO/Wqdz/DuXlAKK7HmhLAXdPIGsV4xzKcL3ev/zYc4yLNo+OvGaw==" + }, "@types/body-parser": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", @@ -1168,8 +1173,7 @@ "bluebird": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", - "dev": true + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" }, "bn.js": { "version": "4.11.8", @@ -1442,6 +1446,11 @@ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", "dev": true }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -1819,6 +1828,67 @@ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", "dev": true }, + "connect-mongo": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-2.0.3.tgz", + "integrity": "sha512-Vs+QZ/6X6gbCrP1Ls7Oh/wlyY6pgpbPSrUKF5yRT+zd+4GZPNbjNquxquZ+Clv2+03HBXE7T4lVM0PUcaBhihg==", + "requires": { + "mongodb": "^2.0.36" + }, + "dependencies": { + "bson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" + }, + "mongodb": { + "version": "2.2.36", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", + "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.20", + "readable-stream": "2.2.7" + } + }, + "mongodb-core": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", + "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", + "requires": { + "bson": "~1.0.4", + "require_optional": "~1.0.0" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -2557,6 +2627,11 @@ "es6-symbol": "^3.1.1" } }, + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" + }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", diff --git a/package.json b/package.json index 1342fe62e..3a245cfd0 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.14", "@types/bcrypt-nodejs": "0.0.30", + "@types/bluebird": "^3.5.25", "@types/body-parser": "^1.17.0", "@types/express": "^4.16.1", "@types/express-flash": "0.0.0", @@ -63,7 +64,9 @@ "@types/uuid": "^3.4.4", "@types/webpack": "^4.4.24", "bcrypt-nodejs": "0.0.3", + "bluebird": "^3.5.3", "body-parser": "^1.18.3", + "connect-mongo": "^2.0.3", "express": "^4.16.4", "express-flash": "0.0.2", "express-session": "^1.15.6", diff --git a/src/server/authentication/controllers/user.ts b/src/server/authentication/controllers/user.ts index 590224fb0..f74ff9039 100644 --- a/src/server/authentication/controllers/user.ts +++ b/src/server/authentication/controllers/user.ts @@ -17,7 +17,7 @@ export let getSignup = (req: Request, res: Response) => { return res.redirect("/"); } res.render("signup.pug", { - title: "Create Account" + title: "Sign Up" }); }; diff --git a/src/server/authentication/models/User.ts b/src/server/authentication/models/User.ts index 9f58d317d..9752c4260 100644 --- a/src/server/authentication/models/User.ts +++ b/src/server/authentication/models/User.ts @@ -1,7 +1,21 @@ +//@ts-ignore import * as bcrypt from "bcrypt-nodejs"; import * as crypto from "crypto"; +//@ts-ignore import * as mongoose from "mongoose"; +var url = 'mongodb://localhost:27017/Dash' +mongoose.connect(url, { useNewUrlParser: true }); + +mongoose.connection.on('connected', function () { + console.log('Stablished connection on ' + url); +}); +mongoose.connection.on('error', function (error) { + console.log('Something wrong happened: ' + error); +}); +mongoose.connection.on('disconnected', function () { + console.log('connection closed'); +}); export type UserModel = mongoose.Document & { email: string, password: string, @@ -18,7 +32,6 @@ export type UserModel = mongoose.Document & { }, comparePassword: comparePasswordFunction, - gravatar: (size: number) => string }; type comparePasswordFunction = (candidatePassword: string, cb: (err: any, isMatch: any) => {}) => void; diff --git a/src/server/index.ts b/src/server/index.ts index 416eaa009..b81cdbcca 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -11,7 +11,7 @@ import { Socket } from 'socket.io'; import { Utils } from '../Utils'; import { ObservableMap } from 'mobx'; import { FIELD_ID, Field } from '../fields/Field'; -import { Database } from './database'; +// import { Database } from './database'; import { ServerUtils } from './ServerUtil'; import * as passportConfig from './authentication/config/passport'; import { getLogin, postLogin, getSignup, postSignup } from './authentication/controllers/user'; @@ -19,15 +19,50 @@ const config = require('../../webpack.config'); const compiler = webpack(config); const port = 1050; // default port to listen const serverPort = 1234; -import expressValidator = require('express-validator'); +import * as expressValidator from 'express-validator'; import expressFlash = require('express-flash'); -import bodyParser = require('body-parser'); +import * as bodyParser from 'body-parser'; +import * as session from 'express-session'; import c = require("crypto"); +const MongoStore = require('connect-mongo')(session); +const mongoose = require('mongoose'); +const bluebird = require('bluebird'); + +const mongoUrl = 'mongodb://localhost:27017/Dash'; +// mongoose.Promise = bluebird; +mongoose.connect(mongoUrl)//.then( +// () => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ }, +// ).catch((err: any) => { +// console.log("MongoDB connection error. Please make sure MongoDB is running. " + err); +// process.exit(); +// }); +mongoose.connection.on('connected', function () { + console.log("connected"); +}) -app.use(bodyParser()); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })); app.use(expressValidator()); app.use(expressFlash()); -app.use(require('express-session')({ secret: `${c.randomBytes(64)}`, resave: true, saveUninitialized: true })); +app.use(require('express-session')({ + secret: `${c.randomBytes(64)}`, + resave: true, + saveUninitialized: true, + store: new MongoStore({ + url: 'mongodb://localhost:27017/Dash' + }) +})); +app.use(passport.initialize()); +app.use(passport.session()); +app.use((req, res, next) => { + res.locals.user = req.user; + next(); +}); + +app.get("/signup", getSignup); +app.post("/signup", postSignup); +app.get("/login", getLogin); +app.post("/login", postLogin); let FieldStore: ObservableMap = new ObservableMap(); @@ -69,7 +104,7 @@ server.on("connection", function (socket: Socket) { function barReceived(guid: String) { clients[guid.toString()] = new Client(guid.toString()); - Database.Instance.print() + // Database.Instance.print() } function addDocument(document: Document) { @@ -78,35 +113,21 @@ function addDocument(document: Document) { function setField(newValue: Transferable) { console.log(newValue._id) - if (Database.Instance.getDocument(newValue._id)) { - Database.Instance.update(newValue._id, newValue) - } - else { - Database.Instance.insert(newValue) - } + // if (Database.Instance.getDocument(newValue._id)) { + // Database.Instance.update(newValue._id, newValue) + // } + // else { + // Database.Instance.insert(newValue) + // } } function getField([fieldRequest, callback]: [GetFieldArgs, (field: Field) => void]) { let fieldId: string = fieldRequest.field - let result: string | undefined = Database.Instance.getDocument(fieldId) - if (result) { - let fromJson: Field = ServerUtils.FromJson(result) - } + // let result: string | undefined = Database.Instance.getDocument(fieldId) + // if (result) { + // let fromJson: Field = ServerUtils.FromJson(result) + // } } -// initialize passport -app.use(passport.initialize()); -app.use(passport.session()); - -app.use((req, res, next) => { - res.locals.user = req.user; - next(); -}); - -app.get("/signup", getSignup); -app.post("/signup", postSignup); -app.get("/login", getLogin); -app.post("/login", postLogin); - server.listen(serverPort); console.log(`listening on port ${serverPort}`); \ No newline at end of file diff --git a/views/layout.pug b/views/layout.pug index b45a6bd59..fb22ae770 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -4,7 +4,7 @@ html(lang='') meta(charset='utf-8') meta(http-equiv='X-UA-Compatible', content='IE=edge') meta(name='viewport', content='width=device-width, initial-scale=1.0') - title #{title} - Hackathon Starter + title #{title} - Dash meta(name='description', content='') meta(name='theme-color' content='#4DA5F4') meta(name='csrf-token', content=_csrf) -- cgit v1.2.3-70-g09d2