mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-04-14 19:56:23 +00:00
gut custom everyauth code & replace with derby-auth
This commit is contained in:
parent
b2d6596f92
commit
91364e19b6
8 changed files with 51 additions and 247 deletions
|
|
@ -26,7 +26,7 @@ _ = require('underscore');
|
|||
get('/:uid?', function(page, model, _arg, next) {
|
||||
var req, sess, uid;
|
||||
uid = _arg.uid;
|
||||
if (uid && !(require('guid').isGuid(uid))) {
|
||||
if (uid && !(require('derby-auth/node_modules/guid').isGuid(uid))) {
|
||||
return next();
|
||||
}
|
||||
req = page._res.req;
|
||||
|
|
@ -34,8 +34,8 @@ get('/:uid?', function(page, model, _arg, next) {
|
|||
return page.redirect('https://' + req.headers.host + req.url);
|
||||
}
|
||||
sess = model.session;
|
||||
if (sess.habitRpgAuth && sess.habitRpgAuth.facebook) {
|
||||
model.set('_facebookAuthenticated', true);
|
||||
if (sess.loggedIn) {
|
||||
model.set('_loggedIn', true);
|
||||
}
|
||||
model.set('_userId', sess.userId);
|
||||
return model.subscribe("users." + sess.userId, function(err, user) {
|
||||
|
|
|
|||
|
|
@ -1,114 +0,0 @@
|
|||
// Generated by CoffeeScript 1.4.0
|
||||
var content, derby, req, schema, _;
|
||||
|
||||
derby = require('derby');
|
||||
|
||||
schema = require('../app/schema');
|
||||
|
||||
content = require('../app/content');
|
||||
|
||||
_ = require('underscore');
|
||||
|
||||
req = void 0;
|
||||
|
||||
module.exports.setRequest = function(r) {
|
||||
return req = r;
|
||||
};
|
||||
|
||||
module.exports.newUserAndPurl = function() {
|
||||
var acceptableUid, model, sess, uidParam;
|
||||
model = req.getModel();
|
||||
sess = model.session;
|
||||
uidParam = req.url.split('/')[1];
|
||||
if (!sess.userId) {
|
||||
sess.userId = derby.uuid();
|
||||
model.set("users." + sess.userId, schema.newUserObject());
|
||||
}
|
||||
acceptableUid = require('guid').isGuid(uidParam);
|
||||
if (acceptableUid && sess.userId !== uidParam && !(sess.habitRpgAuth && sess.habitRpgAuth.facebook)) {
|
||||
return sess.userId = uidParam;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.setupEveryauth = function(everyauth) {
|
||||
everyauth.debug = true;
|
||||
everyauth.everymodule.findUserById(function(id, callback) {
|
||||
return callback(null, null);
|
||||
});
|
||||
everyauth.facebook.appId(process.env.FACEBOOK_KEY).appSecret(process.env.FACEBOOK_SECRET).findOrCreateUser(function(session, accessToken, accessTokenExtra, fbUserMetadata) {
|
||||
var model, q;
|
||||
session.habitRpgAuth || (session.habitRpgAuth = {});
|
||||
session.habitRpgAuth.facebook = fbUserMetadata.id;
|
||||
model = req.getModel();
|
||||
q = model.query('users').withEveryauth('facebook', fbUserMetadata.id);
|
||||
model.fetch(q, function(err, user) {
|
||||
var id;
|
||||
id = user && !_.isEmpty(user.get()) && user.get()[0].id;
|
||||
console.log({
|
||||
err: err,
|
||||
id: id,
|
||||
fbUserMetadata: fbUserMetadata
|
||||
});
|
||||
if (id && id !== session.userId) {
|
||||
return session.userId = id;
|
||||
} else {
|
||||
model.setNull("users." + session.userId + ".auth", {
|
||||
'facebook': {}
|
||||
});
|
||||
return model.set("users." + session.userId + ".auth.facebook", fbUserMetadata);
|
||||
}
|
||||
});
|
||||
return fbUserMetadata;
|
||||
}).redirectPath("/");
|
||||
return everyauth.everymodule.handleLogout(function(req, res) {
|
||||
if (req.session.habitRpgAuth && req.session.habitRpgAuth.facebook) {
|
||||
req.session.habitRpgAuth.facebook = void 0;
|
||||
}
|
||||
req.session.userId = void 0;
|
||||
req.logout();
|
||||
return this.redirect(res, this.logoutRedirectPath());
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.setupQueries = function(store) {
|
||||
store.query.expose('users', 'withId', function(id) {
|
||||
return this.byId(id);
|
||||
});
|
||||
store.query.expose('users', 'withEveryauth', function(provider, id) {
|
||||
console.log({
|
||||
withEveryauth: {
|
||||
provider: provider,
|
||||
id: id
|
||||
}
|
||||
});
|
||||
return this.where("auth." + provider + ".id").equals(id);
|
||||
});
|
||||
return store.queryAccess('users', 'withEveryauth', function(methodArgs) {
|
||||
var accept;
|
||||
accept = arguments[arguments.length - 1];
|
||||
return accept(true);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.setupAccessControl = function(store) {
|
||||
store.accessControl = true;
|
||||
store.readPathAccess('users.*', function() {
|
||||
var captures, next;
|
||||
if (!(this.session && this.session.userId)) {
|
||||
return;
|
||||
}
|
||||
captures = arguments[0];
|
||||
next = arguments[arguments.length - 1];
|
||||
return next(captures === this.session.userId);
|
||||
});
|
||||
return store.writeAccess('*', 'users.*', function() {
|
||||
var captures, next, pathArray;
|
||||
if (!(this.session && this.session.userId)) {
|
||||
return;
|
||||
}
|
||||
captures = arguments[0];
|
||||
next = arguments[arguments.length - 1];
|
||||
pathArray = captures.split('.');
|
||||
return next(pathArray[0] === this.session.userId);
|
||||
});
|
||||
};
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Generated by CoffeeScript 1.4.0
|
||||
var MongoStore, ONE_YEAR, app, auth, derby, everyauth, express, expressApp, gzippo, habitrpgMiddleware, http, path, priv, publicPath, racer, root, server, serverError, store;
|
||||
var MongoStore, ONE_YEAR, app, auth, derby, everyauth, express, expressApp, gzippo, habitrpgMiddleware, http, options, path, priv, publicPath, racer, root, server, serverError, store, strategies;
|
||||
|
||||
http = require('http');
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ serverError = require('./serverError');
|
|||
|
||||
MongoStore = require('connect-mongo')(express);
|
||||
|
||||
auth = require('./auth');
|
||||
auth = require('derby-auth');
|
||||
|
||||
priv = require('./private');
|
||||
|
||||
|
|
@ -48,12 +48,6 @@ store = derby.createStore({
|
|||
listen: server
|
||||
});
|
||||
|
||||
auth.setupQueries(store);
|
||||
|
||||
auth.setupEveryauth(everyauth);
|
||||
|
||||
auth.setupAccessControl(store);
|
||||
|
||||
ONE_YEAR = 1000 * 60 * 60 * 24 * 365;
|
||||
|
||||
root = path.dirname(path.dirname(__dirname));
|
||||
|
|
@ -65,11 +59,27 @@ habitrpgMiddleware = function(req, res, next) {
|
|||
model = req.getModel();
|
||||
model.set('_mobileDevice', /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header('User-Agent')));
|
||||
model.set('_nodeEnv', process.env.NODE_ENV);
|
||||
auth.setRequest(req);
|
||||
auth.newUserAndPurl();
|
||||
return next();
|
||||
};
|
||||
|
||||
strategies = {
|
||||
facebook: {
|
||||
strategy: require("passport-facebook").Strategy,
|
||||
conf: {
|
||||
clientID: process.env.FACEBOOK_KEY,
|
||||
clientSecret: process.env.FACEBOOK_SECRET
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
options = {
|
||||
domain: "http://localhost:3000",
|
||||
allowPurl: true,
|
||||
schema: require('../app/schema').newUserObject()
|
||||
};
|
||||
|
||||
auth.init(expressApp, store, strategies, options);
|
||||
|
||||
expressApp.use(express.favicon()).use(gzippo.staticGzip(publicPath, {
|
||||
maxAge: ONE_YEAR
|
||||
})).use(express.compress()).use(express.bodyParser()).use(express.methodOverride()).use(express.cookieParser()).use(store.sessionMiddleware({
|
||||
|
|
@ -80,7 +90,9 @@ expressApp.use(express.favicon()).use(gzippo.staticGzip(publicPath, {
|
|||
store: new MongoStore({
|
||||
url: process.env.NODE_DB_URI
|
||||
})
|
||||
})).use(store.modelMiddleware()).use(priv.middleware).use(habitrpgMiddleware).use(everyauth.middleware()).use(app.router()).use(expressApp.router).use(serverError(root));
|
||||
})).use(store.modelMiddleware()).use(priv.middleware).use(habitrpgMiddleware).use(auth.middleware()).use(app.router()).use(expressApp.router).use(serverError(root));
|
||||
|
||||
auth.routes();
|
||||
|
||||
priv.routes(expressApp);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@
|
|||
"main": "./server.js",
|
||||
"dependencies": {
|
||||
"derby": "0.3.13",
|
||||
"derby-ui-boot": "*",
|
||||
"racer-db-mongo": "0.3.13",
|
||||
"connect-mongo": ">=0.1.9",
|
||||
"derby-auth": "*",
|
||||
"passport-facebook": "*",
|
||||
"express": "*",
|
||||
"gzippo": "*",
|
||||
"connect-mongo": ">=0.1.9",
|
||||
"everyauth": "git://github.com/bnoguchi/everyauth#express3",
|
||||
"derby-ui-boot": "*",
|
||||
"guid": "*",
|
||||
"moment": "*",
|
||||
"stripe": "*",
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ _ = require 'underscore'
|
|||
|
||||
get '/:uid?', (page, model, {uid}, next) ->
|
||||
# delegate to other routes. FIXME how to define express routes first?
|
||||
if uid && !(require('guid').isGuid(uid))
|
||||
if uid && !(require('derby-auth/node_modules/guid').isGuid(uid))
|
||||
return next()
|
||||
|
||||
# Force SSL
|
||||
|
|
@ -26,8 +26,7 @@ get '/:uid?', (page, model, {uid}, next) ->
|
|||
return page.redirect 'https://' + req.headers.host + req.url
|
||||
|
||||
sess = model.session
|
||||
if sess.habitRpgAuth && sess.habitRpgAuth.facebook
|
||||
model.set('_facebookAuthenticated', true)
|
||||
model.set('_loggedIn', true) if sess.loggedIn
|
||||
model.set '_userId', sess.userId
|
||||
model.subscribe "users.#{sess.userId}", (err, user) ->
|
||||
# Set variables which are passed from the controller to the view
|
||||
|
|
|
|||
|
|
@ -1,103 +0,0 @@
|
|||
derby = require('derby')
|
||||
schema = require('../app/schema')
|
||||
content = require('../app/content')
|
||||
_ = require('underscore')
|
||||
|
||||
# Need this for later use by EveryAuth in the MiddleWare
|
||||
req = undefined
|
||||
module.exports.setRequest = (r) ->
|
||||
req = r
|
||||
|
||||
module.exports.newUserAndPurl = ->
|
||||
model = req.getModel()
|
||||
sess = model.session
|
||||
uidParam = req.url.split('/')[1]
|
||||
|
||||
## -------- (1) New user --------
|
||||
# They get to play around before creating a new account.
|
||||
unless sess.userId
|
||||
sess.userId = derby.uuid()
|
||||
model.set "users.#{sess.userId}", schema.newUserObject()
|
||||
|
||||
## -------- (2) PURL --------
|
||||
# eg, http://localhost/{guid}), legacy - will be removed eventually
|
||||
# tests if UUID was used (bookmarked private url), and restores that session
|
||||
acceptableUid = require('guid').isGuid(uidParam)
|
||||
if acceptableUid && sess.userId!=uidParam && !(sess.habitRpgAuth && sess.habitRpgAuth.facebook)
|
||||
# TODO check if in database - issue with accessControl which is on current uid?
|
||||
sess.userId = uidParam
|
||||
|
||||
module.exports.setupEveryauth = (everyauth) ->
|
||||
everyauth.debug = true
|
||||
|
||||
everyauth.everymodule.findUserById (id, callback) ->
|
||||
# will never be called, can't fetch user from database at this point on the server
|
||||
# see https://github.com/codeparty/racer/issues/39. Handled in app/auth.coffee for now
|
||||
callback null, null
|
||||
|
||||
# Facebook Authentication Logic
|
||||
everyauth
|
||||
.facebook
|
||||
.appId(process.env.FACEBOOK_KEY)
|
||||
.appSecret(process.env.FACEBOOK_SECRET)
|
||||
.findOrCreateUser( (session, accessToken, accessTokenExtra, fbUserMetadata) ->
|
||||
|
||||
# Put it in the session for later use
|
||||
# FIXME shouldn't this be set by everyauth? (session.auth.facebook)
|
||||
session.habitRpgAuth ||= {}
|
||||
session.habitRpgAuth.facebook = fbUserMetadata.id
|
||||
|
||||
model = req.getModel()
|
||||
q = model.query('users').withEveryauth('facebook', fbUserMetadata.id)
|
||||
model.fetch q, (err, user) ->
|
||||
id = user && !_.isEmpty(user.get()) && user.get()[0].id
|
||||
console.log {err:err, id:id, fbUserMetadata:fbUserMetadata}
|
||||
# Has user been tied to facebook account already?
|
||||
if (id && id!=session.userId)
|
||||
session.userId = id
|
||||
# Else tie user to their facebook account
|
||||
else
|
||||
model.setNull "users.#{session.userId}.auth", {'facebook':{}}
|
||||
model.set "users.#{session.userId}.auth.facebook", fbUserMetadata
|
||||
|
||||
fbUserMetadata
|
||||
).redirectPath "/"
|
||||
|
||||
everyauth.everymodule.handleLogout (req, res) ->
|
||||
if req.session.habitRpgAuth && req.session.habitRpgAuth.facebook
|
||||
req.session.habitRpgAuth.facebook = undefined
|
||||
req.session.userId = undefined
|
||||
req.logout() # The logout method is added for you by everyauth, too
|
||||
@redirect res, @logoutRedirectPath()
|
||||
|
||||
module.exports.setupQueries = (store) ->
|
||||
## Setup Queries
|
||||
store.query.expose 'users', 'withId', (id) ->
|
||||
@byId(id)
|
||||
store.query.expose 'users', 'withEveryauth', (provider, id) ->
|
||||
console.log {withEveryauth:{provider:provider,id:id}}
|
||||
@where("auth.#{provider}.id").equals(id)
|
||||
store.queryAccess 'users', 'withEveryauth', (methodArgs) ->
|
||||
accept = arguments[arguments.length-1]
|
||||
accept(true) #for now
|
||||
|
||||
module.exports.setupAccessControl = (store) ->
|
||||
store.accessControl = true
|
||||
|
||||
# Callback signatures here have variable length, eg `callback(captures..., next)`
|
||||
# Is using arguments[n] the correct way to handle this?
|
||||
|
||||
store.readPathAccess 'users.*', () -> #captures, next) ->
|
||||
return unless @session && @session.userId # https://github.com/codeparty/racer/issues/37
|
||||
captures = arguments[0]
|
||||
next = arguments[arguments.length-1]
|
||||
# console.log { readPathAccess: {captures:captures, sessionUserId:@session.userId, next:next} }
|
||||
next(captures == @session.userId)
|
||||
|
||||
store.writeAccess '*', 'users.*', () -> #captures, value, next) ->
|
||||
return unless @session && @session.userId
|
||||
captures = arguments[0]
|
||||
next = arguments[arguments.length-1]
|
||||
pathArray = captures.split('.')
|
||||
# console.log { writeAccess: {captures:captures, next:next, pathArray:pathArray, arguments:arguments} }
|
||||
next(pathArray[0] == @session.userId)
|
||||
|
|
@ -7,8 +7,8 @@ app = require '../app'
|
|||
everyauth = require('everyauth')
|
||||
serverError = require './serverError'
|
||||
MongoStore = require('connect-mongo')(express)
|
||||
auth = require('./auth')
|
||||
priv = require('./private')
|
||||
auth = require 'derby-auth'
|
||||
priv = require './private'
|
||||
|
||||
## RACER CONFIGURATION ##
|
||||
|
||||
|
|
@ -28,9 +28,6 @@ derby.use(require 'racer-db-mongo')
|
|||
store = derby.createStore
|
||||
db: {type: 'Mongo', uri: process.env.NODE_DB_URI}
|
||||
listen: server
|
||||
auth.setupQueries(store)
|
||||
auth.setupEveryauth(everyauth)
|
||||
auth.setupAccessControl(store)
|
||||
|
||||
ONE_YEAR = 1000 * 60 * 60 * 24 * 365
|
||||
root = path.dirname path.dirname __dirname
|
||||
|
|
@ -41,9 +38,20 @@ habitrpgMiddleware = (req, res, next) ->
|
|||
## Set _mobileDevice to true or false so view can exclude portions from mobile device
|
||||
model.set '_mobileDevice', /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header 'User-Agent')
|
||||
model.set '_nodeEnv', process.env.NODE_ENV
|
||||
auth.setRequest(req) # Need to pass into auth, so auth can save as private variable used later by EveryAuth
|
||||
auth.newUserAndPurl()
|
||||
next()
|
||||
|
||||
# Authentication setup
|
||||
strategies =
|
||||
facebook:
|
||||
strategy: require("passport-facebook").Strategy
|
||||
conf:
|
||||
clientID: process.env.FACEBOOK_KEY
|
||||
clientSecret: process.env.FACEBOOK_SECRET
|
||||
options =
|
||||
domain: "http://localhost:3000"
|
||||
allowPurl: true
|
||||
schema: require('../app/schema').newUserObject()
|
||||
auth.init expressApp, store, strategies, options
|
||||
|
||||
expressApp
|
||||
.use(express.favicon())
|
||||
|
|
@ -71,12 +79,13 @@ expressApp
|
|||
# the app router to pass server accessible data to a model
|
||||
.use(priv.middleware)
|
||||
.use(habitrpgMiddleware)
|
||||
.use(everyauth.middleware())
|
||||
.use(auth.middleware())
|
||||
# Creates an express middleware from the app's routes
|
||||
.use(app.router())
|
||||
.use(expressApp.router)
|
||||
.use(serverError root)
|
||||
|
||||
auth.routes()
|
||||
priv.routes(expressApp)
|
||||
require('./serverRoutes')(expressApp, root, derby)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@
|
|||
<ui:connectionAlert>
|
||||
<div id="head">
|
||||
<div class='pull-right'>
|
||||
{#unless _facebookAuthenticated}
|
||||
{#unless _loggedIn}
|
||||
<a href="/auth/facebook"><img src='/img/facebook-login-register.jpeg' alt="Login / Register With Facebook"/></a>
|
||||
{else}
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-small">{_user.auth.facebook.name}</button>
|
||||
<button class="btn btn-small">{_user.auth.facebook.name.givenName} {_user.auth.facebook.name.familyName}</button>
|
||||
<button class="btn btn-small dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in a new issue