Skip to content

Instantly share code, notes, and snippets.

@lackac
Created September 20, 2012 22:26
Show Gist options
  • Save lackac/3758734 to your computer and use it in GitHub Desktop.
Save lackac/3758734 to your computer and use it in GitHub Desktop.
Authentication with everyauth in Derby
derby = require 'derby'
everyauth = require 'everyauth'
config = require './config'
users = require('mongoskin').db(config('mongo_url')).collection('users')
# let's make sure there is a userId set, this way there will always be a user
exports.ensureUser = ->
(req, res, next) ->
req.session.auth ||= {}
req.session.auth.userId ||= derby.uuid()
next()
everyauth.debug = true
everyauth.everymodule.configure
userPkey: '_id'
performRedirect: (res, location) ->
res.redirect 303, location
findUserById: (req, userId, callback) ->
model = req.getModel()
model.subscribe "users.#{userId}", (err, user) ->
return callback(err) if err
model.ref '_user', user
for key, value of config('default_user_values')
user.setNull key, value
user.setNull 'created_at', new Date()
callback null, user.get()
handleLogout: (req, res) ->
req.logout()
@redirect res, @logoutRedirectPath()
# Facebook Authentication Logic
everyauth.facebook.configure
appId: config('facebook_app_id')
appSecret: config('facebook_secret')
findOrCreateUser: (session, access_token, access_token_extra, fb_user) ->
promise = @Promise()
users.findOne 'auth.facebook.id': fb_user.id, (err, user) ->
return promise.fail(err) if err
if user
# set userId explicitly because everyauth wouldn't overwrite it if it was set
session.auth.userId = user._id
return promise.fulfill(user)
users.findAndModify {_id: session.auth.userId}, {_id: 1},
{$set: {'auth.facebook': fb_user}}
{new: true, upsert: true}
(err, user) ->
return promise.fail(err) if err
promise.fulfill(user)
promise
handleAuthCallbackError: (req, res) ->
@redirect res, @logoutRedirectPath()
redirectPath: '/'
# conditionally offer mobile view
everyauth.facebook.mobile = (isMobile) ->
if isMobile
@authPath 'https://m.facebook.com/dialog/oauth'
else
@authPath 'https://www.facebook.com/dialog/oauth'
this
origGetAuthUri = everyauth.facebook._getAuthUri
everyauth.facebook.getAuthUri (req, res) ->
@mobile /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(req.header 'User-Agent')
origGetAuthUri.apply(this, arguments)
http = require 'http'
path = require 'path'
express = require 'express'
gzippo = require 'gzippo'
derby = require 'derby'
everyauth = require 'everyauth'
MongoStore = require('connect-mongo')(require('express'))
app = require '../app'
serverError = require './serverError'
config = require './config'
## SERVER CONFIGURATION ##
derby.use derby.logPlugin
expressApp = express()
server = module.exports = http.createServer expressApp
store = require './store'
auth = require './auth'
ONE_YEAR = 1000 * 60 * 60 * 24 * 365
root = path.dirname path.dirname __dirname
publicPath = path.join root, 'public'
expressApp
.use(express.favicon())
# Gzip static files and serve from memory
.use(gzippo.staticGzip publicPath, maxAge: ONE_YEAR)
# Gzip dynamically rendered content
.use(express.compress())
# Uncomment to add form data parsing support
.use(express.bodyParser())
.use(express.methodOverride())
# Derby session middleware creates req.session and socket.io sessions
.use(express.cookieParser())
.use(store.sessionMiddleware
secret: config('session_secret')
cookie: {maxAge: config('cookie_max_age')}
store: new MongoStore(url: config('mongo_url'))
)
# Adds req.getModel method
.use(store.modelMiddleware())
# authentication middlewares
.use(auth.ensureUser())
.use(everyauth.middleware())
# Creates an express middleware from the app's routes
.use(app.router())
.use(expressApp.router)
.use(serverError root)
## SERVER ONLY ROUTES ##
expressApp.all '*', (req) ->
throw "404: #{req.url}"
derby = require 'derby'
server = require './server'
config = require './config'
# Setting up racer store with mongo
derby.use require('racer-db-mongo')
module.exports = store = derby.createStore
listen: server
db: { type: 'Mongo', uri: config('mongo_url') }
# Access Control
store.accessControl = true
# Everyone should read the Bible
store.readPathAccess 'bibles.*', (path, accept) -> accept(true)
store.readPathAccess 'chapters.*', (path, accept) -> accept(true)
# Allow users to read and modify their own users
store.readPathAccess 'users.*', (userId, accept) ->
accept userId == @session.auth?.userId
store.writeAccess 'set', 'users.*.*', (userId, field, value, accept) ->
accept userId == @session.auth?.userId
@philcockfield
Copy link

Hi there. Thanks so much for posting this code. Very very useful to get rolling with Derby + Everyauth.

I'm wondering, why are you suing mongoskin in the auth file instead of accessing the Derby data store directly via a model.

I see you are doing that within the everyauth.everymodule.configure.findUserById but yet you're using the collection from mongo-skin in the everyauth.facebook.configure.findOrCreateUser method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment