Skip to content

Commit

Permalink
local auth needs data access
Browse files Browse the repository at this point in the history
  • Loading branch information
fschwiet committed Sep 5, 2013
1 parent 27cd8d2 commit e6da8c6
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 91 deletions.
2 changes: 2 additions & 0 deletions purgeProcesses.ps1
@@ -0,0 +1,2 @@
Get-Process *node* | Stop-Process
Get-Process *phant* | stop-process
93 changes: 65 additions & 28 deletions src/requirements/can_log_in_via_local_account.test.js
@@ -1,50 +1,87 @@
var assert = require("assert");
var expect = require("expect.js");

var setup = require("../test/setup");
var config = require("../server/config");
var login = require("../test/login.js");

var waitUntil = require("../test/waitUntil.js");

var username = "SomeUsername";
var password = "SomePassword";

var context = setup.usingPhantomPage(setup.whenRunningTheServer(exports));


function doLoginFromPage(page, url) {

return page.promise.open(url)
.then(function() {
console.log("1");
return page.promise.clickElement(login.selectors.loginButton, true);
})
.then(function() {
return waitUntil("login page loads", function() {
return page.promise.evaluate(function(selectors) {
return document.querySelector(selectors.loginUsername) !== null;
}, login.selectors);
});
})
.then(function() {
console.log("2");
return page.promise.evaluate(function(selectors, u,p) {

document.querySelector(selectors.loginUsername).value = u;
document.querySelector(selectors.loginPassword).value = p;
}, login.selectors, username, password);
})
.then(function() {
console.log("3");
return page.promise.clickElement(login.selectors.loginLocalSubmit);
});
}

setup.qtest(context, "should show user message for invalid username/password", function() {

var page = this.page;

return doLoginFromPage(page, config.urlFor("/"))
.then(function() {
return waitUntil("login completes", function() {
return page.promise.evaluate(function() {
return document.querySelector('span.info') !== null;
});
});
})
.then(function() {
return page.promise.evaluate(function() {
return document.querySelector('span.info').textContent;
});
})
.then(function(textContent) {
expect(textContent).to.contain('Incorrect username or password');
});
});

function check_login_from(startPage) {

setup.qtest(context, "can log in with local account from " + startPage, function() {

var page = this.page;

return page.promise.open(startPage)
.then(function() {
console.log("1");
return page.promise.clickElement(login.selectors.loginButton, true);
})
.then(function() {
console.log("2");
return page.promise.evaluate(function(selectors, u,p) {

document.querySelector(selectors.loginUsername).value = u;
document.querySelector(selectors.loginPassword).value = p;
}, login.selectors, username, password);
})
.then(function() {
console.log("3");
return page.promise.clickElement(login.selectors.loginLocalSubmit);
})
.then(function() {
console.log("4");
return page.promise.evaluate(function() {
return window.location.toString();
});
})
.then(function(location) {
console.log("5");
assert.equal(location, startPage);
return doLoginFromPage(page, startPage)
.then(function() {
console.log("4");
return page.promise.evaluate(function() {
return window.location.toString();
});
})
.then(function(location) {
console.log("5");
assert.equal(location, startPage);
});
});
}

/*
check_login_from(config.urlFor("/feeds"));
check_login_from(config.urlFor("/status"));
*/
5 changes: 5 additions & 0 deletions src/server/auth.js
Expand Up @@ -35,6 +35,11 @@ exports.getAuthHandler = function(req, res, next) {
if (err) {
return next(err);
}

if (typeof info == 'object' && 'message' in info) {
req.flash('info', info.message);
}

if (!user) {
return res.redirect('/login');
}
Expand Down
53 changes: 53 additions & 0 deletions src/server/data/users.js
@@ -0,0 +1,53 @@

var Q = require("q");

var database = require('../database.js');


exports.findOrCreateUserByGoogleIdentifier = function(identifier, profile, callback) {

var connection = database.getConnection();

var query = Q.nbind(connection.query, connection);

query("SELECT users.id, users.friendlyName FROM users JOIN googleProfiles ON googleProfiles.userId = users.id WHERE googleProfiles.id = ?", identifier)
.then(function(result) {

if (result[0].length > 0) {
var firstResult = result[0][0];

callback(null, {
id: firstResult.id,
friendlyName: firstResult.friendlyName
});
} else {
return query("INSERT INTO users SET ?", {
friendlyName: profile.displayName
})
.then(function(result) {

var userId = result[0].insertId;

return query("INSERT INTO googleProfiles SET ?", {
id: identifier,
userId: userId,
profile: JSON.stringify(profile)
})
.then(function() {
callback(null, {
id: userId,
friendlyName: profile.displayName
});
});
});
}
})
.fin(function() {
connection.end();
})
.fail(function(err) {
callback(err);
});
};


84 changes: 42 additions & 42 deletions src/server/database.test.js → src/server/data/users.test.js
@@ -1,42 +1,42 @@
var Q = require("q");
var uuid = require('node-uuid');
var expect = require("expect.js");
var assert = require("assert");

var setup = require("../test/setup");
var database = require("./database");

var findOrCreateUserByGoogleIdentifier = Q.nbind(database.findOrCreateUserByGoogleIdentifier);

setup.qtest(exports, "findOrCreateUserByGoogleIdentifier can save and load users", function() {

var firstGoogleIdentifier = uuid.v4();
var firstGoogleProfile = setup.getGoogleProfile("First");

var secondGoogleIdentifier = uuid.v4();
var secondGoogleProfile = setup.getGoogleProfile("Second");

// Load the first user
return findOrCreateUserByGoogleIdentifier(firstGoogleIdentifier, firstGoogleProfile)
.then(function(firstUser) {
expect(firstUser.id).to.be.a('number');
expect(firstUser.friendlyName).to.equal("displayNameFirst");

// Load the second user
return findOrCreateUserByGoogleIdentifier(secondGoogleIdentifier, secondGoogleProfile)
.then(function(secondUser) {
expect(secondUser.id).to.be.a('number');
expect(secondUser.id).not.to.equal(firstUser.id);
expect(secondUser.friendlyName).to.equal("displayNameSecond");
})
.then(function() {

// Reload the first user
return findOrCreateUserByGoogleIdentifier(firstGoogleIdentifier, firstGoogleProfile)
.then(function(reloadedUser) {
expect(reloadedUser.id).to.equal(firstUser.id);
expect(reloadedUser.friendlyName).to.equal("displayNameFirst");
});
});
});
});
var Q = require("q");
var uuid = require('node-uuid');
var expect = require("expect.js");
var assert = require("assert");

var setup = require("../../test/setup.js");
var users = require("./users.js");

var findOrCreateUserByGoogleIdentifier = Q.nbind(users.findOrCreateUserByGoogleIdentifier);

setup.qtest(exports, "findOrCreateUserByGoogleIdentifier can save and load users", function() {

var firstGoogleIdentifier = uuid.v4();
var firstGoogleProfile = setup.getGoogleProfile("First");

var secondGoogleIdentifier = uuid.v4();
var secondGoogleProfile = setup.getGoogleProfile("Second");

// Load the first user
return findOrCreateUserByGoogleIdentifier(firstGoogleIdentifier, firstGoogleProfile)
.then(function(firstUser) {
expect(firstUser.id).to.be.a('number');
expect(firstUser.friendlyName).to.equal("displayNameFirst");

// Load the second user
return findOrCreateUserByGoogleIdentifier(secondGoogleIdentifier, secondGoogleProfile)
.then(function(secondUser) {
expect(secondUser.id).to.be.a('number');
expect(secondUser.id).not.to.equal(firstUser.id);
expect(secondUser.friendlyName).to.equal("displayNameSecond");
})
.then(function() {

// Reload the first user
return findOrCreateUserByGoogleIdentifier(firstGoogleIdentifier, firstGoogleProfile)
.then(function(reloadedUser) {
expect(reloadedUser.id).to.equal(firstUser.id);
expect(reloadedUser.friendlyName).to.equal("displayNameFirst");
});
});
});
});
47 changes: 34 additions & 13 deletions src/server/google-auth.js
@@ -1,20 +1,30 @@
var GoogleStrategy = require('passport-google');
var LocalStrategy = require('passport-local').Strategy;

var passport = require('passport');
var config = require("./config");
var Q = require("q");

var auth = require("./auth.js");
var database = require("./database");
var database = require("./database.js");
var modelFor = require("./modelFor.js");

module.exports = function(port, app) {

passport.serializeUser(function(user, done) {
done(null, user);
});
passport.serializeUser(function(user, done) {
done(null, user);
});

passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});

module.exports = function(port, app) {
passport.use(new LocalStrategy(
function(username, password, done) {
done(null, false, {message: 'not implemented'});
// done(null, user)
}
));

passport.use(new GoogleStrategy.Strategy({
returnURL: config.urlFor('/auth/google/return'),
Expand All @@ -24,6 +34,22 @@ module.exports = function(port, app) {
app.use(passport.initialize());
app.use(passport.session());

app.get("/login",
auth.withLoginPage("/login").handleRefererUrl,
function(req, res) {
res.render('loginPage', modelFor("login", req));
});

app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});

app.post('/auth/local',
function(req,res,next) {
passport.authenticate('local', auth.getAuthHandler(req,res,next))(req,res,next);
});

app.get('/auth/google',
auth.withLoginPage("/login").handleRefererUrl,
passport.authenticate('google', {
Expand All @@ -35,9 +61,4 @@ module.exports = function(port, app) {
function(req,res,next) {
passport.authenticate('google', auth.getAuthHandler(req,res,next))(req,res,next);
});

app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
};
5 changes: 0 additions & 5 deletions src/server/server.js
Expand Up @@ -54,11 +54,6 @@
app.get("/", handleHomepageRequest);
app.get("/status", handleStatusRequest);
app.get("/about", handleAboutRequest);
app.get("/login",
auth.withLoginPage("/login").handleRefererUrl,
function(req, res) {
res.render('loginPage', modelFor("login", req));
});

app.get("/client/main-built.js", function(req, res) {
var mainBuilt = path.resolve(__dirname + '../../../temp/main-built.js');
Expand Down
2 changes: 1 addition & 1 deletion src/server/views/_layout.jade
Expand Up @@ -23,6 +23,6 @@ html
- if (typeof flash !== "undefined")
fieldset
-if (flash.info)
span.info !{flash.info}
span.info !{flash.info.toString()}

block content
5 changes: 5 additions & 0 deletions src/server/views/loginPage.jade
Expand Up @@ -4,4 +4,9 @@ extends _layout
block content
a(href="/auth/google") Login with a Google account

form(method="post",action="/auth/local")
input(name='username',type='text')
input(name='password',type='password')
input#submitLocalLogin(type='submit')


4 changes: 2 additions & 2 deletions src/test/login.js
Expand Up @@ -13,8 +13,8 @@ var selectors = {

// From the login page
loginWithGoogleButtonSelector: "a[href='/auth/google']",
loginUsername : "input#username",
loginPassword : "input#password",
loginUsername : "input[name='username']",
loginPassword : "input[name='password']",
loginLocalSubmit : "input#submitLocalLogin",

// Selectors used for google login
Expand Down

0 comments on commit e6da8c6

Please sign in to comment.