nodulator
Version:
Complete NodeJS Framework for Restfull APIs
177 lines (125 loc) • 4.61 kB
text/coffeescript
_ = require 'underscore'
async = require 'async'
cookieParser = require 'cookie-parser'
passport = require 'passport'
LocalStrategy = require('passport-local').Strategy
module.exports = (N) ->
N.authApp = true
N.passport = passport
# Init
do ->
if N.consoleMode
return
if not N.app?
N.Route._InitServer()
N.app.use N.passport.initialize()
N.app.use N.passport.session()
class AccountResource extends N '_account', {abstract: true}
:
usernameField: 'username'
passwordField: 'password'
: ->
N.passport.serializeUser (user, done) =>
done null, user.id
N.passport.deserializeUser (id, done) =>
id, (err, user) ->
return done null, false if err? and err.status is 'not_found'
return done 'Error deserialize user', null if err?
done null, user
N.passport.use new LocalStrategy , (username, password, done) =>
constraints = {}
constraints[.usernameField] = username
constraints, (err, user) =>
# @[] username, (err, user) =>
return done err if err? and err.status isnt 'not_found'
return done null, false, {message: 'Incorrect Username/password'} if err? or !(user?) or user[.passwordField] isnt password
return done null, user
: (resName) ->
= N.app
.post '/api/1/' + resName + 's' + '/login', N.passport.authenticate('local'), (req, res) =>
if ? and .loginCallback?
.loginCallback req, ->
res.sendStatus(200)
else
res.sendStatus(200)
.post '/api/1/' + resName + 's' + '/logout', (req, res) =>
if ? and .logoutCallback?
.logoutCallback req, ->
req.logout()
res.sendStatus(200)
else
req.logout()
res.sendStatus(200)
: (req, res) ->
userObject = '<script>var __user = ' + (JSON.stringify(req.user?.ToJSON() || {})) + ';</script>\n'
#FIXME: dirty
userObject
ToJSON: ->
blob = super()
delete blob[AccountResource.userField.passwordField]
blob
AccountResource.Init()
if N.assets?
N.ExtendBeforeRender AccountResource._InjectUser
N.ExtendAfterRender (req, res) =>
rend = 'auth'
if req.user?
rend = 'index'
res.render rend
# Returning false breaks the render loop
return false
N.AccountResource = (args...) ->
if [args[0]]?
return [args[0]]
res = AccountResource.Extend.apply AccountResource, args
if res.config? and res.config.fields?
res.userField = res.config.fields
res._InitPassport()
res._InitLoginRoutes args[0]
res
N.AccountResource._AccountResource = AccountResource
N.Route.Auth = () ->
(req, res, next) ->
return res.sendStatus(403) if not req.user?
next()
N.Route.HasProperty = (obj) ->
(req, res, next) =>
return res.sendStatus(403) if not req.user?
for key, item of obj
if not req.user[key]? or req.user[key] isnt item
return res.sendStatus(403)
next()
N.Route.IsOwn = (key) ->
(req, res, next) =>
return next() if not req.params[key]?
return res.sendStatus(403) if not req.user?
return res.sendStatus(403) if parseInt(req.params[key]) isnt req.user.id
next()
# N.Route.IsOwnObject = (key) ->
# (req, res, next) =>
# return res.sendStatus(403) if not req.user?
# #FIXME: dirty
# toSearch = {}
# toSearch[key] = req.user.id
# .FetchBy toSearch, (err, instance) ->
# return res.status(403).send err if err?
# if
# return res.sendStatus(403) if not req.params[key]? or parseInt(req.params[key]) isnt req.user.id
# next()
N.Route.prototype.Auth = (args...) ->
N.Route.Auth args...
N.Route.prototype.HasProperty = (args...) ->
N.Route.HasProperty args...
N.Route.prototype.IsOwn = (args...) ->
N.Route.IsOwn args...
#Used to wrap _Add call to allow global permissions restrictions on Route
_AddBack = N.Route.prototype._Add
N.Route.prototype._Add = (args...) ->
if not ?
return _AddBack.apply @, args
done = args.splice(args.length - 1, 1)[0]
if .restrict? and typeof(.restrict) is 'function'
args.push .restrict
args.push done
_AddBack.apply @, args
{name: 'Account'}