浏览代码

Core for authentication is done.

KrisVos130 8 年之前
父节点
当前提交
ee179f523a
共有 9 个文件被更改,包括 187 次插入57 次删除
  1. 2 4
      client/html/index.html
  2. 14 0
      client/html/login.html
  3. 18 0
      client/html/register.html
  4. 2 0
      package.json
  5. 0 1
      server/auth/auth-controller.js
  6. 69 11
      server/auth/auth-router.js
  7. 72 39
      server/auth/index.js
  8. 1 1
      server/db/index.js
  9. 9 1
      server/server.js

+ 2 - 4
client/html/index.html

@@ -8,8 +8,7 @@
 <h1>Musare!</h1>
 <h1>Musare!</h1>
 <h1>Passport/RethinkDB Example</h1>
 <h1>Passport/RethinkDB Example</h1>
 {{#user}}
 {{#user}}
-<img style='width: 100px; height: 100px;' src='{{ avatarUrl }}'>
-<p>You are logged in as <span style="font-weight: bold;">{{ login }}</span>. Account created through <span style="font-weight: bold;">{{ type }}</span>.</p>
+<p>You are logged in as <span style="font-weight: bold;">{{ username }}</span>. Account created through <span style="font-weight: bold;">{{ type }}</span>.</p>
 <a href='/auth/user'>See user data</a>
 <a href='/auth/user'>See user data</a>
 </br>
 </br>
 <a href='/auth/logout'>Logout</a>
 <a href='/auth/logout'>Logout</a>
@@ -17,12 +16,11 @@
 {{^user}}
 {{^user}}
 <p>You are not logged in.</p>
 <p>You are not logged in.</p>
 <a href='/auth/login/github'>Login with GitHub</a>
 <a href='/auth/login/github'>Login with GitHub</a>
-{{/user}}
-
 <form action="/auth/login">
 <form action="/auth/login">
     <input id="username" name="username" type="text">
     <input id="username" name="username" type="text">
     <input id="password" name="password" type="password">
     <input id="password" name="password" type="password">
     <button type="submit">Submit</button>
     <button type="submit">Submit</button>
 </form>
 </form>
+{{/user}}
 </body>
 </body>
 </html>
 </html>

+ 14 - 0
client/html/login.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Login</title>
+</head>
+<body>
+<form action="/auth/login">
+    <input id="username" name="username" type="text">
+    <input id="password" name="password" type="password">
+    <button type="submit">Submit</button>
+</form>
+</body>
+</html>

+ 18 - 0
client/html/register.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Register</title>
+</head>
+<body>
+<form action="/auth/register">
+    <label for="username">Username</label>
+    <input id="username" name="username" type="text">
+    <label for="email">Email</label>
+    <input id="email" name="email" type="text">
+    <label for="password">Password</label>
+    <input id="password" name="password" type="password">
+    <button type="submit">Submit</button>
+</form>
+</body>
+</html>

+ 2 - 0
package.json

@@ -9,9 +9,11 @@
   "author": "Musare",
   "author": "Musare",
   "license": "ISC",
   "license": "ISC",
   "dependencies": {
   "dependencies": {
+    "bcryptjs": "^2.3.0",
     "consolidate": "^0.14.1",
     "consolidate": "^0.14.1",
     "express": "^4.14.0",
     "express": "^4.14.0",
     "express-session": "^1.14.0",
     "express-session": "^1.14.0",
+    "express-validator": "^2.20.8",
     "mustache": "^2.2.1",
     "mustache": "^2.2.1",
     "node-sass": "^3.8.0",
     "node-sass": "^3.8.0",
     "passport": "^0.3.2",
     "passport": "^0.3.2",

+ 0 - 1
server/auth/auth-controller.js

@@ -1,6 +1,5 @@
 var authController = {};
 var authController = {};
 authController.getUser = function (req, res) {
 authController.getUser = function (req, res) {
-    console.log(req.user, 777);
     if (req.user && req.user.id) {
     if (req.user && req.user.id) {
         res.json(req.user);
         res.json(req.user);
         return;
         return;

+ 69 - 11
server/auth/auth-router.js

@@ -3,28 +3,86 @@ var authControllers = require('./auth-controller');
 
 
 var auth = require('./index');
 var auth = require('./index');
 var authRouter = express.Router();
 var authRouter = express.Router();
+var r = require('../db');
+
+var bcrypt = require('bcryptjs');
 
 
 // GitHub
 // GitHub
 authRouter.use('/login/callback/github', auth.authenticate('github'), function (req, res) {
 authRouter.use('/login/callback/github', auth.authenticate('github'), function (req, res) {
     res.redirect('/');
     res.redirect('/');
 });
 });
-authRouter.get('/login/github', auth.authenticate('github'));
+authRouter.get('/login/github', auth.authenticate('github', { scope: [ 'user:email' ] }));
 
 
 // Local
 // Local
-/*authRouter.post('/login', auth.authenticate('local', {successRedirect: '/user', failureRedirect: '/login'}), function(req, res) {
+authRouter.get('/login', auth.authenticate('local', {successRedirect: '/auth/user', failureRedirect: '/login'}), function(req, res) {
     // If this function gets called, authentication was successful.
     // If this function gets called, authentication was successful.
     // `req.user` contains the authenticated user.
     // `req.user` contains the authenticated user.
-    console.log(res.user.username, 111);
-    res.redirect('/user');
-});*/
-authRouter.get('/login', function(req, res, next) {
-    auth.authenticate('local', function(err, user, info) {
-        // If this gets called, authentication was successful
-        console.log(err, user, info, 333);
-        res.redirect("/auth/user");
-    })(req, res, next);
+    res.redirect("/auth/user");
 });
 });
 
 
+// Local
+authRouter.get('/register', function(req, res) {
+    req.checkQuery('email', 'Invalid email').isEmail();
+    req.checkQuery('username', 'Invalid getparam').notEmpty();
+    req.checkQuery('password', 'Invalid getparam').notEmpty();
+    var query = req.query;
+
+    var errors = req.validationErrors();
+    if (errors) {
+        res.send('There have been validation errors: ', 400);
+        return;
+    } else {
+        //TODO Check if username/email already exists
+        r.table("users").getAll(query.username.toLowerCase(), {index: "usernameL"}).isEmpty().run(r.conn, function(err, result) {
+            if (err) throw err;
+            if (result) {
+                r.table("users").getAll(query.email.toLowerCase(), {index: "email"}).isEmpty().run(r.conn, function(err, result) {
+                    if (err) throw err;
+                    if (result) {
+                        //TODO Hash password
+                        var hash;
+                        bcrypt.genSalt(10, function (err, salt) {
+                            if (err) {
+                                //TODO Throw error
+                            } else {
+                                bcrypt.hash(query.password, salt, function (err, hash) {
+                                    if (err) {
+                                        //TODO Throw error
+                                    } else {
+                                        var email = query.email.toLowerCase();
+                                        var usernameL = query.username.toLowerCase();
+                                        r.table('users')
+                                            .insert({
+                                                username: query.username,
+                                                usernameL: usernameL,
+                                                email: email,
+                                                type: 'local',
+                                                password: hash
+                                            })
+                                            .run(r.conn)
+                                            .then(function (response) {
+
+                                                return r.table('users')
+                                                    .get(response.generated_keys[0])
+                                                    .run(r.conn);
+                                            })
+                                            .then(function (newUser) {
+                                                //TODO Log in
+                                            });
+                                    }
+                                });
+                            }
+                        });
+                    } else {
+                        //TODO Throw error
+                    }
+                });
+            } else {
+                //TODO Throw error
+            }
+        });
+    }
+});
 
 
 // All
 // All
 authRouter.use('/user', authControllers.getUser);
 authRouter.use('/user', authControllers.getUser);

+ 72 - 39
server/auth/index.js

@@ -2,48 +2,96 @@ var passport = require('passport');
 var GitHubStrategy = require('passport-github').Strategy;
 var GitHubStrategy = require('passport-github').Strategy;
 var LocalStrategy = require('passport-local').Strategy;
 var LocalStrategy = require('passport-local').Strategy;
 var r = require('../db');
 var r = require('../db');
+var bcrypt = require('bcryptjs');
 
 
 passport.serializeUser(function (user, done) {
 passport.serializeUser(function (user, done) {
-    console.log(user, 555);
     return done(null, user.id);
     return done(null, user.id);
 });
 });
 
 
 passport.deserializeUser(function (id, done) {
 passport.deserializeUser(function (id, done) {
-    console.log(id, 444);
     r
     r
         .table('users')
         .table('users')
         .get(id)
         .get(id)
         .run(r.conn)
         .run(r.conn)
         .then(function (user) {
         .then(function (user) {
+            delete user.password;
             done(null, user);
             done(null, user);
         });
         });
 });
 });
 
 
 var loginCallbackHandler = function (objectMapper, type) {
 var loginCallbackHandler = function (objectMapper, type) {
-    return function (accessToken, refreshToken, profile, done) {
-        if (accessToken !== null) {
+    return function (arg1, arg2, arg3, arg4) {
+        /*
+        * If the type is github
+        * arg1 is the accessToken
+        * arg2 is the refresh token
+        * arg3 is profile object
+        * arg4 is done callback
+        *
+        * if the type is local
+        * arg1 is username
+        * arg2 is password
+        * arg3 is done callback
+        * */
+        var username, done;
+        if (type === "github") {
+            username = arg3.username;
+            done = arg4;
+        } else {
+            username = arg1;
+            done = arg3;
+        }
+
+        if (arg1 !== null) {
             r
             r
                 .table('users')
                 .table('users')
-                .getAll(profile.username, { index: 'login' })
-                .filter({ type: type })
+                .getAll(username.toLowerCase(), { index: 'usernameL' })
                 .run(r.conn)
                 .run(r.conn)
                 .then(function (cursor) {
                 .then(function (cursor) {
                     return cursor.toArray()
                     return cursor.toArray()
                         .then(function (users) {
                         .then(function (users) {
                             if (users.length > 0) {
                             if (users.length > 0) {
-                                return done(null, users[0]);
+                                var userType = users[0].type;
+                                if (userType === "github" && type === userType) {
+                                    return done(null, users[0]);
+                                } else if (userType === "local" && userType === type) {
+                                    var hash = users[0].password;
+                                    console.log("Checking password...");
+                                    bcrypt.compare(arg2, hash, function(err, isMatch) {
+                                        if (err || isMatch === false) {
+                                            //Incorrect password/error occured
+                                            //TODO Throw error
+                                        } else {
+                                            var user = users[0];
+                                            delete user.password;
+                                            return done(null, user);
+                                        }
+                                    });
+                                } else {
+                                    // If this gets called, a user tried to sign in with a GitHub account even though a normal account with that username already exists, or the other way around
+                                    if (userType === "local") {
+                                        return done(null, false, {message: "This account has been registered via email, not via GitHub."});
+                                    } else {
+                                        return done(null, false, {message: "This account has been registered via GitHub, not via email."});
+                                    }
+                                }
+                            } else if (type === "github") {
+                                return r.table('users')
+                                    .insert(objectMapper(arg3))
+                                    .run(r.conn)
+                                    .then(function (response) {
+                                        return r.table('users')
+                                            .get(response.generated_keys[0])
+                                            .run(r.conn);
+                                    })
+                                    .then(function (newUser) {
+                                        done(null, newUser);
+                                    });
+                            } else {
+                                console.log("User not found");
+                                done(null, false, {message: 'Account not found.'});
+                                // TODO Say account not found
                             }
                             }
-                            return r.table('users')
-                                .insert(objectMapper(profile))
-                                .run(r.conn)
-                                .then(function (response) {
-                                    return r.table('users')
-                                        .get(response.generated_keys[0])
-                                        .run(r.conn);
-                                })
-                                .then(function (newUser) {
-                                    done(null, newUser);
-                                });
                         });
                         });
                 })
                 })
                 .catch(function (err) {
                 .catch(function (err) {
@@ -62,10 +110,10 @@ passport.use(new GitHubStrategy({
     },
     },
     loginCallbackHandler(function (profile) {
     loginCallbackHandler(function (profile) {
         return {
         return {
-            'login': profile.username,
-            'name': profile.displayName || null,
-            'url': profile.profileUrl,
-            'avatarUrl': profile._json.avatar_url,
+            'username': profile.username,
+            'usernameL': profile.username.toLowerCase(),
+            'name': profile.displayName || undefined,
+            'email': 'email',
             'type': 'github'
             'type': 'github'
         };
         };
     }, 'github')
     }, 'github')
@@ -73,26 +121,11 @@ passport.use(new GitHubStrategy({
 
 
 // Local
 // Local
 passport.use(new LocalStrategy(
 passport.use(new LocalStrategy(
-    function(username, password, done) {
-        /*User.findOne({ username: username }, function (err, user) {
-            if (err) { return done(err); }
-            if (!user) {
-                return done(null, false, { message: 'Incorrect username.' });
-            }
-            if (!user.validPassword(password)) {
-                return done(null, false, { message: 'Incorrect password.' });
-            }
-            return done(null, user);
-        });*/
-        //TODO Check password
-        // This is checking if passord is valid and all
-        console.log(username, password);
-        return done(null, {id: "potatoe", login: "Kris", name: "Kristian", url: "no", avatarUrl: "no", type: "local"});
-    }
+    {},
+    loginCallbackHandler(undefined, 'local')
 ));
 ));
 
 
 passport.checkIfLoggedIn = function (req, res, next) {
 passport.checkIfLoggedIn = function (req, res, next) {
-    console.log(req.user, 666);
     if (req.user) {
     if (req.user) {
         return next();
         return next();
     }
     }

+ 1 - 1
server/db/index.js

@@ -13,7 +13,7 @@ r.getNewConnection = function () {
 r.init({host: 'localhost', port: 28015, db: 'musare'}, [
 r.init({host: 'localhost', port: 28015, db: 'musare'}, [
     {
     {
         name: 'users',
         name: 'users',
-        indexes: ['login']
+        indexes: ['username', 'usernameL', 'email']
     }
     }
 ]).then(function (conn) {
 ]).then(function (conn) {
     r.conn = conn;
     r.conn = conn;

+ 9 - 1
server/server.js

@@ -23,6 +23,7 @@ app.listen(3000, function () {
 */
 */
 
 
 var express = require('express');
 var express = require('express');
+var expressValidator = require('express-validator');
 var session = require('express-session');
 var session = require('express-session');
 var engines = require('consolidate');
 var engines = require('consolidate');
 
 
@@ -38,7 +39,8 @@ app
         saveUninitialized: true
         saveUninitialized: true
     }))
     }))
     .use(auth.initialize())
     .use(auth.initialize())
-    .use(auth.session());
+    .use(auth.session())
+    .use(expressValidator({}));
 
 
 // Views
 // Views
 app
 app
@@ -52,6 +54,12 @@ app
     .get('/', function (req, res) {
     .get('/', function (req, res) {
         res.render('index.html', { user: req.user });
         res.render('index.html', { user: req.user });
     })
     })
+    .get('/login', function (req, res) {
+        res.render('login.html');
+    })
+    .get('/register', function (req, res) {
+        res.render('register.html');
+    })
     .use(express.static(__dirname + '../static'))
     .use(express.static(__dirname + '../static'))
     .use('*', function (req, res) {
     .use('*', function (req, res) {
         res.status(404).send('404 Not Found').end();
         res.status(404).send('404 Not Found').end();