public
Last active

Express authentication using Redis for session store and Couchdb for database (in coffeescript!)

  • Download Gist
gistfile1.coffee
CoffeeScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
###
Module dependencies
###
require.paths.unshift "#{__dirname}/lib/support/express-csrf/"
require.paths.unshift "#{__dirname}/lib/support/node_hash/lib/"
 
express = require 'express'
app = module.exports = express.createServer()
 
RedisStore = require 'connect-redis'
 
csrf = require 'csrf.js'
fugue = require 'fugue'
 
couchdb = require 'couchdb'
client = couchdb.createClient 5984, 'localhost'
db = client.db 'blahblahblah-devel'
 
hash = require 'hash.js'
###
Configuration
###
 
app.dynamicHelpers({
csrf: csrf.token
})
app.dynamicHelpers({
flash: (req) ->
flash = req.flash()
return flash
})
app.dynamicHelpers({
current_user: (req) -> req.session.user
})
 
app.configure(() ->
app.set 'views', "#{__dirname}/views"
app.use express.logger()
app.use express.bodyDecoder()
app.use express.cookieDecoder()
app.use express.session({
store: new RedisStore({
maxAge: 24 * 60 * 60 * 1000
})
})
app.use csrf.check()
app.use app.router
app.use express.methodOverride()
app.use express.staticProvider("#{__dirname}/public")
)
 
app.configure 'development', () ->
app.use express.errorHandler({
dumpExceptions: true
showStack : true
})
app.configure 'production', () ->
app.use express.errorHandler()
###
ROUTE: ROOT '/' (GET)
###
app.get '/', (req, res) ->
if req.session.user
req.flash 'success', "Authenticated as #{req.session.user.name}"
res.redirect '/dashboard'
 
res.render 'index.jade',
locals:
title: 'Home'
###
ROUTE: DASHBOARD '/dashboard' (GET, POST)
###
app.get '/dashboard', (req, res) ->
if req.session.user
res.render 'dashboard/index.jade',
locals:
title: 'Dashboard'
else
res.redirect '/login'
 
app.post '/dashboard', (req, res) ->
params = req.body
if req.session.user
user = req.session.user
console.log params
else
res.redirect '/login'
###
ROUTE: LOGIN '/login' (GET, POST)
###
app.get '/login', (req, res) ->
if req.session.user
req.flash 'success', "Authenticated as #{req.session.user.name}"
res.redirect '/dashboard'
 
res.render 'index.jade',
locals:
title: 'Login'
app.post '/login', (req, res) ->
params = req.body
if params.commit.login
db.getDoc params.user.name, (e, doc) ->
if e
req.flash 'error', 'User does not exist!'
res.redirect '/login'
if doc
salt = "superblahblah--#{params.user.password}"
salted_password = hash.sha1 params.user.password, salt
if doc.password is salted_password
req.session.regenerate(() ->
req.session.user = params.user
res.redirect '/dashboard'
)
else
res.redirect '404'
else if params.commit.signup
res.redirect '/signup'
###
ROUTE: LOGOUT '/logout' (GET)
###
app.get '/logout', (req, res) ->
req.session.destroy(() ->
res.redirect '/'
)
###
ROUTE: SIGNUP '/signup' (GET, POST)
###
app.get '/signup', (req, res) ->
if req.session.user
req.flash 'success', "Autenticated as #{req.session.user.name}"
res.redirect '/dashboard'
res.render 'users/signup.jade',
locals:
title: 'Signup'
username: ''
password: ''
password_confirmation: ''
email: ''
 
app.post '/signup', (req, res) ->
params = req.body
errors = []
salt = "superblahblah--#{params.user.password}"
salted_password = hash.sha1 params.user.password, salt
salted_confirm_password = hash.sha1 params.user.password_confirmation, salt
user =
name: params.user.name
password: salted_password
email: params.user.email
confirm_password = salted_confirm_password
 
create_user = () ->
db.exists (e,c) ->
if c is true
db.saveDoc user.name, couchdb.toJSON(user), (e,c) ->
if e
req.flash 'error', "Document update conflict. This user exists!"
res.redirect 'back'
if c
req.flash 'success', "SUCCESS"
req.session.regenerate(() ->
req.session.user = params.user
res.redirect '/dashboard'
)
if errors.length > 0
errors.forEach (err) ->
req.flash 'error', err
res.render 'users/signup.jade',
locals:
title: "Signup"
username: user.name
password: ""
password_confirmation: ""
email: user.email
else
create_user()
###
Only listen on $ sudo node server.js
###
if not module.parent
fugue.start app, 3000, null, 10, {
verbose: true
daemonize: true
}
console.log "Express server listening on port #{app.address().port}"

Great. Will modify it to fit MongoDB.

express-csrf is a module for CSRF protection. see: https://github.com/hanssonlarsson/express-csrf

this is a really old gist. you don't need the first two lines. the modules have their own entries in the npm registry.

You could get rid of a lot of those parentheses. Anonymous functions in CoffeeScript don't need to be surrounded by parens.

$ sudo node server.js

Why would you need to sudo? Are you binding directly to port 80?

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.