diff --git a/README.md b/README.md
index 25c2411..79ac5b9 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,17 @@
# User Authentification and role management REST Webservice
+
+## Description
+
+Usr provides you a webservice to authenticate and manage your users with a REST API :
+
+- Using EveryAuth to enable your users to login with any credentials
+- Using REST to be shared within multiples service.
+
+## Authentification of a user :
+
+1/ You deploy your service to auth.yourdomain.com
+2/ On your application, to authentificate a user, just need to :
+ - redirect the user to http://auth.yourdomain.com/login/http://mynewapp.com/loguedId/
+ - The user will come back to http://mynewapp.com/loguedId/SUPERTOKEN with a token
+ - Send a request to get all the details about your user.
+
diff --git a/configs.coffee b/examples/configs.coffee
similarity index 100%
rename from configs.coffee
rename to examples/configs.coffee
diff --git a/examples/myappnewapp.coffee b/examples/myappnewapp.coffee
new file mode 100644
index 0000000..f3a65d1
--- /dev/null
+++ b/examples/myappnewapp.coffee
@@ -0,0 +1,37 @@
+express = require 'express'
+$ = require 'jquery'
+
+app = express.createServer(
+ express.bodyParser(),
+ express.favicon(),
+ express.cookieParser(),
+ express.session({ secret: 'supersecret'}),
+)
+
+myAppUrl = 'http://127.0.0.1:3001'
+usrAppToken = 'lalalal'
+usrUrl = "http://local.host:3000"
+
+
+app.get('/', (req, res)->
+ if req.session.user
+ user = req.session.user
+ res.send("Welcome : #{user.id}, you are in the groups : #{user.groups.join(',')}logout")
+ else
+ res.send("login")
+)
+
+app.get('/logout', (req, res)->
+ delete(req.session.user)
+ res.redirect(usrUrl+"/logout/#{myAppUrl}")
+)
+
+app.get('/logguedIn/:token', (req, res)->
+ url = usrUrl+"/info/#{req.params.token}/#{usrAppToken}"
+ $.getJSON(url,(datas)->
+ req.session.user = datas
+ res.redirect('/')
+ )
+)
+
+app.listen(3001)
diff --git a/lib/exec.coffee b/examples/server.coffee
similarity index 82%
rename from lib/exec.coffee
rename to examples/server.coffee
index ca5ce44..d19aff6 100644
--- a/lib/exec.coffee
+++ b/examples/server.coffee
@@ -2,19 +2,18 @@ Async = require 'async'
Log = require 'log'
log = new Log('warning')
-configs = require '../configs'
+configs = require './configs'
express = require 'express'
app = express.createServer(
express.bodyParser(),
- express.static(__dirname + "/public"),
express.favicon(),
express.cookieParser(),
express.session({ secret: 'supersecret'}),
)
app.log = log
-Auth = require './app'
+Auth = require '../index'
auth = new Auth(app,configs)
app.get('/', (req, res)->
@@ -29,4 +28,3 @@ app.configure(()->
app.listen(configs.app.port)
log.info __dirname
log.info 'Application started http://local.host:'+configs.app.port
-module.exports = app
diff --git a/index.js b/index.js
index 7605f9e..f97237a 100644
--- a/index.js
+++ b/index.js
@@ -1,2 +1,2 @@
require('coffee-script')
-module.exports = require('./lib/exec.coffee');
+module.exports = require('./lib/app');
diff --git a/lib/app.coffee b/lib/app.coffee
index 5d90a5d..3a1e8a0 100644
--- a/lib/app.coffee
+++ b/lib/app.coffee
@@ -1,9 +1,12 @@
-
module.exports = class App
constructor : (express,@configs)->
_ = @
- Log = require 'log'
- @log = new Log()
+ if not @configs.logger?
+ Log = require 'log'
+ @log = new Log("warning")
+ else
+ @log = @configs.logger
+
EventEmitter = require('eventemitter2').EventEmitter2
@_event = new EventEmitter(
wildcard:true
@@ -14,17 +17,24 @@ module.exports = class App
#!TODO move this function to access...
@_event.once('token/new',(datas)->
- console.log "Check INIT ROOT ?"
+ _.log.debug "First token has been created maybe a root group need to be created ?"
_.stores.group.findGroupByName('root',(err,group)->
if group == null
- console.log "ROOT NULL ?"
_.stores.group.addGroup('_root',(err,groupId)->
+ _.emit('group/new',
+ groupId : groupId
+ token : datas.token
+ )
_.stores.group.addUserToGroup(datas.userId,groupId,(err,res)->
- if !res
- throw "Error root access granted..."
+ _.emit('group/addUser',
+ groupId : groupId
+ token : datas.token
+ userId : datas.userId
+ )
_.stores.group.addUserToGroupCache(datas.userId,groupId,(err,res)->
if !res
throw "Error root access granted..."
+ # Might be a bit strange, but root seems to proclam himself root
_.emit('root/new',datas)
)
)
@@ -50,7 +60,7 @@ module.exports = class App
'access' : './access/access'
'event' : './event/event'
for name,file of modules
- console.log "Load #{file} as #{name}"
+ @log.info "Load #{file} as #{name}"
Module = require file
@[name] = new Module(@)
diff --git a/lib/auth/auth.coffee b/lib/auth/auth.coffee
index 2c3d7d4..8cea5d3 100644
--- a/lib/auth/auth.coffee
+++ b/lib/auth/auth.coffee
@@ -5,6 +5,7 @@ module.exports = class Auth extends Component
@._everyAuth()
@._routes()
+ #No Check on addUser, everybody can register or create a new user
addUser : (source='', id='', datas={},cb)->
_ = @
store = @app.stores.user
@@ -12,7 +13,9 @@ module.exports = class Auth extends Component
_.checkErr(err)
cb(null,userId)
_.emit('user/new',
- userId:userId
+ userId : userId
+ source : source
+ id : id
)
)
@@ -56,6 +59,17 @@ module.exports = class Auth extends Component
_routes : ()->
_ = @
+
+ #Add a Are you sure on the logout ?
+ @routeGet('/logout/*', (req, res)->
+ req.logout()
+ delete(req.session.token)
+ if req.params? and req.params[0]? and req.params[0] != ''
+ res.redirect(req.params[0])
+ return
+ #!TODO redirect you from where you are coming ?
+ res.redirect('/')#!TODO RENDER LOGIN PAGE
+ )
@routeGet('/login/*', (req, res)->
if req.params? and req.params[0]? and req.params[0] != ''
req.session.url = req.params[0]
@@ -65,6 +79,16 @@ module.exports = class Auth extends Component
res.redirect('/auth/local')#!TODO RENDER LOGIN PAGE
)
+
+ #!TODO Check on AppToken
+ @routeGet('/info/:token/:appToken', (req, res)->
+ json = {}
+ _.app.token.getInfo(req.params.token,req.params.appToken,(err,info)->
+ _.checkErr(err)
+ res.json(info)
+ )
+
+ )
@routeGet('/redirect', (req, res)->
if not req.loggedIn
res.redirect('/login/')
diff --git a/lib/event/event.coffee b/lib/event/event.coffee
index c75b8f3..4acc183 100644
--- a/lib/event/event.coffee
+++ b/lib/event/event.coffee
@@ -4,6 +4,8 @@ module.exports = class Event extends Component
@app = app
@access = app.access
io = require('socket.io').listen(@express())
+ io.set('log level', 1)
+
@channel = io.of('/auth')#!TODO Put in configs...
#@channel = io
@_init_socket()
diff --git a/lib/group/group.coffee b/lib/group/group.coffee
index 13a987c..b396772 100644
--- a/lib/group/group.coffee
+++ b/lib/group/group.coffee
@@ -36,42 +36,55 @@ module.exports = class Group extends Component
add : (groupName, token, cb)->
_ = @
- #!TODO Validate Name with Regex
+ #!TODO Validate Name with Regex and rules
+
+ #Add a new user Group
+ #Add a new group access group
+
+ #Add a new Group
_.app.access.check(token, ['_group_add','_root'],(userId)->
#!TODO check group existence
- _.store.addGroup(groupName, (groupId)->
- cb(groupId)
- _.event.emit('group:new',
+ _.store.addGroup(groupName, (err,groupId)->
+ cb(err,groupId)
+ _.emit('group:new',
groupId : groupId
token : token
+ groupName : groupName
+ authorId : userId
)
)
)
- addUserToGroup : (groupName, userId, token, cb)->
+ addUserToGroup : (userId, groupName, token, cb)->
_ = @
#!TODO Validate Regex
_.app.access.check(token,
[
- 'group_'+groupName+"_"+owner,
- 'group_'+groupName+"_"+add,
+ 'group_'+groupName+"_add",
'_root'
],
- (userId)->
- @store.findGroupByName(groupName,(group)->
- @store.addUserToGroup(group.id,userId,cb)
- @store.addUserToGroupCache(group.id,userId,()->
- _.event.emit('group:addUser',
- groupId : groupId
- token : token
- )
+ (authorId)->
+ _.store.findGroupByName(groupName,(err,group)->
+ _.checkErr(err)
+ _.store.addUserToGroup(userId,group.id,cb)
+ _.emit('group:addUser',
+ groupId : group.id
+ token : token
+ authorId : authorId
+ userId : userId
+ groupName : groupName
)
+ #Add to cache
addUserToGroupCache = (groupId, userId)->
- @store.addUserToGroupCache(i,userId,()->
- _.event.emit('group:addUser',
- groupId : groupId
+ _.store.addUserToGroupCache(userId, groupId,(err,res)->
+ _.checkErr(err)
+ _.emit('group:addUserCache',
+ groupId : group.id
token : token
+ userId : userId
+ groupName : groupName
)
)
+ addUserToGroupCache(group.id, userId)
for i in group._groups
addUserToGroupCache(i, userId)
)
diff --git a/lib/token/token.coffee b/lib/token/token.coffee
index 718f326..13915bd 100644
--- a/lib/token/token.coffee
+++ b/lib/token/token.coffee
@@ -29,7 +29,7 @@ module.exports = class Token extends Component
)
get : (token, cb)->
- @store.get(token, cb)
+ @store.getToken(token, cb)
add : (userId, options, cb)->
_ = @
_.app.stores.token.addToken(
@@ -44,3 +44,28 @@ module.exports = class Token extends Component
userId : userId
)
)
+ #!TODO ADD Check on AppToken
+ getInfo : (token, appToken, cb)->
+ _ = @
+ json = {}
+ _.get(token,(err,datas)->
+ if err != null
+ cb(err,json)
+ return
+ _.app.stores.user.findUserById(datas.userId, (err,user)->
+ if err != null
+ cb(err,json)
+ return
+ json= user
+ _.app.stores.group.getGroupsUserIsMemberOf(user.id, (err,groups)->
+ if err != null
+ cb(err,json)
+ return
+ json.groups = []
+ for k,g of groups
+ json.groups.push(g.name)
+ cb(err,json)
+ return
+ )
+ )
+ )
diff --git a/package.json b/package.json
index d0d9300..0113829 100644
--- a/package.json
+++ b/package.json
@@ -16,22 +16,23 @@
],
"main": "index",
"dependencies": {
- "log": "*",
"coffee-script": ">=1.3",
- "mongodb": "*",
- "everyauth": "*",
- "express": "=2.3.10",
- "node-promise": "*",
- "eventemitter2": "*",
- "async": "*",
- "socket.io": "~0.9.8"
+ "express": "~2.5.9",
+ "everyauth": "~0.2.32",
+ "log": "~1.3.0",
+ "mongodb": "~1.1.2",
+ "node-promise": "~0.5.3",
+ "eventemitter2": "~0.4.9",
+ "async": "~0.1.22",
+ "socket.io": "~0.9.9",
+ "jade": "~0.27.0"
},
"devDependencies": {
"tobi": "*",
"chai": "*",
- "should": "*",
"socket.io-client": "~0.9.8",
- "mocha": "*"
+ "mocha": "*",
+ "jquery": "~1.7.3"
},
"_id": "@0.0.1",
"engines": {
diff --git a/test/access.coffee b/test/access.coffee
deleted file mode 100644
index 66ed97d..0000000
--- a/test/access.coffee
+++ /dev/null
@@ -1,54 +0,0 @@
-should = require('chai').should()
-expect = require('chai').expect()
-tobi = require 'tobi'
-
-describe('Access', ()->
-
- app = {}
- browser = {}
- users = []
- groups = []
- tokens = []
- before((done)->
- app = require('./app')()
- tobi.Browser.browsers = {}
- browser = tobi.createBrowser(3001, 'local.host')
- browser.userAgent = 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.100 Safari/534.30'
- app.auth.addUser('local','ombr0',{},(err,userId)->
- users.push(userId)
- console.log "IDI :"
- console.log userId
- app.token.add(userId,{},(err,token)->
- tokens.push(token)
- console.log "I have a token :-D Hope I'm root ?"
- done()
- )
- )
- )
-
- after(()->
- app.express.close()
- )
-
- describe('Root user', ()->
- it('First user should be root',(done)->
- console.log tokens[0]
- app.access.check(tokens[0], ['_root'],(err,userId)->
- userId.should.eql(users[0])
- done()
- ,'test/root')
- )
- it('Second user should not be root',(done)->
- app.auth.addUser('local','ombr1',{},(err,userId)->
- users.push(userId)
- app.token.add(userId,{},(err,token)->
- tokens.push(token)
- app.access.check(token, ['_root'],(err,userId)->
- err[0].should.eql('Access denied')
- done()
- ,'test/root')
- )
- )
- )
- )
-)
diff --git a/test/access/root.coffee b/test/access/root.coffee
new file mode 100644
index 0000000..87e9d07
--- /dev/null
+++ b/test/access/root.coffee
@@ -0,0 +1,59 @@
+should = require('chai').should()
+expect = require('chai').expect()
+tobi = require 'tobi'
+
+describe('Root Capabilities', ()->
+
+
+ app = {}
+ tool = require '../tool'
+
+ before(()->
+ app = tool.app()
+ )
+
+ after(()->
+ app.express.close()
+ )
+
+ rootToken = null
+ rootId = null
+ it('First user should be root',(done)->
+ tool.user(app, (userId)->
+ rootiId = userId
+ tool.token(app,userId, (token)->
+ rootToken = token
+ setTimeout(()-> #Timeout required for event propagation
+ app.access.check(token, ['_root'],(err,rootId)->
+ rootId.should.eql(userId)
+ done()
+ ,'test/root')
+ ,5)
+ )
+ )
+ )
+ it('Second user should not be root',(done)->
+ tool.user(app, (userId)->
+ tool.token(app,userId, (token)->
+ setTimeout(()-> #Timeout required for event propagation
+ app.access.check(token, ['_root'],(err,rootId)->
+ should.exist(err)
+ should.exist(err[0])
+ err[0].should.eql('Access denied')
+ done()
+ ,'test/root')
+ ,5)
+ )
+ )
+ )
+ it('Should be able to create a group and put himself in it',(done)->
+ groupName = tool._uniq('group')
+ app.group.add(groupName,rootToken,(err,groupId)->
+ app.group.addUserToGroup(rootId,groupName,rootToken,(err,res)->
+ res.should.be.true
+ should.not.exist(err)
+ done()
+ )
+ )
+ )
+)
diff --git a/test/app.coffee b/test/app.coffee
deleted file mode 100644
index d8851e7..0000000
--- a/test/app.coffee
+++ /dev/null
@@ -1,33 +0,0 @@
-module.exports = ()->
- Async = require 'async'
- Log = require 'log'
-
- log = new Log()
- configs = require '../configs-test'
-
- express = require 'express'
- app = express.createServer(
- express.bodyParser(),
- express.static(__dirname + "/public"),
- express.favicon(),
- express.cookieParser(),
- express.session({ secret: 'supersecret'}),
- )
- app.log = log
-
- Auth = require '../lib/app'
- auth = new Auth(app,configs)
-
- app.get('/', (req, res)->
- res.render('index.jade')
- )
-
- app.configure(()->
- app.set('view engine', 'jade')
- app.set('views', __dirname + '/../views')
- )
-
- app.listen(configs.app.port)
- log.info __dirname
- log.info 'Application started http://local.host:'+configs.app.port
- return auth
diff --git a/configs-test.coffee b/test/configs.coffee
similarity index 97%
rename from configs-test.coffee
rename to test/configs.coffee
index 68effc3..e54e476 100644
--- a/configs-test.coffee
+++ b/test/configs.coffee
@@ -6,7 +6,9 @@ module.exports = configs
###
configs.app =
port : process.env.VCAP_APP_PORT or 3001
-
+Log = require 'log'
+configs.logger = new Log('error')
+#configs.logger = new Log()
###
#MONGO
###
diff --git a/test/token/infos.coffee b/test/token/infos.coffee
new file mode 100644
index 0000000..7a3b2d5
--- /dev/null
+++ b/test/token/infos.coffee
@@ -0,0 +1,39 @@
+should = require('chai').should()
+expect = require('chai').expect()
+tobi = require 'tobi'
+
+describe('Token GetInfo', ()->
+
+
+ app = {}
+ tool = require '../tool'
+
+ before(()->
+ app = tool.app()
+ )
+
+ after(()->
+ app.express.close()
+ )
+
+ rootToken = null
+ rootId = null
+ it('Root user should be able to get Info',(done)->
+ tool.user(app, (userId)->
+ rootId = userId
+ tool.token(app,userId, (token)->
+ rootToken = token
+ setTimeout(()-> #Timeout required for event propagation
+ app.token.getInfo(token,(err,infos)->
+ should.not.exist(err)
+ should.exist(infos)
+ infos.id.should.eql rootId
+ should.exist(infos.groups)
+ infos.groups.should.contain "_root"
+ done()
+ )
+ ,5)
+ )
+ )
+ )
+)
diff --git a/test/tool.coffee b/test/tool.coffee
new file mode 100644
index 0000000..a924b97
--- /dev/null
+++ b/test/tool.coffee
@@ -0,0 +1,61 @@
+class Tool
+
+ app:()->
+ configs = require './configs'
+
+ express = require 'express'
+ app = express.createServer(
+ express.bodyParser(),
+ express.static(__dirname + "/public"),
+ express.favicon(),
+ express.cookieParser(),
+ express.session({ secret: 'supersecret'}),
+ )
+
+ Auth = require '../lib/app'
+ auth = new Auth(app,configs)
+
+ app.get('/', (req, res)->
+ res.render('index.jade')
+ )
+
+ app.configure(()->
+ app.set('view engine', 'jade')
+ app.set('views', __dirname + '/../views')
+ )
+ app.listen(configs.app.port)
+ return auth
+ #Will Return the user or a new user
+ user : (app, cb, name)->
+ if not name?
+ name = @_uniq('user')
+ app.auth.addUser('local',name,{},(err,userId)->
+ if err != null
+ throw "An Error occured"
+ cb(userId)
+ )
+ group: (app, cb, name)->
+ if not name?
+ name = @_uniq('user')
+ app.stores.group.findByName(name,(err,group)->
+ if err != null
+ app.stores.group.add(name, (err,groupId)->
+ cb(groupId)
+ )
+ return
+ cb(group.id)
+ )
+
+ token : (app,userId,cb)->
+ app.token.add(userId,{}, (err,token)->
+ if err != null
+ throw "An Error occured"
+ cb(token)
+ )
+
+ _uniq:(prefix = '')->
+ timestamp = new Date().getTime()
+ id = Math.round( timestamp+""+Math.round(Math.random()*1000))
+ return prefix+id
+
+module.exports = new Tool()