├── .gitignore ├── .travis.yml ├── .vscode └── settings.json ├── README.md ├── app.js ├── bin └── www ├── components └── oauth │ ├── authenticate.js │ ├── express.js │ ├── index.js │ ├── models.js │ ├── mongo-models.js │ ├── mongodb │ ├── OAuthAccessToken.js │ ├── OAuthAuthorizationCode.js │ ├── OAuthClient.js │ ├── OAuthRefreshToken.js │ ├── OAuthScope.js │ ├── Thing.js │ ├── User.js │ └── index.js │ ├── oauth.js │ ├── seed-mongo.js │ ├── seed.js │ └── sqldb │ ├── OAuthAccessToken.js │ ├── OAuthAuthorizationCode.js │ ├── OAuthClient.js │ ├── OAuthRefreshToken.js │ ├── OAuthScope.js │ ├── Thing.js │ ├── User.js │ └── index.js ├── config.js ├── mongo-dump ├── oauthaccesstokens.json ├── oauthauthorizationcodes.json ├── oauthclients.json ├── oauthscopes.json ├── refreshtokens.json └── users.json ├── package.json ├── public └── stylesheets │ └── style.css ├── routes ├── index.js └── users.js ├── sql └── oauth_demo.sql ├── test └── unit │ └── password_grant_test.js ├── views ├── error.jade ├── index.jade └── layout.jade └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | ### Node template 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directory 28 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 29 | node_modules 30 | 31 | # Created by .ignore support plugin (hsz.mobi) 32 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - 4 5 | - 4.0 6 | - 6 7 | - 6.0 8 | - 7 9 | - 7.0 10 | 11 | sudo: false -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node OAuth2 Server Implementation 2 | 3 | Please refer this [Fully functional OAuth 2.0 Implementation with production example](https://identity.parkenconsulting.com/guide/nodejs-oauth-implementation.html) with [node-oauth2-server#2.4.0](https://www.npmjs.com/package/node-oauth2-server) 4 | 5 | Supports ` "oauth2-server": "^3.0.0-b2",` 6 | 7 | ## Installation 8 | 9 | ``` 10 | git clone https://github.com/manjeshpv/node-oauth2-server-implementation 11 | npm install 12 | npm start or node ./bin/www 13 | ``` 14 | 15 | ## Quick Start 16 | 17 | The module provides two middlewares, one for authorization and routing, another for error handling, use them as you would any other middleware: 18 | 19 | ```js 20 | var express = require('express'); 21 | var oauthServer = require('oauth2-server'); 22 | var Request = oauthServer.Request; 23 | var Response = oauthServer.Response; 24 | var authenticate = require('./components/oauth/authenticate') 25 | 26 | var app = express(); 27 | 28 | app.use(bodyParser.urlencoded({ extended: true })); 29 | 30 | app.use(bodyParser.json()); 31 | 32 | // https://github.com/manjeshpv/node-oauth2-server-implementation/blob/master/components/oauth/models.js 33 | var oauth = new oauthServer({ 34 | model: require('./models.js') 35 | }); 36 | 37 | app.all('/oauth/token', function(req,res,next){ 38 | var request = new Request(req); 39 | var response = new Response(res); 40 | 41 | oauth 42 | .token(request,response) 43 | .then(function(token) { 44 | // Todo: remove unnecessary values in response 45 | return res.json(token) 46 | }).catch(function(err){ 47 | return res.status( 500).json(err) 48 | }) 49 | }); 50 | 51 | app.post('/authorise', function(req, res){ 52 | var request = new Request(req); 53 | var response = new Response(res); 54 | 55 | return oauth.authorize(request, response).then(function(success) { 56 | res.json(success) 57 | }).catch(function(err){ 58 | res.status(err.code || 500).json(err) 59 | }) 60 | }); 61 | 62 | app.get('/secure', authenticate(), function(req,res){ 63 | res.json({message: 'Secure data'}) 64 | }); 65 | 66 | app.get('/me', authenticate(), function(req,res){ 67 | res.json({ 68 | me: req.user, 69 | messsage: 'Authorization success, Without Scopes, Try accessing /profile with `profile` scope', 70 | description: 'Try postman https://www.getpostman.com/collections/37afd82600127fbeef28', 71 | more: 'pass `profile` scope while Authorize' 72 | }) 73 | }); 74 | 75 | app.get('/profile', authenticate({scope:'profile'}), function(req,res){ 76 | res.json({ 77 | profile: req.user 78 | }) 79 | }); 80 | 81 | app.listen(3000); 82 | ``` 83 | 84 | After running with node, visting http://127.0.0.1:3000 should present you with a json response saying your access token could not be found. 85 | 86 | To simulate, Use Postman: https://www.getpostman.com/collections/37afd82600127fbeef28 87 | 88 | ## Features 89 | 90 | - Supports authorization_code, password, refresh_token, client_credentials and extension (custom) grant types 91 | - Implicitly supports any form of storage e.g. PostgreSQL, MySQL, Mongo, Redis... 92 | - Full test suite 93 | 94 | ## Model Specification 95 | 96 | See SQL file in `/sql` folder 97 | 98 | The module requires a model object through which some aspects or storage, retrieval and custom validation are abstracted. 99 | The last parameter of all methods is a callback of which the first parameter is always used to indicate an error. 100 | 101 | Note: see https://github.com/manjeshpv/node-oauth2-server-implementation/blob/master/components/oauth/models.js for a full model example using MySQL. 102 | 103 | References: 104 | https://github.com/dsquier/oauth2-server-php-mysql 105 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | var config = require('./config.js') 8 | var authenticate = require('./components/oauth/authenticate') 9 | var routes = require('./routes/index'); 10 | var users = require('./routes/users'); 11 | 12 | var app = express(); 13 | 14 | // view engine setup 15 | app.set('views', path.join(__dirname, 'views')); 16 | app.set('view engine', 'jade'); 17 | 18 | // uncomment after placing your favicon in /public 19 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 20 | app.use(logger('dev')); 21 | app.use(bodyParser.json()); 22 | app.use(bodyParser.urlencoded({ extended: false })); 23 | app.use(cookieParser()); 24 | app.use(express.static(path.join(__dirname, 'public'))); 25 | 26 | if (config.seedDB) { require('./components/oauth/seed'); } 27 | if (config.seedMongoDB) { require('./components/oauth/seed-mongo'); } 28 | 29 | /** Public Area **/ 30 | 31 | require('./components/oauth')(app) 32 | 33 | /** Control Private through OAuth **/ 34 | 35 | app.use('/', routes); 36 | app.use('/users', users); 37 | 38 | app.get('/secure', authenticate(), function(req,res){ 39 | res.json({message: 'Secure data'}) 40 | }); 41 | 42 | app.get('/me', authenticate(), function(req,res){ 43 | res.json({ 44 | me: req.user, 45 | messsage: 'Authorization success, Without Scopes, Try accessing /profile with `profile` scope', 46 | description: 'Try postman https://www.getpostman.com/collections/37afd82600127fbeef28', 47 | more: 'pass `profile` scope while Authorize' 48 | }) 49 | }); 50 | 51 | app.get('/profile', authenticate({scope:'profile'}), function(req,res){ 52 | res.json({ 53 | profile: req.user 54 | }) 55 | }); 56 | 57 | // catch 404 and forward to error handler 58 | app.use(function(req, res, next) { 59 | var err = new Error('Not Found'); 60 | err.status = 404; 61 | next(err); 62 | }); 63 | 64 | // error handlers 65 | 66 | // development error handler 67 | // will print stacktrace 68 | if (app.get('env') === 'development') { 69 | app.use(function(err, req, res, next) { 70 | res.status(err.status || 500); 71 | res.render('error', { 72 | message: err.message, 73 | error: err 74 | }); 75 | }); 76 | } 77 | 78 | // production error handler 79 | // no stacktraces leaked to user 80 | app.use(function(err, req, res, next) { 81 | res.status(err.status || 500); 82 | res.render('error', { 83 | message: err.message, 84 | error: {} 85 | }); 86 | }); 87 | 88 | app.listen(3000); 89 | 90 | 91 | module.exports = app; 92 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('node-oauth2-server-component:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port,function(){ 29 | console.log('Express server listening on %d', port); 30 | }); 31 | server.on('error', onError); 32 | server.on('listening', onListening); 33 | 34 | /** 35 | * Normalize a port into a number, string, or false. 36 | */ 37 | 38 | function normalizePort(val) { 39 | var port = parseInt(val, 10); 40 | 41 | if (isNaN(port)) { 42 | // named pipe 43 | return val; 44 | } 45 | 46 | if (port >= 0) { 47 | // port number 48 | return port; 49 | } 50 | 51 | return false; 52 | } 53 | 54 | /** 55 | * Event listener for HTTP server "error" event. 56 | */ 57 | 58 | function onError(error) { 59 | if (error.syscall !== 'listen') { 60 | throw error; 61 | } 62 | 63 | var bind = typeof port === 'string' 64 | ? 'Pipe ' + port 65 | : 'Port ' + port; 66 | 67 | // handle specific listen errors with friendly messages 68 | switch (error.code) { 69 | case 'EACCES': 70 | console.error(bind + ' requires elevated privileges'); 71 | process.exit(1); 72 | break; 73 | case 'EADDRINUSE': 74 | console.error(bind + ' is already in use'); 75 | process.exit(1); 76 | break; 77 | default: 78 | throw error; 79 | } 80 | } 81 | 82 | /** 83 | * Event listener for HTTP server "listening" event. 84 | */ 85 | 86 | function onListening() { 87 | var addr = server.address(); 88 | var bind = typeof addr === 'string' 89 | ? 'pipe ' + addr 90 | : 'port ' + addr.port; 91 | debug('Listening on ' + bind); 92 | } 93 | -------------------------------------------------------------------------------- /components/oauth/authenticate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | var oauthServer = require('oauth2-server'); 6 | var Request = oauthServer.Request; 7 | var Response = oauthServer.Response; 8 | var db = require('./sqldb') 9 | var config = require('../../config'); 10 | if(config.db === 'mongo'){ 11 | db = require('./mongodb') 12 | } 13 | var oauth = require('./oauth') 14 | 15 | module.exports = function(options){ 16 | var options = options || {}; 17 | return function(req, res, next) { 18 | var request = new Request({ 19 | headers: {authorization: req.headers.authorization}, 20 | method: req.method, 21 | query: req.query, 22 | body: req.body 23 | }); 24 | var response = new Response(res); 25 | 26 | oauth.authenticate(request, response,options) 27 | .then(function (token) { 28 | // Request is authorized. 29 | req.user = token 30 | next() 31 | }) 32 | .catch(function (err) { 33 | // Request is not authorized. 34 | res.status(err.code || 500).json(err) 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /components/oauth/express.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | var oauthServer = require('oauth2-server'); 6 | var Request = oauthServer.Request; 7 | var Response = oauthServer.Response; 8 | var config = require('../../config'); 9 | var db = config.db==='mongo' ? require('./mongodb') : require('./sqldb'); 10 | 11 | var oauth = require('./oauth') 12 | 13 | module.exports = function(app){ 14 | app.all('/oauth/token', function(req,res,next){ 15 | var request = new Request(req); 16 | var response = new Response(res); 17 | 18 | oauth 19 | .token(request,response) 20 | .then(function(token) { 21 | // Todo: remove unnecessary values in response 22 | return res.json(token) 23 | }).catch(function(err){ 24 | return res.status(500).json(err) 25 | }) 26 | }); 27 | 28 | app.post('/authorise', function(req, res){ 29 | var request = new Request(req); 30 | var response = new Response(res); 31 | 32 | return oauth.authorize(request, response).then(function(success) { 33 | // if (req.body.allow !== 'true') return callback(null, false); 34 | // return callback(null, true, req.user); 35 | res.json(success) 36 | }).catch(function(err){ 37 | res.status(err.code || 500).json(err) 38 | }) 39 | }); 40 | 41 | app.get('/authorise', function(req, res) { 42 | return db.OAuthClient.findOne({ 43 | where: { 44 | client_id: req.query.client_id, 45 | redirect_uri: req.query.redirect_uri, 46 | }, 47 | attributes: ['id', 'name'], 48 | }) 49 | .then(function(model) { 50 | if (!model) return res.status(404).json({ error: 'Invalid Client' }); 51 | return res.json(model); 52 | }).catch(function(err){ 53 | return res.status(err.code || 500).json(err) 54 | }); 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /components/oauth/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | module.exports = function(app){ 6 | require('./express')(app) 7 | } -------------------------------------------------------------------------------- /components/oauth/models.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | var _ = require('lodash'); 6 | var sqldb = require('./sqldb'); 7 | var User = sqldb.User; 8 | var OAuthClient = sqldb.OAuthClient; 9 | var OAuthAccessToken = sqldb.OAuthAccessToken; 10 | var OAuthAuthorizationCode = sqldb.OAuthAuthorizationCode; 11 | var OAuthRefreshToken = sqldb.OAuthRefreshToken; 12 | 13 | function getAccessToken(bearerToken) { 14 | return OAuthAccessToken 15 | .findOne({ 16 | where: {access_token: bearerToken}, 17 | attributes: [['access_token', 'accessToken'], ['expires', 'accessTokenExpiresAt'],'scope'], 18 | include: [ 19 | { 20 | model: User, 21 | attributes: ['id', 'username'], 22 | }, OAuthClient 23 | ], 24 | }) 25 | .then(function (accessToken) { 26 | if (!accessToken) return false; 27 | var token = accessToken.toJSON(); 28 | token.user = token.User; 29 | token.client = token.OAuthClient; 30 | token.scope = token.scope 31 | return token; 32 | }) 33 | .catch(function (err) { 34 | console.log("getAccessToken - Err: ") 35 | }); 36 | } 37 | 38 | function getClient(clientId, clientSecret) { 39 | const options = { 40 | where: {client_id: clientId}, 41 | attributes: ['id', 'client_id', 'redirect_uri', 'scope'], 42 | }; 43 | if (clientSecret) options.where.client_secret = clientSecret; 44 | 45 | return sqldb.OAuthClient 46 | .findOne(options) 47 | .then(function (client) { 48 | if (!client) return new Error("client not found"); 49 | var clientWithGrants = client.toJSON() 50 | clientWithGrants.grants = ['authorization_code', 'password', 'refresh_token', 'client_credentials'] 51 | // Todo: need to create another table for redirect URIs 52 | clientWithGrants.redirectUris = [clientWithGrants.redirect_uri] 53 | delete clientWithGrants.redirect_uri 54 | //clientWithGrants.refreshTokenLifetime = integer optional 55 | //clientWithGrants.accessTokenLifetime = integer optional 56 | return clientWithGrants 57 | }).catch(function (err) { 58 | console.log("getClient - Err: ", err) 59 | }); 60 | } 61 | 62 | 63 | function getUser(username, password) { 64 | return User 65 | .findOne({ 66 | where: {username: username}, 67 | attributes: ['id', 'username', 'password', 'scope'], 68 | }) 69 | .then(function (user) { 70 | return user.password == password ? user.toJSON() : false; 71 | }) 72 | .catch(function (err) { 73 | console.log("getUser - Err: ", err) 74 | }); 75 | } 76 | 77 | function revokeAuthorizationCode(code) { 78 | return OAuthAuthorizationCode.findOne({ 79 | where: { 80 | authorization_code: code.code 81 | } 82 | }).then(function (rCode) { 83 | //if(rCode) rCode.destroy(); 84 | /*** 85 | * As per the discussion we need set older date 86 | * revokeToken will expected return a boolean in future version 87 | * https://github.com/oauthjs/node-oauth2-server/pull/274 88 | * https://github.com/oauthjs/node-oauth2-server/issues/290 89 | */ 90 | var expiredCode = code 91 | expiredCode.expiresAt = new Date('2015-05-28T06:59:53.000Z') 92 | return expiredCode 93 | }).catch(function (err) { 94 | console.log("getUser - Err: ", err) 95 | }); 96 | } 97 | 98 | function revokeToken(token) { 99 | return OAuthRefreshToken.findOne({ 100 | where: { 101 | refresh_token: token.refreshToken 102 | } 103 | }).then(function (rT) { 104 | if (rT) rT.destroy(); 105 | /*** 106 | * As per the discussion we need set older date 107 | * revokeToken will expected return a boolean in future version 108 | * https://github.com/oauthjs/node-oauth2-server/pull/274 109 | * https://github.com/oauthjs/node-oauth2-server/issues/290 110 | */ 111 | var expiredToken = token 112 | expiredToken.refreshTokenExpiresAt = new Date('2015-05-28T06:59:53.000Z') 113 | return expiredToken 114 | }).catch(function (err) { 115 | console.log("revokeToken - Err: ", err) 116 | }); 117 | } 118 | 119 | 120 | function saveToken(token, client, user) { 121 | return Promise.all([ 122 | OAuthAccessToken.create({ 123 | access_token: token.accessToken, 124 | expires: token.accessTokenExpiresAt, 125 | client_id: client.id, 126 | user_id: user.id, 127 | scope: token.scope 128 | }), 129 | token.refreshToken ? OAuthRefreshToken.create({ // no refresh token for client_credentials 130 | refresh_token: token.refreshToken, 131 | expires: token.refreshTokenExpiresAt, 132 | client_id: client.id, 133 | user_id: user.id, 134 | scope: token.scope 135 | }) : [], 136 | 137 | ]) 138 | .then(function (resultsArray) { 139 | return _.assign( // expected to return client and user, but not returning 140 | { 141 | client: client, 142 | user: user, 143 | access_token: token.accessToken, // proxy 144 | refresh_token: token.refreshToken, // proxy 145 | }, 146 | token 147 | ) 148 | }) 149 | .catch(function (err) { 150 | console.log("revokeToken - Err: ", err) 151 | }); 152 | } 153 | 154 | function getAuthorizationCode(code) { 155 | return OAuthAuthorizationCode 156 | .findOne({ 157 | attributes: ['client_id', 'expires', 'user_id', 'scope'], 158 | where: {authorization_code: code}, 159 | include: [User, OAuthClient] 160 | }) 161 | .then(function (authCodeModel) { 162 | if (!authCodeModel) return false; 163 | var client = authCodeModel.OAuthClient.toJSON() 164 | var user = authCodeModel.User.toJSON() 165 | return reCode = { 166 | code: code, 167 | client: client, 168 | expiresAt: authCodeModel.expires, 169 | redirectUri: client.redirect_uri, 170 | user: user, 171 | scope: authCodeModel.scope, 172 | }; 173 | }).catch(function (err) { 174 | console.log("getAuthorizationCode - Err: ", err) 175 | }); 176 | } 177 | 178 | function saveAuthorizationCode(code, client, user) { 179 | return OAuthAuthorizationCode 180 | .create({ 181 | expires: code.expiresAt, 182 | client_id: client.id, 183 | authorization_code: code.authorizationCode, 184 | user_id: user.id, 185 | scope: code.scope 186 | }) 187 | .then(function () { 188 | code.code = code.authorizationCode 189 | return code 190 | }).catch(function (err) { 191 | console.log("saveAuthorizationCode - Err: ", err) 192 | }); 193 | } 194 | 195 | function getUserFromClient(client) { 196 | var options = { 197 | where: {client_id: client.client_id}, 198 | include: [User], 199 | attributes: ['id', 'client_id', 'redirect_uri'], 200 | }; 201 | if (client.client_secret) options.where.client_secret = client.client_secret; 202 | 203 | return OAuthClient 204 | .findOne(options) 205 | .then(function (client) { 206 | if (!client) return false; 207 | if (!client.User) return false; 208 | return client.User.toJSON(); 209 | }).catch(function (err) { 210 | console.log("getUserFromClient - Err: ", err) 211 | }); 212 | } 213 | 214 | function getRefreshToken(refreshToken) { 215 | if (!refreshToken || refreshToken === 'undefined') return false 216 | 217 | return OAuthRefreshToken 218 | .findOne({ 219 | attributes: ['client_id', 'user_id', 'expires'], 220 | where: {refresh_token: refreshToken}, 221 | include: [OAuthClient, User] 222 | 223 | }) 224 | .then(function (savedRT) { 225 | var tokenTemp = { 226 | user: savedRT ? savedRT.User.toJSON() : {}, 227 | client: savedRT ? savedRT.OAuthClient.toJSON() : {}, 228 | refreshTokenExpiresAt: savedRT ? new Date(savedRT.expires) : null, 229 | refreshToken: refreshToken, 230 | refresh_token: refreshToken, 231 | scope: savedRT.scope 232 | }; 233 | return tokenTemp; 234 | 235 | }).catch(function (err) { 236 | console.log("getRefreshToken - Err: ", err) 237 | }); 238 | } 239 | 240 | function validateScope(token, client) { 241 | return (user.scope === scope && client.scope === scope && scope !== null) ? scope : false 242 | } 243 | 244 | function verifyScope(token, scope) { 245 | return token.scope === scope 246 | } 247 | 248 | module.exports = { 249 | //generateOAuthAccessToken, optional - used for jwt 250 | //generateAuthorizationCode, optional 251 | //generateOAuthRefreshToken, - optional 252 | getAccessToken: getAccessToken, 253 | getAuthorizationCode: getAuthorizationCode, //getOAuthAuthorizationCode renamed to, 254 | getClient: getClient, 255 | getRefreshToken: getRefreshToken, 256 | getUser: getUser, 257 | getUserFromClient: getUserFromClient, 258 | //grantTypeAllowed, Removed in oauth2-server 3.0 259 | revokeAuthorizationCode: revokeAuthorizationCode, 260 | revokeToken: revokeToken, 261 | saveToken: saveToken,//saveOAuthAccessToken, renamed to 262 | saveAuthorizationCode: saveAuthorizationCode, //renamed saveOAuthAuthorizationCode, 263 | validateScope: validateScope, 264 | verifyScope: verifyScope, 265 | } 266 | 267 | -------------------------------------------------------------------------------- /components/oauth/mongo-models.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | var _ = require('lodash'); 6 | var mongodb = require('./mongodb'); 7 | var User = mongodb.User; 8 | var OAuthClient = mongodb.OAuthClient; 9 | var OAuthAccessToken = mongodb.OAuthAccessToken; 10 | var OAuthAuthorizationCode = mongodb.OAuthAuthorizationCode; 11 | var OAuthRefreshToken = mongodb.OAuthRefreshToken; 12 | 13 | function getAccessToken(bearerToken) { 14 | console.log("getAccessToken",bearerToken) 15 | return OAuthAccessToken 16 | //User,OAuthClient 17 | .findOne({access_token: bearerToken}) 18 | .populate('User') 19 | .populate('OAuthClient') 20 | .then(function (accessToken) { 21 | console.log('at',accessToken) 22 | if (!accessToken) return false; 23 | var token = accessToken; 24 | token.user = token.User; 25 | token.client = token.OAuthClient; 26 | token.scope = token.scope 27 | return token; 28 | }) 29 | .catch(function (err) { 30 | console.log("getAccessToken - Err: ") 31 | }); 32 | } 33 | 34 | function getClient(clientId, clientSecret) { 35 | console.log("getClient",clientId, clientSecret) 36 | const options = {client_id: clientId}; 37 | if (clientSecret) options.client_secret = clientSecret; 38 | 39 | return OAuthClient 40 | .findOne(options) 41 | .then(function (client) { 42 | if (!client) return new Error("client not found"); 43 | var clientWithGrants = client 44 | clientWithGrants.grants = ['authorization_code', 'password', 'refresh_token', 'client_credentials'] 45 | // Todo: need to create another table for redirect URIs 46 | clientWithGrants.redirectUris = [clientWithGrants.redirect_uri] 47 | delete clientWithGrants.redirect_uri 48 | //clientWithGrants.refreshTokenLifetime = integer optional 49 | //clientWithGrants.accessTokenLifetime = integer optional 50 | return clientWithGrants 51 | }).catch(function (err) { 52 | console.log("getClient - Err: ", err) 53 | }); 54 | } 55 | 56 | 57 | function getUser(username, password) { 58 | return User 59 | .findOne({username: username}) 60 | .then(function (user) { 61 | console.log("u",user) 62 | return user.password === password ? user : false; 63 | }) 64 | .catch(function (err) { 65 | console.log("getUser - Err: ", err) 66 | }); 67 | } 68 | 69 | function revokeAuthorizationCode(code) { 70 | console.log("revokeAuthorizationCode",code) 71 | return OAuthAuthorizationCode.findOne({ 72 | where: { 73 | authorization_code: code.code 74 | } 75 | }).then(function (rCode) { 76 | //if(rCode) rCode.destroy(); 77 | /*** 78 | * As per the discussion we need set older date 79 | * revokeToken will expected return a boolean in future version 80 | * https://github.com/oauthjs/node-oauth2-server/pull/274 81 | * https://github.com/oauthjs/node-oauth2-server/issues/290 82 | */ 83 | var expiredCode = code 84 | expiredCode.expiresAt = new Date('2015-05-28T06:59:53.000Z') 85 | return expiredCode 86 | }).catch(function (err) { 87 | console.log("getUser - Err: ", err) 88 | }); 89 | } 90 | 91 | function revokeToken(token) { 92 | console.log("revokeToken",token) 93 | return OAuthRefreshToken.findOne({ 94 | where: { 95 | refresh_token: token.refreshToken 96 | } 97 | }).then(function (rT) { 98 | if (rT) rT.destroy(); 99 | /*** 100 | * As per the discussion we need set older date 101 | * revokeToken will expected return a boolean in future version 102 | * https://github.com/oauthjs/node-oauth2-server/pull/274 103 | * https://github.com/oauthjs/node-oauth2-server/issues/290 104 | */ 105 | var expiredToken = token 106 | expiredToken.refreshTokenExpiresAt = new Date('2015-05-28T06:59:53.000Z') 107 | return expiredToken 108 | }).catch(function (err) { 109 | console.log("revokeToken - Err: ", err) 110 | }); 111 | } 112 | 113 | 114 | function saveToken(token, client, user) { 115 | console.log("saveToken",token, client, user) 116 | return Promise.all([ 117 | OAuthAccessToken.create({ 118 | access_token: token.accessToken, 119 | expires: token.accessTokenExpiresAt, 120 | OAuthClient: client._id, 121 | User: user._id, 122 | scope: token.scope 123 | }), 124 | token.refreshToken ? OAuthRefreshToken.create({ // no refresh token for client_credentials 125 | refresh_token: token.refreshToken, 126 | expires: token.refreshTokenExpiresAt, 127 | OAuthClient: client._id, 128 | User: user._id, 129 | scope: token.scope 130 | }) : [], 131 | 132 | ]) 133 | .then(function (resultsArray) { 134 | return _.assign( // expected to return client and user, but not returning 135 | { 136 | client: client, 137 | user: user, 138 | access_token: token.accessToken, // proxy 139 | refresh_token: token.refreshToken, // proxy 140 | }, 141 | token 142 | ) 143 | }) 144 | .catch(function (err) { 145 | console.log("revokeToken - Err: ", err) 146 | }); 147 | } 148 | 149 | function getAuthorizationCode(code) { 150 | console.log("getAuthorizationCode",code) 151 | return OAuthAuthorizationCode 152 | .findOne({authorization_code: code}) 153 | .populate('User') 154 | .populate('OAuthClient') 155 | .then(function (authCodeModel) { 156 | if (!authCodeModel) return false; 157 | var client = authCodeModel.OAuthClient 158 | var user = authCodeModel.User 159 | return reCode = { 160 | code: code, 161 | client: client, 162 | expiresAt: authCodeModel.expires, 163 | redirectUri: client.redirect_uri, 164 | user: user, 165 | scope: authCodeModel.scope, 166 | }; 167 | }).catch(function (err) { 168 | console.log("getAuthorizationCode - Err: ", err) 169 | }); 170 | } 171 | 172 | function saveAuthorizationCode(code, client, user) { 173 | console.log("saveAuthorizationCode",code, client, user) 174 | return OAuthAuthorizationCode 175 | .create({ 176 | expires: code.expiresAt, 177 | OAuthClient: client._id, 178 | authorization_code: code.authorizationCode, 179 | User: user._id, 180 | scope: code.scope 181 | }) 182 | .then(function () { 183 | code.code = code.authorizationCode 184 | return code 185 | }).catch(function (err) { 186 | console.log("saveAuthorizationCode - Err: ", err) 187 | }); 188 | } 189 | 190 | function getUserFromClient(client) { 191 | console.log("getUserFromClient", client) 192 | var options = {client_id: client.client_id}; 193 | if (client.client_secret) options.client_secret = client.client_secret; 194 | 195 | return OAuthClient 196 | .findOne(options) 197 | .populate('User') 198 | .then(function (client) { 199 | console.log(client) 200 | if (!client) return false; 201 | if (!client.User) return false; 202 | return client.User; 203 | }).catch(function (err) { 204 | console.log("getUserFromClient - Err: ", err) 205 | }); 206 | } 207 | 208 | function getRefreshToken(refreshToken) { 209 | console.log("getRefreshToken", refreshToken) 210 | if (!refreshToken || refreshToken === 'undefined') return false 211 | //[OAuthClient, User] 212 | return OAuthRefreshToken 213 | .findOne({refresh_token: refreshToken}) 214 | .populate('User') 215 | .populate('OAuthClient') 216 | .then(function (savedRT) { 217 | console.log("srt",savedRT) 218 | var tokenTemp = { 219 | user: savedRT ? savedRT.User : {}, 220 | client: savedRT ? savedRT.OAuthClient : {}, 221 | refreshTokenExpiresAt: savedRT ? new Date(savedRT.expires) : null, 222 | refreshToken: refreshToken, 223 | refresh_token: refreshToken, 224 | scope: savedRT.scope 225 | }; 226 | return tokenTemp; 227 | 228 | }).catch(function (err) { 229 | console.log("getRefreshToken - Err: ", err) 230 | }); 231 | } 232 | 233 | function validateScope(token, client, scope) { 234 | console.log("validateScope", token, client, scope) 235 | return (user.scope === client.scope) ? scope : false 236 | } 237 | 238 | function verifyScope(token, scope) { 239 | console.log("verifyScope", token, scope) 240 | return token.scope === scope 241 | } 242 | module.exports = { 243 | //generateOAuthAccessToken, optional - used for jwt 244 | //generateAuthorizationCode, optional 245 | //generateOAuthRefreshToken, - optional 246 | getAccessToken: getAccessToken, 247 | getAuthorizationCode: getAuthorizationCode, //getOAuthAuthorizationCode renamed to, 248 | getClient: getClient, 249 | getRefreshToken: getRefreshToken, 250 | getUser: getUser, 251 | getUserFromClient: getUserFromClient, 252 | //grantTypeAllowed, Removed in oauth2-server 3.0 253 | revokeAuthorizationCode: revokeAuthorizationCode, 254 | revokeToken: revokeToken, 255 | saveToken: saveToken,//saveOAuthAccessToken, renamed to 256 | saveAuthorizationCode: saveAuthorizationCode, //renamed saveOAuthAuthorizationCode, 257 | //validateScope: validateScope, 258 | verifyScope: verifyScope, 259 | } 260 | 261 | -------------------------------------------------------------------------------- /components/oauth/mongodb/OAuthAccessToken.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var mongoose = require('mongoose'), 8 | Schema = mongoose.Schema; 9 | 10 | var OAuthAccessTokenSchema = new Schema({ 11 | access_token: String, 12 | expires: Date, 13 | scope: String, 14 | User: { type : Schema.Types.ObjectId, ref: 'User' }, 15 | OAuthClient: { type : Schema.Types.ObjectId, ref: 'OAuthClient' }, 16 | }); 17 | 18 | module.exports = mongoose.model('OAuthAccessToken', OAuthAccessTokenSchema); 19 | -------------------------------------------------------------------------------- /components/oauth/mongodb/OAuthAuthorizationCode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var mongoose = require('mongoose'), 8 | Schema = mongoose.Schema; 9 | 10 | var OAuthAuthorizationCodeSchema = new Schema({ 11 | authorization_code: String, 12 | expires: Date, 13 | redirect_uri: String, 14 | scope: String, 15 | User: { type : Schema.Types.ObjectId, ref: 'User' }, 16 | OAuthClient: { type : Schema.Types.ObjectId, ref: 'OAuthClient' }, 17 | }); 18 | 19 | module.exports = mongoose.model('OAuthAuthorizationCode', OAuthAuthorizationCodeSchema); 20 | 21 | -------------------------------------------------------------------------------- /components/oauth/mongodb/OAuthClient.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | var mongoose = require('mongoose'), 6 | Schema = mongoose.Schema; 7 | 8 | var OAuthClientSchema = new Schema({ 9 | name: String, 10 | client_id: String, 11 | client_secret: String, 12 | redirect_uri: String, 13 | grant_types: String, 14 | scope: String, 15 | User: { type : Schema.Types.ObjectId, ref: 'User' }, 16 | }); 17 | 18 | module.exports = mongoose.model('OAuthClient', OAuthClientSchema); 19 | 20 | -------------------------------------------------------------------------------- /components/oauth/mongodb/OAuthRefreshToken.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | var mongoose = require('mongoose'), 7 | Schema = mongoose.Schema; 8 | 9 | var RefreshTokenSchema = new Schema({ 10 | refresh_token: String, 11 | expires: Date, 12 | scope: String, 13 | User: { type : Schema.Types.ObjectId, ref: 'User' }, 14 | OAuthClient: { type : Schema.Types.ObjectId, ref: 'OAuthClient' }, 15 | }); 16 | 17 | module.exports = mongoose.model('RefreshToken', RefreshTokenSchema); 18 | -------------------------------------------------------------------------------- /components/oauth/mongodb/OAuthScope.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | var mongoose = require('mongoose'), 7 | Schema = mongoose.Schema; 8 | 9 | var OAuthScopeSchema = new Schema({ 10 | scope: String, 11 | is_default: Boolean 12 | }); 13 | 14 | module.exports = mongoose.model('OAuthScope', OAuthScopeSchema); 15 | -------------------------------------------------------------------------------- /components/oauth/mongodb/Thing.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var mongoose = require('mongoose'), 4 | Schema = mongoose.Schema; 5 | 6 | var ThingSchema = new Schema({ 7 | name: String, 8 | info: String, 9 | active: Boolean 10 | }); 11 | 12 | module.exports = mongoose.model('Thing', ThingSchema); 13 | 14 | -------------------------------------------------------------------------------- /components/oauth/mongodb/User.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | var mongoose = require('mongoose'), 7 | Schema = mongoose.Schema; 8 | 9 | var UserSchema = new Schema({ 10 | username: String, 11 | password: String, 12 | scope: String 13 | }); 14 | 15 | module.exports = mongoose.model('User', UserSchema); 16 | 17 | -------------------------------------------------------------------------------- /components/oauth/mongodb/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | /** https://github.com/dsquier/oauth2-server-php-mysql **/ 6 | var config = require('./../../../config') 7 | var mongoose = require('mongoose'); 8 | var Promise = require('bluebird'); 9 | console.log(config.mongo.uri) 10 | mongoose.Promise = Promise; 11 | mongoose.connect(config.mongo.uri, 12 | { keepAlive: true, useMongoClient: true }, 13 | function(err) { 14 | if (err) return console.log(err); 15 | console.log('Mongoose Connected'); 16 | }); 17 | var db ={}; 18 | db.OAuthAccessToken = require('./OAuthAccessToken') 19 | db.OAuthAuthorizationCode = require('./OAuthAuthorizationCode') 20 | db.OAuthClient = require('./OAuthClient') 21 | db.OAuthRefreshToken = require('./OAuthRefreshToken') 22 | db.OAuthScope = require('./OAuthScope') 23 | db.User = require('./User') 24 | db.Thing = require('./Thing') 25 | 26 | module.exports = db; -------------------------------------------------------------------------------- /components/oauth/oauth.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 15-05-2016. 3 | */ 4 | 5 | var oauthServer = require('oauth2-server'); 6 | var config = require('../../config') 7 | 8 | var oauth = new oauthServer({ 9 | model: config.db==='mongo' ? require('./mongo-models.js') : require('./models.js') 10 | }); 11 | 12 | module.exports = oauth; -------------------------------------------------------------------------------- /components/oauth/seed-mongo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | * 4 | * Populate DB with sample data on server start 5 | * to disable, edit config/environment/index.js, and set `seedDB: false` 6 | */ 7 | 8 | 'use strict'; 9 | var config = require('./../../config') 10 | var mongodb = require('./mongodb'); 11 | 12 | var Thing = mongodb.Thing; 13 | var OAuthAccessToken = mongodb.OAuthAccessToken 14 | var OAuthAuthorizationCode = mongodb.OAuthAuthorizationCode 15 | var OAuthClient = mongodb.OAuthClient 16 | var OAuthRefreshToken = mongodb.OAuthRefreshToken 17 | var OAuthScope = mongodb.OAuthScope 18 | var User = mongodb.User 19 | 20 | 21 | //OAuthAccessToken.sync({force:config.seedDBForce}) 22 | //OAuthRefreshToken.sync({force:config.seedDBForce}) 23 | //OAuthAuthorizationCode.sync({force:config.seedDBForce}) 24 | 25 | 26 | OAuthScope.find({}).remove() 27 | .then(function() { 28 | OAuthScope.create({ 29 | scope: 'profile', 30 | is_default: false 31 | },{ 32 | scope: 'defaultscope', 33 | is_default: true 34 | }) 35 | .then(function() { 36 | console.log('finished populating OAuthScope'); 37 | }); 38 | }); 39 | User.find({}).remove() 40 | .then(function() { 41 | User.create({ 42 | username: 'admin', 43 | password: 'admin' 44 | }) 45 | .then(function(user) { 46 | console.log('finished populating users',user); 47 | return OAuthClient.find({}).remove() 48 | .then(function() { 49 | OAuthClient.create({ 50 | client_id:'democlient', 51 | client_secret:'democlientsecret', 52 | redirect_uri:'http://localhost/cb', 53 | User:user._id 54 | }) 55 | .then(function(client) { 56 | console.log('finished populating OAuthClient',client); 57 | }).catch(console.log); 58 | }); 59 | 60 | }); 61 | }); 62 | 63 | 64 | Thing.find({}).remove() 65 | .then(function(){ 66 | Thing.create({ 67 | name: 'Development Tools', 68 | info: 'Integration with popular tools such as Bower, Grunt, Babel, Karma, ' + 69 | 'Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, ' + 70 | 'Stylus, Sass, and Less.' 71 | }, { 72 | name: 'Server and Client integration', 73 | info: 'Built with a powerful and fun stack: MongoDB, Express, ' + 74 | 'AngularJS, and Node.' 75 | }, { 76 | name: 'Smart Build System', 77 | info: 'Build system ignores `spec` files, allowing you to keep ' + 78 | 'tests alongside code. Automatic injection of scripts and ' + 79 | 'styles into your index.html' 80 | }, { 81 | name: 'Modular Structure', 82 | info: 'Best practice client and server structures allow for more ' + 83 | 'code reusability and maximum scalability' 84 | }, { 85 | name: 'Optimized Build', 86 | info: 'Build process packs up your templates as a single JavaScript ' + 87 | 'payload, minifies your scripts/css/images, and rewrites asset ' + 88 | 'names for caching.' 89 | }, { 90 | name: 'Deployment Ready', 91 | info: 'Easily deploy your app to Heroku or Openshift with the heroku ' + 92 | 'and openshift subgenerators' 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /components/oauth/seed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | * 4 | * Populate DB with sample data on server start 5 | * to disable, edit config/environment/index.js, and set `seedDB: false` 6 | */ 7 | 8 | 'use strict'; 9 | var config = require('./../../config') 10 | var sqldb = require('./sqldb'); 11 | 12 | var Thing = sqldb.Thing; 13 | var OAuthAccessToken = sqldb.OAuthAccessToken 14 | var OAuthAuthorizationCode = sqldb.OAuthAuthorizationCode 15 | var OAuthClient = sqldb.OAuthClient 16 | var OAuthRefreshToken = sqldb.OAuthRefreshToken 17 | var OAuthScope = sqldb.OAuthScope 18 | var User = sqldb.User 19 | // 20 | //User.sync({force:config.seedDBForce}).then(function() { 21 | // return User.destroy({ where: {} }); 22 | // }) 23 | // .then(function() { 24 | // User.bulkCreate([{username:'admin',password:'admin'}]) 25 | // }) 26 | // 27 | 28 | OAuthClient.sync({force:config.seedDBForce}).then(function() { 29 | return OAuthClient.destroy({ where: {} }); 30 | }) 31 | .then(function() { 32 | OAuthClient.bulkCreate([{ 33 | client_id:'democlient', 34 | client_secret:'democlientsecret', 35 | redirect_uri:'http://localhost/cb' 36 | }]) 37 | }) 38 | OAuthAccessToken.sync({force:config.seedDBForce}) 39 | OAuthRefreshToken.sync({force:config.seedDBForce}) 40 | OAuthAuthorizationCode.sync({force:config.seedDBForce}) 41 | 42 | 43 | OAuthScope.sync({force:config.seedDBForce}).then(function() { 44 | return OAuthScope.destroy({ where: {} }); 45 | }) 46 | .then(function() { 47 | OAuthScope.bulkCreate([{scope:'profile'}]) 48 | }) 49 | 50 | //Thing.sync({force:config.seedDBForce}) 51 | // .then(function() { 52 | // return Thing.destroy({ where: {} }); 53 | // }) 54 | // .then(function() { 55 | // Thing.bulkCreate([{}]) 56 | // }) 57 | // 58 | // 59 | //Thing.sync({force:config.seedDBForce}) 60 | // .then(function() { 61 | // return Thing.destroy({ where: {} }); 62 | //}) 63 | //.then(function() { 64 | // Thing.bulkCreate([{ 65 | // name: 'Development Tools', 66 | // info: 'Integration with popular tools such as Bower, Grunt, Babel, Karma, ' + 67 | // 'Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, ' + 68 | // 'Stylus, Sass, and Less.' 69 | //}, { 70 | // name: 'Server and Client integration', 71 | // info: 'Built with a powerful and fun stack: MongoDB, Express, ' + 72 | // 'AngularJS, and Node.' 73 | //}, { 74 | // name: 'Smart Build System', 75 | // info: 'Build system ignores `spec` files, allowing you to keep ' + 76 | // 'tests alongside code. Automatic injection of scripts and ' + 77 | // 'styles into your index.html' 78 | //}, { 79 | // name: 'Modular Structure', 80 | // info: 'Best practice client and server structures allow for more ' + 81 | // 'code reusability and maximum scalability' 82 | //}, { 83 | // name: 'Optimized Build', 84 | // info: 'Build process packs up your templates as a single JavaScript ' + 85 | // 'payload, minifies your scripts/css/images, and rewrites asset ' + 86 | // 'names for caching.' 87 | //}, { 88 | // name: 'Deployment Ready', 89 | // info: 'Easily deploy your app to Heroku or Openshift with the heroku ' + 90 | // 'and openshift subgenerators' 91 | //}]); 92 | //}); 93 | // 94 | -------------------------------------------------------------------------------- /components/oauth/sqldb/OAuthAccessToken.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | 7 | module.exports = function(sequelize, DataTypes) { 8 | const OAuthAccessToken = sequelize.define('OAuthAccessToken', { 9 | id: { 10 | type: DataTypes.INTEGER(14), 11 | autoIncrement: true, 12 | primaryKey: true, 13 | allowNull: false, 14 | unique: true, 15 | }, 16 | access_token:DataTypes.STRING(256), 17 | expires:DataTypes.DATE, 18 | scope: DataTypes.STRING 19 | }, { 20 | tableName: 'oauth_access_tokens', 21 | timestamps: false, 22 | underscored: true, 23 | classMethods: { 24 | associate: function(models) { 25 | OAuthAccessToken.belongsTo(models.OAuthClient, { 26 | foreignKey: 'client_id', 27 | }); 28 | 29 | OAuthAccessToken.belongsTo(models.User, { 30 | foreignKey: 'user_id', 31 | }); 32 | }, 33 | }, 34 | }); 35 | 36 | return OAuthAccessToken; 37 | }; 38 | -------------------------------------------------------------------------------- /components/oauth/sqldb/OAuthAuthorizationCode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | const moment = require('moment'); 7 | 8 | module.exports = function AuthCodeModel(sequelize, DataTypes) { 9 | const OAuthAuthorizationCode = sequelize.define('OAuthAuthorizationCode', { 10 | id: { 11 | type: DataTypes.INTEGER(14), 12 | autoIncrement: true, 13 | primaryKey: true, 14 | allowNull: false, 15 | unique: true, 16 | }, 17 | authorization_code : DataTypes.STRING(256), 18 | expires: DataTypes.DATE, 19 | redirect_uri: DataTypes.STRING(2000), 20 | scope: DataTypes.STRING 21 | }, { 22 | tableName: 'oauth_authorization_codes', 23 | timestamps: false, 24 | underscored: true, 25 | 26 | classMethods: { 27 | associate: function associate(models) { 28 | OAuthAuthorizationCode.belongsTo(models.OAuthClient, { 29 | foreignKey: 'client_id', 30 | }); 31 | 32 | OAuthAuthorizationCode.belongsTo(models.User, { 33 | foreignKey: 'user_id', 34 | }); 35 | }, 36 | }, 37 | }); 38 | 39 | return OAuthAuthorizationCode; 40 | }; 41 | -------------------------------------------------------------------------------- /components/oauth/sqldb/OAuthClient.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = function AppModel(sequelize, DataTypes) { 7 | const OAuthClient = sequelize.define('OAuthClient', { 8 | id: { 9 | type: DataTypes.INTEGER(14), 10 | autoIncrement: true, 11 | primaryKey: true, 12 | allowNull: false, 13 | unique: true, 14 | }, 15 | name: DataTypes.STRING(255), 16 | client_id: DataTypes.STRING(80), 17 | client_secret: DataTypes.STRING(80), 18 | redirect_uri: DataTypes.STRING(2000), 19 | grant_types: DataTypes.STRING(80), 20 | scope: DataTypes.STRING 21 | }, { 22 | tableName: 'oauth_clients', 23 | timestamps: false, 24 | underscored: true, 25 | 26 | classMethods: { 27 | associate: function associate(models) { 28 | OAuthClient.belongsTo(models.User, { 29 | foreignKey: 'user_id', 30 | }); 31 | }, 32 | }, 33 | }); 34 | 35 | return OAuthClient; 36 | }; 37 | -------------------------------------------------------------------------------- /components/oauth/sqldb/OAuthRefreshToken.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = function RefreshTokenModel(sequelize, DataTypes) { 7 | const RefreshToken = sequelize.define('RefreshToken', { 8 | id: { 9 | type: DataTypes.INTEGER(14), 10 | autoIncrement: true, 11 | primaryKey: true, 12 | allowNull: false, 13 | unique: true, 14 | }, 15 | refresh_token: DataTypes.STRING(256), 16 | expires: DataTypes.DATE, 17 | scope: DataTypes.STRING 18 | }, { 19 | tableName: 'oauth_refresh_tokens', 20 | timestamps: false, 21 | underscored: true, 22 | 23 | classMethods: { 24 | associate: function associate(models) { 25 | RefreshToken.belongsTo(models.OAuthClient, { 26 | foreignKey: 'client_id', 27 | }); 28 | 29 | RefreshToken.belongsTo(models.User, { 30 | foreignKey: 'user_id', 31 | }); 32 | }, 33 | }, 34 | }); 35 | 36 | return RefreshToken; 37 | }; 38 | -------------------------------------------------------------------------------- /components/oauth/sqldb/OAuthScope.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | module.exports = function(sequelize, DataTypes) { 6 | var OAuthScope = sequelize.define('OAuthScope', { 7 | id: { 8 | type: DataTypes.INTEGER(11), 9 | autoIncrement: true, 10 | primaryKey: true, 11 | allowNull: false, 12 | unique: true, 13 | }, 14 | scope: DataTypes.STRING(80), 15 | is_default: DataTypes.BOOLEAN 16 | }, { 17 | tableName: 'oauth_scopes', 18 | timestamps: false, 19 | underscored: true 20 | }) 21 | 22 | return OAuthScope; 23 | } -------------------------------------------------------------------------------- /components/oauth/sqldb/Thing.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(sequelize, DataTypes) { 4 | return sequelize.define('Thing', { 5 | _id: { 6 | type: DataTypes.INTEGER, 7 | allowNull: false, 8 | primaryKey: true, 9 | autoIncrement: true 10 | }, 11 | name: DataTypes.STRING, 12 | info: DataTypes.STRING, 13 | active: DataTypes.BOOLEAN 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /components/oauth/sqldb/User.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 'use strict'; 5 | 6 | module.exports = function(sequelize, DataTypes) { 7 | var User = sequelize.define('User', { 8 | id: { 9 | type: DataTypes.INTEGER(11), 10 | autoIncrement: true, 11 | primaryKey: true, 12 | allowNull: false, 13 | unique: true, 14 | }, 15 | username: DataTypes.STRING(32), 16 | password: DataTypes.STRING(32), 17 | scope: DataTypes.STRING 18 | }, { 19 | tableName: 'users', // oauth_users 20 | timestamps: false, 21 | underscored: true, 22 | 23 | classMethods: { 24 | associate: function associate(models) { 25 | //User.hasMany(models.OAuthClient); 26 | }, 27 | }, 28 | }); 29 | 30 | return User; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /components/oauth/sqldb/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | /** https://github.com/dsquier/oauth2-server-php-mysql **/ 6 | var config = require('./../../../config') 7 | var Sequelize = require('sequelize'); 8 | 9 | var db = { 10 | sequelize: new Sequelize( 11 | config.sql.database, 12 | config.sql.username, 13 | config.sql.password, 14 | config.sql 15 | ) 16 | }; 17 | 18 | db.OAuthAccessToken = db.sequelize.import('./OAuthAccessToken'); 19 | db.OAuthAuthorizationCode = db.sequelize.import('./OAuthAuthorizationCode'); 20 | db.OAuthClient = db.sequelize.import('./OAuthClient'); 21 | db.OAuthRefreshToken = db.sequelize.import('./OAuthRefreshToken'); 22 | db.OAuthScope = db.sequelize.import('./OAuthScope'); 23 | db.User = db.sequelize.import('./User'); 24 | db.Thing = db.sequelize.import('./Thing'); 25 | 26 | Object.keys(db).forEach(function(modelName) { 27 | if ('associate' in db[modelName]) { 28 | db[modelName].associate(db); 29 | } 30 | }); 31 | 32 | module.exports = db; -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 14-05-2016. 3 | */ 4 | 5 | module.exports = { 6 | sql: { 7 | host: 'host_ip', 8 | database: 'oauth_demo', 9 | username: 'root', 10 | password: '', 11 | dialect: 'mysql', // PostgreSQL, MySQL, MariaDB, SQLite and MSSQL See more: http://docs.sequelizejs.com/en/latest/ 12 | logging: true, 13 | timezone: '+05:30', 14 | }, 15 | mongo: { 16 | uri: 'mongodb://localhost/oauth2' 17 | }, 18 | seedDB:false, 19 | seedMongoDB:false, 20 | seedDBForce:true, 21 | db:'mongo' // mongo,sql if you want to use any SQL change dialect above in sql config 22 | } 23 | -------------------------------------------------------------------------------- /mongo-dump/oauthaccesstokens.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id" : ObjectId("573825e60982fbc82be85f09"), 3 | "access_token" : "e601bea6c8b942f884e4074b05a67eb3eb1ced11", 4 | "expires" : ISODate("2016-05-15T08:31:50.724+0000"), 5 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 6 | "__v" : NumberInt(0) 7 | } 8 | { 9 | "_id" : ObjectId("5738260dbfa2d9ac190a74a9"), 10 | "access_token" : "88a73e3c5b402aff0929bda9a423ffba2f639f86", 11 | "expires" : ISODate("2016-05-15T08:32:29.954+0000"), 12 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 13 | "__v" : NumberInt(0) 14 | } 15 | { 16 | "_id" : ObjectId("57382699e2b7f9b423de55f1"), 17 | "access_token" : "646d8885ecd19e9ad8483a797c383207b60b1ef1", 18 | "expires" : ISODate("2016-05-15T08:34:49.317+0000"), 19 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 20 | "__v" : NumberInt(0) 21 | } 22 | { 23 | "_id" : ObjectId("573826f89985bf5c17e394d6"), 24 | "access_token" : "b7c229b10434c7a5a1e0aac3dc514681d01f26c3", 25 | "expires" : ISODate("2016-05-15T08:36:24.707+0000"), 26 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 27 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 28 | "__v" : NumberInt(0) 29 | } 30 | { 31 | "_id" : ObjectId("573827b11dbf26d83393070b"), 32 | "access_token" : "e08b0219d8ede40f165e167aa688f6c0063d86d8", 33 | "expires" : ISODate("2016-05-15T08:39:29.074+0000"), 34 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 35 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 36 | "__v" : NumberInt(0) 37 | } 38 | { 39 | "_id" : ObjectId("573827fb6e89bf342427fe39"), 40 | "access_token" : "a64d59840268eb4c8e149f88440e84fa0633fac8", 41 | "expires" : ISODate("2016-05-15T08:40:43.836+0000"), 42 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 43 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 44 | "__v" : NumberInt(0) 45 | } 46 | { 47 | "_id" : ObjectId("5738281f486f067c03b2a3d0"), 48 | "access_token" : "bf79447c6e27104e576cabe324bae591b168e28f", 49 | "expires" : ISODate("2016-05-15T08:41:19.476+0000"), 50 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 51 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 52 | "__v" : NumberInt(0) 53 | } 54 | { 55 | "_id" : ObjectId("573828536f42fcb0265cdc27"), 56 | "access_token" : "4f4daaa1637d01adc036651cf6455abf26b50ed8", 57 | "expires" : ISODate("2016-05-15T08:42:11.862+0000"), 58 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 59 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 60 | "__v" : NumberInt(0) 61 | } 62 | { 63 | "_id" : ObjectId("57382876fd5d079803a162ac"), 64 | "access_token" : "cfb87f92a802ed6dba549a4d66018cdc64cf101e", 65 | "expires" : ISODate("2016-05-15T08:42:46.217+0000"), 66 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 67 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 68 | "__v" : NumberInt(0) 69 | } 70 | { 71 | "_id" : ObjectId("57382879fd5d079803a162ae"), 72 | "access_token" : "93be3a007dd8dacbdb2fb856d016436d5df3c1a0", 73 | "expires" : ISODate("2016-05-15T08:42:49.017+0000"), 74 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 75 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 76 | "__v" : NumberInt(0) 77 | } 78 | { 79 | "_id" : ObjectId("573829edef8aff503017b839"), 80 | "access_token" : "8a1453bee822bb7964f8cdb20d8d2b76f32ee472", 81 | "expires" : ISODate("2016-05-15T08:49:01.466+0000"), 82 | "client_id" : ObjectId("573829e6ef8aff503017b838"), 83 | "user_id" : ObjectId("573829e5ef8aff503017b831"), 84 | "__v" : NumberInt(0) 85 | } 86 | { 87 | "_id" : ObjectId("573829f9ef8aff503017b83a"), 88 | "access_token" : "cc981dea4a246bcb4d453d1b805723366251b9cc", 89 | "expires" : ISODate("2016-05-15T08:49:13.279+0000"), 90 | "client_id" : ObjectId("573829e6ef8aff503017b838"), 91 | "user_id" : ObjectId("573829e5ef8aff503017b831"), 92 | "__v" : NumberInt(0) 93 | } 94 | { 95 | "_id" : ObjectId("573829fcef8aff503017b83c"), 96 | "access_token" : "b2bee60fdb0eb2695933596496f8bc7bea479e03", 97 | "expires" : ISODate("2016-05-15T08:49:16.078+0000"), 98 | "client_id" : ObjectId("573829e6ef8aff503017b838"), 99 | "user_id" : ObjectId("573829e5ef8aff503017b831"), 100 | "__v" : NumberInt(0) 101 | } 102 | { 103 | "_id" : ObjectId("573829feef8aff503017b83e"), 104 | "access_token" : "dfb578ddf84b80ec78235daa009ce8988614b203", 105 | "expires" : ISODate("2016-05-15T08:49:18.901+0000"), 106 | "client_id" : ObjectId("573829e6ef8aff503017b838"), 107 | "user_id" : ObjectId("573829e5ef8aff503017b831"), 108 | "__v" : NumberInt(0) 109 | } 110 | { 111 | "_id" : ObjectId("57382a6a7be939200ccb8f01"), 112 | "access_token" : "cda1895a9743461dc627f15b2d5ab5759472a217", 113 | "expires" : ISODate("2016-05-15T08:51:06.531+0000"), 114 | "client_id" : ObjectId("57382a524c862c282c174d8e"), 115 | "user_id" : ObjectId("57382a504c862c282c174d87"), 116 | "__v" : NumberInt(0) 117 | } 118 | { 119 | "_id" : ObjectId("57382aaaa037aad8263dd07d"), 120 | "access_token" : "624cb4cab98684808e17ad62ab49b24eb300c051", 121 | "client_id" : ObjectId("57382a524c862c282c174d8e"), 122 | "user_id" : ObjectId("57382a504c862c282c174d87"), 123 | "scope" : "profile", 124 | "__v" : NumberInt(0) 125 | } 126 | { 127 | "_id" : ObjectId("57382de4fef474e01c5522b1"), 128 | "access_token" : "9ebf32fb220cee76b34a02d2470ad9ae7e6638d1", 129 | "expires" : ISODate("2016-05-15T09:05:56.071+0000"), 130 | "__v" : NumberInt(0) 131 | } 132 | { 133 | "_id" : ObjectId("57382e1fd0b51608283e928a"), 134 | "access_token" : "1a567d7b2bb3a50e9f843553567c70f8310a83ad", 135 | "expires" : ISODate("2016-05-15T09:06:55.324+0000"), 136 | "__v" : NumberInt(0) 137 | } 138 | { 139 | "_id" : ObjectId("57382e5f7db5cbf821d51de0"), 140 | "access_token" : "69ff56a5d81db69db05560cd5b239891979bbcff", 141 | "expires" : ISODate("2016-05-15T09:07:59.112+0000"), 142 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 143 | "User" : ObjectId("57382dd6e05342a003543d54"), 144 | "__v" : NumberInt(0) 145 | } 146 | { 147 | "_id" : ObjectId("57382e617db5cbf821d51de2"), 148 | "access_token" : "94ccf19f4e4ae567eeaf355ff42aa71e8d3970e2", 149 | "expires" : ISODate("2016-05-15T09:08:01.913+0000"), 150 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 151 | "User" : ObjectId("57382dd6e05342a003543d54"), 152 | "__v" : NumberInt(0) 153 | } 154 | { 155 | "_id" : ObjectId("57382e96b2f962d42e827f4b"), 156 | "access_token" : "fb69b800e2979be46cefd7b104de40d8790768bb", 157 | "expires" : ISODate("2016-05-15T09:08:54.802+0000"), 158 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 159 | "User" : ObjectId("57382dd6e05342a003543d54"), 160 | "__v" : NumberInt(0) 161 | } 162 | { 163 | "_id" : ObjectId("57382ef6b2f962d42e827f4d"), 164 | "access_token" : "1864835092f793556844ee1be470f3cd7183cdcd", 165 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 166 | "User" : ObjectId("57382dd6e05342a003543d54"), 167 | "scope" : "profile", 168 | "__v" : NumberInt(0) 169 | } 170 | -------------------------------------------------------------------------------- /mongo-dump/oauthauthorizationcodes.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id" : ObjectId("57382a6c7be939200ccb8f03"), 3 | "expires" : ISODate("2016-05-15T07:56:08.398+0000"), 4 | "client_id" : ObjectId("57382a524c862c282c174d8e"), 5 | "authorization_code" : "ae114889532bcca1542d7c77b4a2964c300cf17f", 6 | "user_id" : ObjectId("57382a504c862c282c174d87"), 7 | "scope" : "profile", 8 | "__v" : NumberInt(0) 9 | } 10 | { 11 | "_id" : ObjectId("57382ef2b2f962d42e827f4c"), 12 | "expires" : ISODate("2016-05-15T08:15:25.679+0000"), 13 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 14 | "authorization_code" : "0e6fecbd2802e7b8778f288a1af76dbd0b916229", 15 | "User" : ObjectId("57382dd6e05342a003543d54"), 16 | "scope" : "profile", 17 | "__v" : NumberInt(0) 18 | } 19 | -------------------------------------------------------------------------------- /mongo-dump/oauthclients.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id" : ObjectId("57382dd7e05342a003543d5b"), 3 | "client_id" : "democlient", 4 | "client_secret" : "democlientsecret", 5 | "redirect_uri" : "http://localhost/cb", 6 | "User" : ObjectId("57382dd6e05342a003543d54"), 7 | "__v" : NumberInt(0) 8 | } 9 | -------------------------------------------------------------------------------- /mongo-dump/oauthscopes.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id" : ObjectId("57382dd5e05342a003543d52"), 3 | "scope" : "profile", 4 | "is_default" : false, 5 | "__v" : NumberInt(0) 6 | } 7 | { 8 | "_id" : ObjectId("57382dd5e05342a003543d53"), 9 | "scope" : "defaultscope", 10 | "is_default" : true, 11 | "__v" : NumberInt(0) 12 | } 13 | -------------------------------------------------------------------------------- /mongo-dump/refreshtokens.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id" : ObjectId("573825e60982fbc82be85f0a"), 3 | "refresh_token" : "bac6eaac70269aa1a0080d8d65404d880b8ea1d0", 4 | "expires" : ISODate("2016-05-29T07:31:50.724+0000"), 5 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 6 | "__v" : NumberInt(0) 7 | } 8 | { 9 | "_id" : ObjectId("5738260dbfa2d9ac190a74aa"), 10 | "refresh_token" : "2903e2ac964fe626c34a6813cf63eb5b6ab6f43e", 11 | "expires" : ISODate("2016-05-29T07:32:29.954+0000"), 12 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 13 | "__v" : NumberInt(0) 14 | } 15 | { 16 | "_id" : ObjectId("57382699e2b7f9b423de55f2"), 17 | "refresh_token" : "d12efe10fb7b9b684ca389556bd8a4305d514d01", 18 | "expires" : ISODate("2016-05-29T07:34:49.317+0000"), 19 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 20 | "__v" : NumberInt(0) 21 | } 22 | { 23 | "_id" : ObjectId("573826f89985bf5c17e394d7"), 24 | "refresh_token" : "074f9268c88627165d3644c65605d1f17b8f5e57", 25 | "expires" : ISODate("2016-05-29T07:36:24.707+0000"), 26 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 27 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 28 | "__v" : NumberInt(0) 29 | } 30 | { 31 | "_id" : ObjectId("573827b11dbf26d83393070c"), 32 | "refresh_token" : "832dd75ddcb6d2d0e3dc22e4537a9ead08c7d495", 33 | "expires" : ISODate("2016-05-29T07:39:29.075+0000"), 34 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 35 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 36 | "__v" : NumberInt(0) 37 | } 38 | { 39 | "_id" : ObjectId("573827fb6e89bf342427fe3a"), 40 | "refresh_token" : "526ec055ddd50f0c6da36b2a400fd44a1bc7c762", 41 | "expires" : ISODate("2016-05-29T07:40:43.836+0000"), 42 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 43 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 44 | "__v" : NumberInt(0) 45 | } 46 | { 47 | "_id" : ObjectId("5738281f486f067c03b2a3d1"), 48 | "refresh_token" : "954f7dedc2bcce80cac15f7efa3fe8cec8b55c7e", 49 | "expires" : ISODate("2016-05-29T07:41:19.476+0000"), 50 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 51 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 52 | "__v" : NumberInt(0) 53 | } 54 | { 55 | "_id" : ObjectId("573828536f42fcb0265cdc28"), 56 | "refresh_token" : "77d957844ff39b4d154d0edc8fc97cb5aeb1c2c7", 57 | "expires" : ISODate("2016-05-29T07:42:11.862+0000"), 58 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 59 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 60 | "__v" : NumberInt(0) 61 | } 62 | { 63 | "_id" : ObjectId("57382876fd5d079803a162ad"), 64 | "refresh_token" : "004786c994c91f02bd09a9922ece03bd98f794aa", 65 | "expires" : ISODate("2016-05-29T07:42:46.217+0000"), 66 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 67 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 68 | "__v" : NumberInt(0) 69 | } 70 | { 71 | "_id" : ObjectId("57382879fd5d079803a162af"), 72 | "refresh_token" : "d3870c6df05158347c75ba83d436c69003ba5f27", 73 | "expires" : ISODate("2016-05-29T07:42:49.017+0000"), 74 | "client_id" : ObjectId("573823f00f7a7fcc33a136d7"), 75 | "user_id" : ObjectId("573823f10f7a7fcc33a136da"), 76 | "__v" : NumberInt(0) 77 | } 78 | { 79 | "_id" : ObjectId("573829f9ef8aff503017b83b"), 80 | "refresh_token" : "e552da65ea927065297768c3ab5a6a479b5fdf53", 81 | "expires" : ISODate("2016-05-29T07:49:13.279+0000"), 82 | "client_id" : ObjectId("573829e6ef8aff503017b838"), 83 | "user_id" : ObjectId("573829e5ef8aff503017b831"), 84 | "__v" : NumberInt(0) 85 | } 86 | { 87 | "_id" : ObjectId("573829fcef8aff503017b83d"), 88 | "refresh_token" : "4654a0c28423d32f22bb510c6f48576208df0338", 89 | "expires" : ISODate("2016-05-29T07:49:16.078+0000"), 90 | "client_id" : ObjectId("573829e6ef8aff503017b838"), 91 | "user_id" : ObjectId("573829e5ef8aff503017b831"), 92 | "__v" : NumberInt(0) 93 | } 94 | { 95 | "_id" : ObjectId("57382a6a7be939200ccb8f02"), 96 | "refresh_token" : "980b2bcfbeb54c0a26c934f76afaa87e9d5bbfbe", 97 | "expires" : ISODate("2016-05-29T07:51:06.532+0000"), 98 | "client_id" : ObjectId("57382a524c862c282c174d8e"), 99 | "user_id" : ObjectId("57382a504c862c282c174d87"), 100 | "__v" : NumberInt(0) 101 | } 102 | { 103 | "_id" : ObjectId("57382aaaa037aad8263dd07e"), 104 | "refresh_token" : "3d17227efbe1ac17c3c82109f1863549dbaaf4a0", 105 | "client_id" : ObjectId("57382a524c862c282c174d8e"), 106 | "user_id" : ObjectId("57382a504c862c282c174d87"), 107 | "scope" : "profile", 108 | "__v" : NumberInt(0) 109 | } 110 | { 111 | "_id" : ObjectId("57382de4fef474e01c5522b2"), 112 | "refresh_token" : "544ba0dba53a4e7e8ed756c4dd877c9f9db82f7d", 113 | "expires" : ISODate("2016-05-29T08:05:56.071+0000"), 114 | "__v" : NumberInt(0) 115 | } 116 | { 117 | "_id" : ObjectId("57382e1fd0b51608283e928b"), 118 | "refresh_token" : "f9483e09561fab0b5451f19de68328e6add62e64", 119 | "expires" : ISODate("2016-05-29T08:06:55.325+0000"), 120 | "__v" : NumberInt(0) 121 | } 122 | { 123 | "_id" : ObjectId("57382e5f7db5cbf821d51de1"), 124 | "refresh_token" : "0888438d6f0255fc3e3d881168ce75f6df28be3b", 125 | "expires" : ISODate("2016-05-29T08:07:59.113+0000"), 126 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 127 | "User" : ObjectId("57382dd6e05342a003543d54"), 128 | "__v" : NumberInt(0) 129 | } 130 | { 131 | "_id" : ObjectId("57382e617db5cbf821d51de3"), 132 | "refresh_token" : "f7741a90f61f51626e04d5f85f9057c1b77f4d74", 133 | "expires" : ISODate("2016-05-29T08:08:01.913+0000"), 134 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 135 | "User" : ObjectId("57382dd6e05342a003543d54"), 136 | "__v" : NumberInt(0) 137 | } 138 | { 139 | "_id" : ObjectId("57382ef6b2f962d42e827f4e"), 140 | "refresh_token" : "b775721ee39b9922695decc9b7d12590720f5827", 141 | "OAuthClient" : ObjectId("57382dd7e05342a003543d5b"), 142 | "User" : ObjectId("57382dd6e05342a003543d54"), 143 | "scope" : "profile", 144 | "__v" : NumberInt(0) 145 | } 146 | -------------------------------------------------------------------------------- /mongo-dump/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id" : ObjectId("57382dd6e05342a003543d54"), 3 | "username" : "admin", 4 | "password" : "admin", 5 | "__v" : NumberInt(0) 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-oauth2-server-implementation", 3 | "version": "0.0.0", 4 | "private": true, 5 | "contributors": [ 6 | { "name": "Manjesh V", "email": "manjeshpv@gmail.com" }, 7 | { "name": "Yogesh", "email": "yogesum@gmail.com" } 8 | ], 9 | "main": "index.js", 10 | "dependencies": { 11 | "bluebird": "^3.5.1", 12 | "body-parser": "~1.13.2", 13 | "cookie-parser": "~1.3.5", 14 | "debug": "~2.2.0", 15 | "express": "~4.13.1", 16 | "jade": "~1.11.0", 17 | "lodash": "^4.15.0", 18 | "lodash-cli": "^4.15.0", 19 | "mongoose": "^4.4.17", 20 | "morgan": "~1.6.1", 21 | "mysql": "^2.10.2", 22 | "oauth2-server": "^3.0.0-b2", 23 | "sequelize": "^3.23.1", 24 | "serve-favicon": "~2.3.0" 25 | }, 26 | "devDependencies": { 27 | "jshint": "^2.9.1", 28 | "mocha": "^3.1.2", 29 | "should": "^5.0.1", 30 | "sinon": "^1.13.0" 31 | }, 32 | "scripts": { 33 | "test": "./node_modules/.bin/mocha 'test/**/*_test.js'", 34 | "start": "node ./bin/www" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "https://github.com/manjeshpv/node-oauth2-server-implementation.git" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /sql/oauth_demo.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 4.5.1 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- Host: 127.0.0.1 6 | -- Generation Time: May 14, 2016 at 03:56 PM 7 | -- Server version: 10.1.9-MariaDB 8 | -- PHP Version: 5.6.15 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | SET time_zone = "+00:00"; 12 | 13 | 14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 17 | /*!40101 SET NAMES utf8mb4 */; 18 | 19 | -- 20 | -- Database: `oauth_demo` 21 | -- 22 | 23 | -- -------------------------------------------------------- 24 | 25 | -- 26 | -- Table structure for table `oauth_access_tokens` 27 | -- 28 | 29 | CREATE TABLE `oauth_access_tokens` ( 30 | `id` int(14) NOT NULL, 31 | `access_token` varchar(256) DEFAULT NULL, 32 | `expires` datetime DEFAULT NULL, 33 | `scope` varchar(255) DEFAULT NULL, 34 | `client_id` int(14) DEFAULT NULL, 35 | `user_id` int(11) DEFAULT NULL 36 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 37 | 38 | -- 39 | -- Dumping data for table `oauth_access_tokens` 40 | -- 41 | 42 | INSERT INTO `oauth_access_tokens` (`id`, `access_token`, `expires`, `scope`, `client_id`, `user_id`) VALUES 43 | (1, '81b011b7f3a903f4e30a19988c8985a16f22d64f', '2016-05-14 19:09:56', NULL, NULL, NULL), 44 | (2, '35d35de511f004fa4132fff79cf0bcf9f03f1c49', '2016-05-14 19:10:34', NULL, NULL, NULL), 45 | (3, 'f70252ff1b57493a5eaf27212b72cd24f12cf764', '2016-05-14 19:12:30', NULL, NULL, 1), 46 | (4, 'aefdf36e9ff2947f121e15cbe2680fc309ebd945', '2016-05-14 19:17:06', NULL, NULL, NULL), 47 | (5, '40898bede94699b0385878c6d37d0284e59e2abf', '2016-05-14 19:17:25', NULL, NULL, NULL), 48 | (6, '4b1d4673bda41926c065a9acb0b3e7bb31f5ea24', '2016-05-14 19:18:04', NULL, NULL, NULL), 49 | (7, '0143e8f0d9f3ccc43c62aa87c38c40f23a5e9ba4', '2016-05-14 19:19:50', NULL, NULL, NULL), 50 | (8, '8c5234b1372c2b78b4d96f3b6f5db8932fa29762', '2016-05-14 19:25:40', NULL, NULL, NULL), 51 | (9, '61fe2c5b0faf9ff96334356b1527ba73b190fa3d', '2016-05-14 19:26:25', NULL, NULL, NULL), 52 | (10, 'b6c9212f29909ec5db9dbeaa4e80f71b507df37f', '2016-05-14 19:27:31', NULL, NULL, 1), 53 | (11, '4185ab5b52452ae295c3011f04c8c13c4115d325', '2016-05-14 19:28:36', NULL, NULL, 1), 54 | (12, '253734e26e1ec8d7389d23458eedf06d6cb50392', '2016-05-14 19:30:06', NULL, 1, 1), 55 | (13, '8161e39caa925cc069e0e709de840fd30be9b7eb', '2016-05-14 19:31:30', NULL, 1, 1), 56 | (14, 'a602543f6bdd6092779939bf1de2299a905dbfec', '2016-05-14 19:31:55', NULL, 1, 1), 57 | (15, '25263fd984cdb089b866608e91c5c17fbc7662a9', '2016-05-14 19:32:07', NULL, 1, 1), 58 | (16, '009adb36c0b2c8d4269676908562fe0a5f0169c3', '2016-05-14 19:32:40', NULL, 1, 1), 59 | (17, '11e3209ea6a793011f7296d566840edf20ac8cd9', '2016-05-14 19:34:00', NULL, 1, 1), 60 | (18, '8226f459dd246a9d1b66ae6671572c38e03a5c57', '2016-05-14 19:34:38', NULL, 1, 1), 61 | (19, '1ca9fe68115a5ecb441af33d8b29ed8fd4aa20d0', '2016-05-14 19:36:38', 'consultant', 1, 1), 62 | (20, '15397cb9904a954a31e162f7635adffb554293ef', '2016-05-14 19:37:14', 'consultant', 1, 1), 63 | (21, '691199101e65b704befca81cb811800aaa8e2ab5', '2016-05-14 19:37:17', 'consultant', 1, 1), 64 | (22, '9c9a78392f164542071d3d3ec8bf8e99e8909ffa', '2016-05-14 19:46:13', NULL, 1, 1), 65 | (23, '06a158438f7685f77b514dd79349af0748a0ba4b', '2016-05-14 19:47:08', NULL, 1, 1), 66 | (24, '2ed79b5743f81418a8da0c5825d67e36be570466', '2016-05-14 19:47:27', NULL, 1, 1), 67 | (25, '4f65fe82d3f9f167328646d710d080f3b270990b', '2016-05-14 19:48:24', NULL, 1, 1), 68 | (26, '0327759746fe5be483943c64eaa018de2d1b72b8', '2016-05-14 19:48:38', NULL, 1, 1), 69 | (27, '9000675b1e23427d7933ea42865605464d1d5600', '2016-05-14 19:51:06', NULL, 1, 1), 70 | (28, 'e3476d9a25cde4ba533c32b4fbd172f55adef84b', '2016-05-14 19:52:41', NULL, 1, 1), 71 | (29, 'a6116f80d7e174e25922912aaed3e5f5972bdfc0', '2016-05-14 19:54:47', NULL, 1, 1), 72 | (30, '21d6074e3b1657f088ea233ece902022e8161910', NULL, NULL, 1, 1), 73 | (31, '83a3a6e42e160716f4c534d1c61f87d78bdf2204', '2016-05-14 19:59:00', NULL, 1, 1), 74 | (32, 'dfc39e4194313191c13a86cbc9d34ca7ffda8b49', '2016-05-14 19:59:03', 'consultant', 1, 1), 75 | (33, '635399997087ef64b813957e20b542ae407c229f', '2016-05-14 19:59:05', NULL, 1, 1), 76 | (34, '4095857d971198669fe3a92a9be2d9f08fa4b09b', '2016-05-14 19:59:10', NULL, 1, 1), 77 | (35, 'b36eaf38995433675531c99abb977199a1b36530', NULL, NULL, 1, 1), 78 | (36, '5a815d1bf7f87cd9465e4599876ce32acfa8bdad', '2016-05-14 20:14:11', NULL, 1, 1); 79 | 80 | -- -------------------------------------------------------- 81 | 82 | -- 83 | -- Table structure for table `oauth_authorization_codes` 84 | -- 85 | 86 | CREATE TABLE `oauth_authorization_codes` ( 87 | `id` int(14) NOT NULL, 88 | `authorization_code` varchar(256) DEFAULT NULL, 89 | `expires` datetime DEFAULT NULL, 90 | `redirect_uri` varchar(2000) DEFAULT NULL, 91 | `scope` varchar(255) DEFAULT NULL, 92 | `client_id` int(14) DEFAULT NULL, 93 | `user_id` int(11) DEFAULT NULL 94 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 95 | 96 | -- 97 | -- Dumping data for table `oauth_authorization_codes` 98 | -- 99 | 100 | INSERT INTO `oauth_authorization_codes` (`id`, `authorization_code`, `expires`, `redirect_uri`, `scope`, `client_id`, `user_id`) VALUES 101 | (1, NULL, '2016-05-14 18:45:02', NULL, NULL, NULL, 1), 102 | (2, NULL, '2016-05-14 18:45:10', NULL, NULL, NULL, 1), 103 | (3, NULL, '2016-05-14 18:45:15', NULL, NULL, NULL, 1), 104 | (4, NULL, '2016-05-14 18:45:41', NULL, NULL, NULL, 1), 105 | (5, NULL, '2016-05-14 18:46:59', NULL, NULL, NULL, 1), 106 | (6, NULL, '2016-05-14 18:47:22', NULL, NULL, NULL, 1), 107 | (7, NULL, '2016-05-14 18:51:16', NULL, NULL, NULL, 1), 108 | (8, NULL, '2016-05-14 18:52:10', NULL, NULL, NULL, 1), 109 | (9, NULL, '2016-05-14 18:52:33', NULL, NULL, NULL, 1), 110 | (10, NULL, '2016-05-14 18:54:20', NULL, NULL, 1, 1), 111 | (11, NULL, '2016-05-14 18:56:08', NULL, NULL, 1, 1), 112 | (12, NULL, '2016-05-14 18:57:44', NULL, NULL, 1, 1), 113 | (13, '513418e2d3a7f6ab72a63100a298d9ddb8ad0b8e', '2016-05-14 18:59:49', NULL, NULL, 1, 1), 114 | (14, '993fa8fe3be5691baa73801e31420f406b1516f8', '2016-05-14 19:04:08', NULL, NULL, 1, 1), 115 | (15, 'e78351c1b13dc09a3c51d24123b2dfb2bf178306', '2016-05-14 19:04:25', NULL, NULL, 1, 1); 116 | 117 | -- -------------------------------------------------------- 118 | 119 | -- 120 | -- Table structure for table `oauth_clients` 121 | -- 122 | 123 | CREATE TABLE `oauth_clients` ( 124 | `id` int(14) NOT NULL, 125 | `name` varchar(255) DEFAULT NULL, 126 | `client_id` varchar(80) DEFAULT NULL, 127 | `client_secret` varchar(80) DEFAULT NULL, 128 | `redirect_uri` varchar(2000) DEFAULT NULL, 129 | `grant_types` varchar(80) DEFAULT NULL, 130 | `scope` varchar(255) DEFAULT NULL, 131 | `user_id` int(11) DEFAULT NULL 132 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 133 | 134 | -- 135 | -- Dumping data for table `oauth_clients` 136 | -- 137 | 138 | INSERT INTO `oauth_clients` (`id`, `name`, `client_id`, `client_secret`, `redirect_uri`, `grant_types`, `scope`, `user_id`) VALUES 139 | (1, NULL, 'democlient', 'democlientsecret', 'http://localhost/cb', NULL, NULL, 1); 140 | 141 | -- -------------------------------------------------------- 142 | 143 | -- 144 | -- Table structure for table `oauth_refresh_tokens` 145 | -- 146 | 147 | CREATE TABLE `oauth_refresh_tokens` ( 148 | `id` int(14) NOT NULL, 149 | `refresh_token` varchar(256) DEFAULT NULL, 150 | `expires` datetime DEFAULT NULL, 151 | `scope` varchar(255) DEFAULT NULL, 152 | `client_id` int(14) DEFAULT NULL, 153 | `user_id` int(11) DEFAULT NULL 154 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 155 | 156 | -- 157 | -- Dumping data for table `oauth_refresh_tokens` 158 | -- 159 | 160 | INSERT INTO `oauth_refresh_tokens` (`id`, `refresh_token`, `expires`, `scope`, `client_id`, `user_id`) VALUES 161 | (1, '6beb7f8b4b7ab60fe123e0430a3f7081da486152', '2016-05-28 18:09:56', NULL, NULL, NULL), 162 | (2, '5dcdbd119a19f3655cc8e247c2f5165822d24399', '2016-05-28 18:10:34', NULL, NULL, NULL), 163 | (3, '3879deb38e38a12a5f5f75ecd142cfcdad00384b', '2016-05-28 18:17:06', NULL, NULL, NULL), 164 | (4, '51021e085ceb17f66701b3f736a1150eadf89ae1', '2016-05-28 18:17:25', NULL, NULL, NULL), 165 | (5, '6658a45a863123535b5331898aa6da44bc352379', '2016-05-28 18:18:04', NULL, NULL, NULL), 166 | (6, 'c28a74b985cc5d95a71d1344c91f40a0e24fc19b', '2016-05-28 18:19:50', NULL, 1, NULL), 167 | (7, '73c49f0adb6ebcb1903245653bb2377ec5dcd31e', '2016-05-28 18:25:40', NULL, 1, NULL), 168 | (8, 'bd5a641e7dce63a11c34a7740a74cf7e1223a1da', '2016-05-28 18:26:25', NULL, 1, NULL), 169 | (9, 'f033a1cc559762ad8ba05244054a8f465a3b8b28', '2016-05-28 18:27:31', NULL, 1, 1), 170 | (10, 'bb67c127cd9653899089eea0938e0da97372056d', '2016-05-28 18:28:36', NULL, 1, 1), 171 | (11, '0e9f3e2dfd02205c7dba197cf54c1cff432ea6fd', '2016-05-28 18:30:06', NULL, 1, 1), 172 | (12, '5b05a19d83ffb4f0559e9df464983deeae87e486', '2016-05-28 18:31:30', NULL, 1, 1), 173 | (13, '929df161fe9921a0e4750de3c532036f99e40fe7', '2016-05-28 18:31:55', NULL, 1, 1), 174 | (14, 'd96008566a2e84aecb403d869e2ea362f88221fc', '2016-05-28 18:32:07', NULL, 1, 1), 175 | (15, 'f4f1a52886d564aa80fcae8eafcabef579a1feb0', '2016-05-28 18:32:40', NULL, 1, 1), 176 | (16, 'd7df4d8bf5472131d3e5d032b5884c65b9a2f65a', '2016-05-28 18:34:00', NULL, 1, 1), 177 | (20, '8ab0c52713e3cb055d7bab949d34806a2807d084', '2016-05-28 18:37:17', 'consultant', 1, 1), 178 | (21, '2b11b4e4559a42f2d9ccbdf7b1ba4c83b79f015e', '2016-05-28 18:47:27', NULL, 1, 1), 179 | (22, '2dfd5a0303b1b7444445fd82287076bcdd535e44', NULL, NULL, 1, 1), 180 | (24, '59d66d169923ae3c26bcccbe9b2d893279efd62e', '2016-05-28 18:59:03', 'consultant', 1, 1), 181 | (25, 'ce3a313e9a98c9cbbe80b0b243d3f9f19d5bb1cb', NULL, NULL, 1, 1), 182 | (26, 'aacfcc24f97b0a8f4455d7c67017a72159d78f79', '2016-05-28 19:14:11', NULL, 1, 1); 183 | 184 | -- -------------------------------------------------------- 185 | 186 | -- 187 | -- Table structure for table `oauth_scopes` 188 | -- 189 | 190 | CREATE TABLE `oauth_scopes` ( 191 | `id` int(11) NOT NULL, 192 | `scope` varchar(80) DEFAULT NULL, 193 | `is_default` tinyint(1) DEFAULT NULL 194 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 195 | 196 | -- 197 | -- Dumping data for table `oauth_scopes` 198 | -- 199 | 200 | INSERT INTO `oauth_scopes` (`id`, `scope`, `is_default`) VALUES 201 | (1, 'profile', NULL); 202 | 203 | -- -------------------------------------------------------- 204 | 205 | -- 206 | -- Table structure for table `users` 207 | -- 208 | 209 | CREATE TABLE `users` ( 210 | `id` int(11) NOT NULL, 211 | `username` varchar(32) DEFAULT NULL, 212 | `password` varchar(32) DEFAULT NULL, 213 | `scope` varchar(255) DEFAULT NULL 214 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 215 | 216 | -- 217 | -- Dumping data for table `users` 218 | -- 219 | 220 | INSERT INTO `users` (`id`, `username`, `password`, `scope`) VALUES 221 | (1, 'admin', 'admin', 'profile'); 222 | 223 | -- 224 | -- Indexes for dumped tables 225 | -- 226 | 227 | -- 228 | -- Indexes for table `oauth_access_tokens` 229 | -- 230 | ALTER TABLE `oauth_access_tokens` 231 | ADD PRIMARY KEY (`id`), 232 | ADD UNIQUE KEY `id` (`id`), 233 | ADD UNIQUE KEY `oauth_access_tokens_id_unique` (`id`), 234 | ADD KEY `oauth_client_id` (`client_id`), 235 | ADD KEY `user_id` (`user_id`); 236 | 237 | -- 238 | -- Indexes for table `oauth_authorization_codes` 239 | -- 240 | ALTER TABLE `oauth_authorization_codes` 241 | ADD PRIMARY KEY (`id`), 242 | ADD UNIQUE KEY `id` (`id`), 243 | ADD UNIQUE KEY `oauth_authorization_codes_id_unique` (`id`), 244 | ADD KEY `oauth_client_id` (`client_id`), 245 | ADD KEY `user_id` (`user_id`); 246 | 247 | -- 248 | -- Indexes for table `oauth_clients` 249 | -- 250 | ALTER TABLE `oauth_clients` 251 | ADD PRIMARY KEY (`id`), 252 | ADD UNIQUE KEY `id` (`id`), 253 | ADD UNIQUE KEY `oauth_clients_id_unique` (`id`), 254 | ADD KEY `user_id` (`user_id`); 255 | 256 | -- 257 | -- Indexes for table `oauth_refresh_tokens` 258 | -- 259 | ALTER TABLE `oauth_refresh_tokens` 260 | ADD PRIMARY KEY (`id`), 261 | ADD UNIQUE KEY `id` (`id`), 262 | ADD UNIQUE KEY `oauth_refresh_tokens_id_unique` (`id`), 263 | ADD KEY `client_id` (`client_id`), 264 | ADD KEY `user_id` (`user_id`); 265 | 266 | -- 267 | -- Indexes for table `oauth_scopes` 268 | -- 269 | ALTER TABLE `oauth_scopes` 270 | ADD PRIMARY KEY (`id`), 271 | ADD UNIQUE KEY `id` (`id`), 272 | ADD UNIQUE KEY `oauth_scopes_id_unique` (`id`); 273 | 274 | -- 275 | -- Indexes for table `users` 276 | -- 277 | ALTER TABLE `users` 278 | ADD PRIMARY KEY (`id`), 279 | ADD UNIQUE KEY `id` (`id`), 280 | ADD UNIQUE KEY `users_id_unique` (`id`); 281 | 282 | -- 283 | -- AUTO_INCREMENT for dumped tables 284 | -- 285 | 286 | -- 287 | -- AUTO_INCREMENT for table `oauth_access_tokens` 288 | -- 289 | ALTER TABLE `oauth_access_tokens` 290 | MODIFY `id` int(14) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=37; 291 | -- 292 | -- AUTO_INCREMENT for table `oauth_authorization_codes` 293 | -- 294 | ALTER TABLE `oauth_authorization_codes` 295 | MODIFY `id` int(14) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=16; 296 | -- 297 | -- AUTO_INCREMENT for table `oauth_clients` 298 | -- 299 | ALTER TABLE `oauth_clients` 300 | MODIFY `id` int(14) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; 301 | -- 302 | -- AUTO_INCREMENT for table `oauth_refresh_tokens` 303 | -- 304 | ALTER TABLE `oauth_refresh_tokens` 305 | MODIFY `id` int(14) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=27; 306 | -- 307 | -- AUTO_INCREMENT for table `oauth_scopes` 308 | -- 309 | ALTER TABLE `oauth_scopes` 310 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; 311 | -- 312 | -- AUTO_INCREMENT for table `users` 313 | -- 314 | ALTER TABLE `users` 315 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; 316 | -- 317 | -- Constraints for dumped tables 318 | -- 319 | 320 | -- 321 | -- Constraints for table `oauth_access_tokens` 322 | -- 323 | ALTER TABLE `oauth_access_tokens` 324 | ADD CONSTRAINT `oauth_access_tokens_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, 325 | ADD CONSTRAINT `oauth_access_tokens_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; 326 | 327 | -- 328 | -- Constraints for table `oauth_authorization_codes` 329 | -- 330 | ALTER TABLE `oauth_authorization_codes` 331 | ADD CONSTRAINT `oauth_authorization_codes_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, 332 | ADD CONSTRAINT `oauth_authorization_codes_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; 333 | 334 | -- 335 | -- Constraints for table `oauth_clients` 336 | -- 337 | ALTER TABLE `oauth_clients` 338 | ADD CONSTRAINT `oauth_clients_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; 339 | 340 | -- 341 | -- Constraints for table `oauth_refresh_tokens` 342 | -- 343 | ALTER TABLE `oauth_refresh_tokens` 344 | ADD CONSTRAINT `oauth_refresh_tokens_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `oauth_clients` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, 345 | ADD CONSTRAINT `oauth_refresh_tokens_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; 346 | 347 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 348 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 349 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 350 | -------------------------------------------------------------------------------- /test/unit/password_grant_test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Manjesh on 13-04-2017. 3 | */ 4 | -------------------------------------------------------------------------------- /views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/geojson@^1.0.0": 6 | version "1.0.6" 7 | resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.6.tgz#3e02972728c69248c2af08d60a48cbb8680fffdf" 8 | 9 | accepts@~1.2.12: 10 | version "1.2.13" 11 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.2.13.tgz#e5f1f3928c6d95fd96558c36ec3d9d0de4a6ecea" 12 | dependencies: 13 | mime-types "~2.1.6" 14 | negotiator "0.5.3" 15 | 16 | acorn-globals@^1.0.3: 17 | version "1.0.9" 18 | resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" 19 | dependencies: 20 | acorn "^2.1.0" 21 | 22 | acorn@^1.0.1: 23 | version "1.2.2" 24 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014" 25 | 26 | acorn@^2.1.0: 27 | version "2.7.0" 28 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" 29 | 30 | align-text@^0.1.1, align-text@^0.1.3: 31 | version "0.1.4" 32 | resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" 33 | dependencies: 34 | kind-of "^3.0.2" 35 | longest "^1.0.1" 36 | repeat-string "^1.5.2" 37 | 38 | amdefine@>=0.0.4: 39 | version "1.0.1" 40 | resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" 41 | 42 | array-flatten@1.1.1: 43 | version "1.1.1" 44 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 45 | 46 | asap@~1.0.0: 47 | version "1.0.0" 48 | resolved "https://registry.yarnpkg.com/asap/-/asap-1.0.0.tgz#b2a45da5fdfa20b0496fc3768cc27c12fa916a7d" 49 | 50 | async@2.1.4: 51 | version "2.1.4" 52 | resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" 53 | dependencies: 54 | lodash "^4.14.0" 55 | 56 | async@~0.2.6: 57 | version "0.2.10" 58 | resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" 59 | 60 | balanced-match@^1.0.0: 61 | version "1.0.0" 62 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 63 | 64 | basic-auth@1.1.0: 65 | version "1.1.0" 66 | resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.1.0.tgz#45221ee429f7ee1e5035be3f51533f1cdfd29884" 67 | 68 | basic-auth@~1.0.3: 69 | version "1.0.4" 70 | resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-1.0.4.tgz#030935b01de7c9b94a824b29f3fccb750d3a5290" 71 | 72 | bignumber.js@4.0.4: 73 | version "4.0.4" 74 | resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.0.4.tgz#7c40f5abcd2d6623ab7b99682ee7db81b11889a4" 75 | 76 | bluebird@3.5.0: 77 | version "3.5.0" 78 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" 79 | 80 | bluebird@^2.10.0: 81 | version "2.11.0" 82 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" 83 | 84 | bluebird@^3.3.4, bluebird@^3.4.6, bluebird@^3.5.1: 85 | version "3.5.1" 86 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" 87 | 88 | body-parser@~1.13.2: 89 | version "1.13.3" 90 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.13.3.tgz#c08cf330c3358e151016a05746f13f029c97fa97" 91 | dependencies: 92 | bytes "2.1.0" 93 | content-type "~1.0.1" 94 | debug "~2.2.0" 95 | depd "~1.0.1" 96 | http-errors "~1.3.1" 97 | iconv-lite "0.4.11" 98 | on-finished "~2.3.0" 99 | qs "4.0.0" 100 | raw-body "~2.1.2" 101 | type-is "~1.6.6" 102 | 103 | brace-expansion@^1.1.7: 104 | version "1.1.11" 105 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 106 | dependencies: 107 | balanced-match "^1.0.0" 108 | concat-map "0.0.1" 109 | 110 | browser-stdout@1.3.0: 111 | version "1.3.0" 112 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" 113 | 114 | bson@~1.0.4: 115 | version "1.0.5" 116 | resolved "https://registry.yarnpkg.com/bson/-/bson-1.0.5.tgz#34563b73ff1fde9387c1b9fb5afd845ecc4ba623" 117 | 118 | buffer-shims@~1.0.0: 119 | version "1.0.0" 120 | resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" 121 | 122 | bytes@2.1.0: 123 | version "2.1.0" 124 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.1.0.tgz#ac93c410e2ffc9cc7cf4b464b38289067f5e47b4" 125 | 126 | bytes@2.4.0: 127 | version "2.4.0" 128 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339" 129 | 130 | camelcase@^1.0.2: 131 | version "1.2.1" 132 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" 133 | 134 | center-align@^0.1.1: 135 | version "0.1.3" 136 | resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" 137 | dependencies: 138 | align-text "^0.1.3" 139 | lazy-cache "^1.0.3" 140 | 141 | character-parser@1.2.1: 142 | version "1.2.1" 143 | resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-1.2.1.tgz#c0dde4ab182713b919b970959a123ecc1a30fcd6" 144 | 145 | clean-css@^3.1.9: 146 | version "3.4.28" 147 | resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-3.4.28.tgz#bf1945e82fc808f55695e6ddeaec01400efd03ff" 148 | dependencies: 149 | commander "2.8.x" 150 | source-map "0.4.x" 151 | 152 | cli@~1.0.0: 153 | version "1.0.1" 154 | resolved "https://registry.yarnpkg.com/cli/-/cli-1.0.1.tgz#22817534f24bfa4950c34d532d48ecbc621b8c14" 155 | dependencies: 156 | exit "0.1.2" 157 | glob "^7.1.1" 158 | 159 | cliui@^2.1.0: 160 | version "2.1.0" 161 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" 162 | dependencies: 163 | center-align "^0.1.1" 164 | right-align "^0.1.1" 165 | wordwrap "0.0.2" 166 | 167 | closure-compiler@0.2.12: 168 | version "0.2.12" 169 | resolved "https://registry.yarnpkg.com/closure-compiler/-/closure-compiler-0.2.12.tgz#6c3087cad12742c79e47f0ce50e87af91cf8e171" 170 | dependencies: 171 | google-closure-compiler "20150901.x" 172 | 173 | co-bluebird@^1.1.0: 174 | version "1.1.0" 175 | resolved "https://registry.yarnpkg.com/co-bluebird/-/co-bluebird-1.1.0.tgz#c8b9f3a9320a7ed30987dcca1a5c3cff59655c7c" 176 | dependencies: 177 | bluebird "^2.10.0" 178 | co-use "^1.1.0" 179 | 180 | co-use@^1.1.0: 181 | version "1.1.0" 182 | resolved "https://registry.yarnpkg.com/co-use/-/co-use-1.1.0.tgz#c6bb3cdf10cb735ecaa9daeeda46d725c94a4e62" 183 | 184 | commander@2.8.x: 185 | version "2.8.1" 186 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" 187 | dependencies: 188 | graceful-readlink ">= 1.0.0" 189 | 190 | commander@2.9.0: 191 | version "2.9.0" 192 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 193 | dependencies: 194 | graceful-readlink ">= 1.0.0" 195 | 196 | commander@~2.6.0: 197 | version "2.6.0" 198 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" 199 | 200 | concat-map@0.0.1: 201 | version "0.0.1" 202 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 203 | 204 | console-browserify@1.1.x: 205 | version "1.1.0" 206 | resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" 207 | dependencies: 208 | date-now "^0.1.4" 209 | 210 | constantinople@~3.0.1: 211 | version "3.0.2" 212 | resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.0.2.tgz#4b945d9937907bcd98ee575122c3817516544141" 213 | dependencies: 214 | acorn "^2.1.0" 215 | 216 | content-disposition@0.5.1: 217 | version "0.5.1" 218 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b" 219 | 220 | content-type@~1.0.1: 221 | version "1.0.4" 222 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 223 | 224 | cookie-parser@~1.3.5: 225 | version "1.3.5" 226 | resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.3.5.tgz#9d755570fb5d17890771227a02314d9be7cf8356" 227 | dependencies: 228 | cookie "0.1.3" 229 | cookie-signature "1.0.6" 230 | 231 | cookie-signature@1.0.6: 232 | version "1.0.6" 233 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 234 | 235 | cookie@0.1.3: 236 | version "0.1.3" 237 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.3.tgz#e734a5c1417fce472d5aef82c381cabb64d1a435" 238 | 239 | cookie@0.1.5: 240 | version "0.1.5" 241 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.1.5.tgz#6ab9948a4b1ae21952cd2588530a4722d4044d7c" 242 | 243 | core-util-is@~1.0.0: 244 | version "1.0.2" 245 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 246 | 247 | css-parse@1.0.4: 248 | version "1.0.4" 249 | resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-1.0.4.tgz#38b0503fbf9da9f54e9c1dbda60e145c77117bdd" 250 | 251 | css-stringify@1.0.5: 252 | version "1.0.5" 253 | resolved "https://registry.yarnpkg.com/css-stringify/-/css-stringify-1.0.5.tgz#b0d042946db2953bb9d292900a6cb5f6d0122031" 254 | 255 | css@~1.0.8: 256 | version "1.0.8" 257 | resolved "https://registry.yarnpkg.com/css/-/css-1.0.8.tgz#9386811ca82bccc9ee7fb5a732b1e2a317c8a3e7" 258 | dependencies: 259 | css-parse "1.0.4" 260 | css-stringify "1.0.5" 261 | 262 | date-now@^0.1.4: 263 | version "0.1.4" 264 | resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" 265 | 266 | debug@2.6.8: 267 | version "2.6.8" 268 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" 269 | dependencies: 270 | ms "2.0.0" 271 | 272 | debug@2.6.9, debug@^2.6.9: 273 | version "2.6.9" 274 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 275 | dependencies: 276 | ms "2.0.0" 277 | 278 | debug@~2.2.0: 279 | version "2.2.0" 280 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" 281 | dependencies: 282 | ms "0.7.1" 283 | 284 | decamelize@^1.0.0: 285 | version "1.2.0" 286 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 287 | 288 | depd@^1.1.0, depd@~1.1.0: 289 | version "1.1.2" 290 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 291 | 292 | depd@~1.0.1: 293 | version "1.0.1" 294 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" 295 | 296 | destroy@~1.0.4: 297 | version "1.0.4" 298 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 299 | 300 | diff@3.2.0: 301 | version "3.2.0" 302 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" 303 | 304 | dom-serializer@0: 305 | version "0.1.0" 306 | resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" 307 | dependencies: 308 | domelementtype "~1.1.1" 309 | entities "~1.1.1" 310 | 311 | domelementtype@1: 312 | version "1.3.0" 313 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" 314 | 315 | domelementtype@~1.1.1: 316 | version "1.1.3" 317 | resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" 318 | 319 | domhandler@2.3: 320 | version "2.3.0" 321 | resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" 322 | dependencies: 323 | domelementtype "1" 324 | 325 | domutils@1.5: 326 | version "1.5.1" 327 | resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" 328 | dependencies: 329 | dom-serializer "0" 330 | domelementtype "1" 331 | 332 | dottie@^1.0.0: 333 | version "1.1.1" 334 | resolved "https://registry.yarnpkg.com/dottie/-/dottie-1.1.1.tgz#45c2a3f48bd6528eeed267a69a848eaaca6faa6a" 335 | 336 | ee-first@1.1.1: 337 | version "1.1.1" 338 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 339 | 340 | entities@1.0: 341 | version "1.0.0" 342 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" 343 | 344 | entities@~1.1.1: 345 | version "1.1.1" 346 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" 347 | 348 | es6-promise@3.2.1: 349 | version "3.2.1" 350 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.2.1.tgz#ec56233868032909207170c39448e24449dd1fc4" 351 | 352 | escape-html@~1.0.3: 353 | version "1.0.3" 354 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 355 | 356 | escape-string-regexp@1.0.5: 357 | version "1.0.5" 358 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 359 | 360 | etag@~1.7.0: 361 | version "1.7.0" 362 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.7.0.tgz#03d30b5f67dd6e632d2945d30d6652731a34d5d8" 363 | 364 | exit@0.1.2, exit@0.1.x: 365 | version "0.1.2" 366 | resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" 367 | 368 | express@~4.13.1: 369 | version "4.13.4" 370 | resolved "https://registry.yarnpkg.com/express/-/express-4.13.4.tgz#3c0b76f3c77590c8345739061ec0bd3ba067ec24" 371 | dependencies: 372 | accepts "~1.2.12" 373 | array-flatten "1.1.1" 374 | content-disposition "0.5.1" 375 | content-type "~1.0.1" 376 | cookie "0.1.5" 377 | cookie-signature "1.0.6" 378 | debug "~2.2.0" 379 | depd "~1.1.0" 380 | escape-html "~1.0.3" 381 | etag "~1.7.0" 382 | finalhandler "0.4.1" 383 | fresh "0.3.0" 384 | merge-descriptors "1.0.1" 385 | methods "~1.1.2" 386 | on-finished "~2.3.0" 387 | parseurl "~1.3.1" 388 | path-to-regexp "0.1.7" 389 | proxy-addr "~1.0.10" 390 | qs "4.0.0" 391 | range-parser "~1.0.3" 392 | send "0.13.1" 393 | serve-static "~1.10.2" 394 | type-is "~1.6.6" 395 | utils-merge "1.0.0" 396 | vary "~1.0.1" 397 | 398 | finalhandler@0.4.1: 399 | version "0.4.1" 400 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-0.4.1.tgz#85a17c6c59a94717d262d61230d4b0ebe3d4a14d" 401 | dependencies: 402 | debug "~2.2.0" 403 | escape-html "~1.0.3" 404 | on-finished "~2.3.0" 405 | unpipe "~1.0.0" 406 | 407 | formatio@1.1.1: 408 | version "1.1.1" 409 | resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" 410 | dependencies: 411 | samsam "~1.1" 412 | 413 | forwarded@~0.1.0: 414 | version "0.1.2" 415 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" 416 | 417 | fresh@0.3.0: 418 | version "0.3.0" 419 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.3.0.tgz#651f838e22424e7566de161d8358caa199f83d4f" 420 | 421 | fs.realpath@^1.0.0: 422 | version "1.0.0" 423 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 424 | 425 | generic-pool@2.4.2: 426 | version "2.4.2" 427 | resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.2.tgz#886bc5bf0beb7db96e81bcbba078818de5a62683" 428 | 429 | glob@7.1.1: 430 | version "7.1.1" 431 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 432 | dependencies: 433 | fs.realpath "^1.0.0" 434 | inflight "^1.0.4" 435 | inherits "2" 436 | minimatch "^3.0.2" 437 | once "^1.3.0" 438 | path-is-absolute "^1.0.0" 439 | 440 | glob@^7.1.1: 441 | version "7.1.2" 442 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 443 | dependencies: 444 | fs.realpath "^1.0.0" 445 | inflight "^1.0.4" 446 | inherits "2" 447 | minimatch "^3.0.4" 448 | once "^1.3.0" 449 | path-is-absolute "^1.0.0" 450 | 451 | google-closure-compiler@20150901.x: 452 | version "20150901.0.0" 453 | resolved "https://registry.yarnpkg.com/google-closure-compiler/-/google-closure-compiler-20150901.0.0.tgz#3d01c6cade65790a9bfb4e30b2158b7635acbade" 454 | 455 | "graceful-readlink@>= 1.0.0": 456 | version "1.0.1" 457 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 458 | 459 | growl@1.9.2: 460 | version "1.9.2" 461 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" 462 | 463 | has-flag@^1.0.0: 464 | version "1.0.0" 465 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 466 | 467 | he@1.1.1: 468 | version "1.1.1" 469 | resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" 470 | 471 | hooks-fixed@2.0.2: 472 | version "2.0.2" 473 | resolved "https://registry.yarnpkg.com/hooks-fixed/-/hooks-fixed-2.0.2.tgz#20076daa07e77d8a6106883ce3f1722e051140b0" 474 | 475 | htmlparser2@3.8.x: 476 | version "3.8.3" 477 | resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" 478 | dependencies: 479 | domelementtype "1" 480 | domhandler "2.3" 481 | domutils "1.5" 482 | entities "1.0" 483 | readable-stream "1.1" 484 | 485 | http-errors@~1.3.1: 486 | version "1.3.1" 487 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.3.1.tgz#197e22cdebd4198585e8694ef6786197b91ed942" 488 | dependencies: 489 | inherits "~2.0.1" 490 | statuses "1" 491 | 492 | iconv-lite@0.4.11: 493 | version "0.4.11" 494 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.11.tgz#2ecb42fd294744922209a2e7c404dac8793d8ade" 495 | 496 | iconv-lite@0.4.13: 497 | version "0.4.13" 498 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" 499 | 500 | inflection@^1.6.0: 501 | version "1.12.0" 502 | resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" 503 | 504 | inflight@^1.0.4: 505 | version "1.0.6" 506 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 507 | dependencies: 508 | once "^1.3.0" 509 | wrappy "1" 510 | 511 | inherits@2, inherits@~2.0.1, inherits@~2.0.3: 512 | version "2.0.3" 513 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 514 | 515 | inherits@2.0.1: 516 | version "2.0.1" 517 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" 518 | 519 | ipaddr.js@1.0.5: 520 | version "1.0.5" 521 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.0.5.tgz#5fa78cf301b825c78abc3042d812723049ea23c7" 522 | 523 | is-buffer@^1.1.5: 524 | version "1.1.6" 525 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 526 | 527 | is-generator@^1.0.2: 528 | version "1.0.3" 529 | resolved "https://registry.yarnpkg.com/is-generator/-/is-generator-1.0.3.tgz#c14c21057ed36e328db80347966c693f886389f3" 530 | 531 | is-promise@^2.0.0: 532 | version "2.1.0" 533 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 534 | 535 | is-promise@~1: 536 | version "1.0.1" 537 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-1.0.1.tgz#31573761c057e33c2e91aab9e96da08cefbe76e5" 538 | 539 | isarray@0.0.1: 540 | version "0.0.1" 541 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 542 | 543 | isarray@~1.0.0: 544 | version "1.0.0" 545 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 546 | 547 | jade@~1.11.0: 548 | version "1.11.0" 549 | resolved "https://registry.yarnpkg.com/jade/-/jade-1.11.0.tgz#9c80e538c12d3fb95c8d9bb9559fa0cc040405fd" 550 | dependencies: 551 | character-parser "1.2.1" 552 | clean-css "^3.1.9" 553 | commander "~2.6.0" 554 | constantinople "~3.0.1" 555 | jstransformer "0.0.2" 556 | mkdirp "~0.5.0" 557 | transformers "2.1.0" 558 | uglify-js "^2.4.19" 559 | void-elements "~2.0.1" 560 | with "~4.0.0" 561 | 562 | jshint@^2.9.1: 563 | version "2.9.5" 564 | resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.9.5.tgz#1e7252915ce681b40827ee14248c46d34e9aa62c" 565 | dependencies: 566 | cli "~1.0.0" 567 | console-browserify "1.1.x" 568 | exit "0.1.x" 569 | htmlparser2 "3.8.x" 570 | lodash "3.7.x" 571 | minimatch "~3.0.2" 572 | shelljs "0.3.x" 573 | strip-json-comments "1.0.x" 574 | 575 | json3@3.3.2: 576 | version "3.3.2" 577 | resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" 578 | 579 | jstransformer@0.0.2: 580 | version "0.0.2" 581 | resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-0.0.2.tgz#7aae29a903d196cfa0973d885d3e47947ecd76ab" 582 | dependencies: 583 | is-promise "^2.0.0" 584 | promise "^6.0.1" 585 | 586 | kareem@1.5.0: 587 | version "1.5.0" 588 | resolved "https://registry.yarnpkg.com/kareem/-/kareem-1.5.0.tgz#e3e4101d9dcfde299769daf4b4db64d895d17448" 589 | 590 | kind-of@^3.0.2: 591 | version "3.2.2" 592 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" 593 | dependencies: 594 | is-buffer "^1.1.5" 595 | 596 | lazy-cache@^1.0.3: 597 | version "1.0.4" 598 | resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" 599 | 600 | lodash-cli@^4.15.0: 601 | version "4.17.5" 602 | resolved "https://registry.yarnpkg.com/lodash-cli/-/lodash-cli-4.17.5.tgz#1bab72c8c9980febf4fe7a1900b0971ce040dd0b" 603 | dependencies: 604 | closure-compiler "0.2.12" 605 | glob "7.1.1" 606 | lodash "4.17.5" 607 | semver "5.3.0" 608 | uglify-js "2.7.5" 609 | 610 | lodash._baseassign@^3.0.0: 611 | version "3.2.0" 612 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" 613 | dependencies: 614 | lodash._basecopy "^3.0.0" 615 | lodash.keys "^3.0.0" 616 | 617 | lodash._basecopy@^3.0.0: 618 | version "3.0.1" 619 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" 620 | 621 | lodash._basecreate@^3.0.0: 622 | version "3.0.3" 623 | resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" 624 | 625 | lodash._getnative@^3.0.0: 626 | version "3.9.1" 627 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" 628 | 629 | lodash._isiterateecall@^3.0.0: 630 | version "3.0.9" 631 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" 632 | 633 | lodash.create@3.1.1: 634 | version "3.1.1" 635 | resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" 636 | dependencies: 637 | lodash._baseassign "^3.0.0" 638 | lodash._basecreate "^3.0.0" 639 | lodash._isiterateecall "^3.0.0" 640 | 641 | lodash.get@4.4.2: 642 | version "4.4.2" 643 | resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" 644 | 645 | lodash.isarguments@^3.0.0: 646 | version "3.1.0" 647 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 648 | 649 | lodash.isarray@^3.0.0: 650 | version "3.0.4" 651 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" 652 | 653 | lodash.keys@^3.0.0: 654 | version "3.1.2" 655 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" 656 | dependencies: 657 | lodash._getnative "^3.0.0" 658 | lodash.isarguments "^3.0.0" 659 | lodash.isarray "^3.0.0" 660 | 661 | lodash@3.7.x: 662 | version "3.7.0" 663 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.7.0.tgz#3678bd8ab995057c07ade836ed2ef087da811d45" 664 | 665 | lodash@4.12.0: 666 | version "4.12.0" 667 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.12.0.tgz#2bd6dc46a040f59e686c972ed21d93dc59053258" 668 | 669 | lodash@4.17.4: 670 | version "4.17.4" 671 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 672 | 673 | lodash@4.17.5, lodash@^4.14.0, lodash@^4.15.0: 674 | version "4.17.5" 675 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" 676 | 677 | lolex@1.3.2: 678 | version "1.3.2" 679 | resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" 680 | 681 | longest@^1.0.1: 682 | version "1.0.1" 683 | resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" 684 | 685 | media-typer@0.3.0: 686 | version "0.3.0" 687 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 688 | 689 | merge-descriptors@1.0.1: 690 | version "1.0.1" 691 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 692 | 693 | methods@~1.1.2: 694 | version "1.1.2" 695 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 696 | 697 | mime-db@~1.33.0: 698 | version "1.33.0" 699 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" 700 | 701 | mime-types@~2.1.15, mime-types@~2.1.18, mime-types@~2.1.6: 702 | version "2.1.18" 703 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" 704 | dependencies: 705 | mime-db "~1.33.0" 706 | 707 | mime@1.3.4: 708 | version "1.3.4" 709 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" 710 | 711 | minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: 712 | version "3.0.4" 713 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 714 | dependencies: 715 | brace-expansion "^1.1.7" 716 | 717 | minimist@0.0.8: 718 | version "0.0.8" 719 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 720 | 721 | mkdirp@0.5.1, mkdirp@~0.5.0: 722 | version "0.5.1" 723 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 724 | dependencies: 725 | minimist "0.0.8" 726 | 727 | mocha@^3.1.2: 728 | version "3.5.3" 729 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" 730 | dependencies: 731 | browser-stdout "1.3.0" 732 | commander "2.9.0" 733 | debug "2.6.8" 734 | diff "3.2.0" 735 | escape-string-regexp "1.0.5" 736 | glob "7.1.1" 737 | growl "1.9.2" 738 | he "1.1.1" 739 | json3 "3.3.2" 740 | lodash.create "3.1.1" 741 | mkdirp "0.5.1" 742 | supports-color "3.1.2" 743 | 744 | moment-timezone@^0.5.4: 745 | version "0.5.14" 746 | resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.14.tgz#4eb38ff9538b80108ba467a458f3ed4268ccfcb1" 747 | dependencies: 748 | moment ">= 2.9.0" 749 | 750 | "moment@>= 2.9.0", moment@^2.13.0: 751 | version "2.21.0" 752 | resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" 753 | 754 | mongodb-core@2.1.18: 755 | version "2.1.18" 756 | resolved "https://registry.yarnpkg.com/mongodb-core/-/mongodb-core-2.1.18.tgz#4c46139bdf3a1f032ded91db49f38eec01659050" 757 | dependencies: 758 | bson "~1.0.4" 759 | require_optional "~1.0.0" 760 | 761 | mongodb@2.2.34: 762 | version "2.2.34" 763 | resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-2.2.34.tgz#a34f59bbeb61754aec432de72c3fe21526a44c1a" 764 | dependencies: 765 | es6-promise "3.2.1" 766 | mongodb-core "2.1.18" 767 | readable-stream "2.2.7" 768 | 769 | mongoose@^4.4.17: 770 | version "4.13.11" 771 | resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-4.13.11.tgz#da6edf8e399054e12836016316999519a358db43" 772 | dependencies: 773 | async "2.1.4" 774 | bson "~1.0.4" 775 | hooks-fixed "2.0.2" 776 | kareem "1.5.0" 777 | lodash.get "4.4.2" 778 | mongodb "2.2.34" 779 | mpath "0.3.0" 780 | mpromise "0.5.5" 781 | mquery "2.3.3" 782 | ms "2.0.0" 783 | muri "1.3.0" 784 | regexp-clone "0.0.1" 785 | sliced "1.0.1" 786 | 787 | morgan@~1.6.1: 788 | version "1.6.1" 789 | resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.6.1.tgz#5fd818398c6819cba28a7cd6664f292fe1c0bbf2" 790 | dependencies: 791 | basic-auth "~1.0.3" 792 | debug "~2.2.0" 793 | depd "~1.0.1" 794 | on-finished "~2.3.0" 795 | on-headers "~1.0.0" 796 | 797 | mpath@0.3.0: 798 | version "0.3.0" 799 | resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.3.0.tgz#7a58f789e9b5fd3c94520634157960f26bd5ef44" 800 | 801 | mpromise@0.5.5: 802 | version "0.5.5" 803 | resolved "https://registry.yarnpkg.com/mpromise/-/mpromise-0.5.5.tgz#f5b24259d763acc2257b0a0c8c6d866fd51732e6" 804 | 805 | mquery@2.3.3: 806 | version "2.3.3" 807 | resolved "https://registry.yarnpkg.com/mquery/-/mquery-2.3.3.tgz#221412e5d4e7290ca5582dd16ea8f190a506b518" 808 | dependencies: 809 | bluebird "3.5.0" 810 | debug "2.6.9" 811 | regexp-clone "0.0.1" 812 | sliced "0.0.5" 813 | 814 | ms@0.7.1: 815 | version "0.7.1" 816 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" 817 | 818 | ms@0.7.2: 819 | version "0.7.2" 820 | resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" 821 | 822 | ms@2.0.0: 823 | version "2.0.0" 824 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 825 | 826 | muri@1.3.0: 827 | version "1.3.0" 828 | resolved "https://registry.yarnpkg.com/muri/-/muri-1.3.0.tgz#aeccf3db64c56aa7c5b34e00f95b7878527a4721" 829 | 830 | mysql@^2.10.2: 831 | version "2.15.0" 832 | resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.15.0.tgz#ea16841156343e8f2e47fc8985ec41cdd9573b5c" 833 | dependencies: 834 | bignumber.js "4.0.4" 835 | readable-stream "2.3.3" 836 | safe-buffer "5.1.1" 837 | sqlstring "2.3.0" 838 | 839 | negotiator@0.5.3: 840 | version "0.5.3" 841 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.5.3.tgz#269d5c476810ec92edbe7b6c2f28316384f9a7e8" 842 | 843 | oauth2-server@^3.0.0-b2: 844 | version "3.0.0" 845 | resolved "https://registry.yarnpkg.com/oauth2-server/-/oauth2-server-3.0.0.tgz#c46276b74c3d28634d59ee981f76b58a6459cc28" 846 | dependencies: 847 | basic-auth "1.1.0" 848 | bluebird "3.5.0" 849 | lodash "4.17.4" 850 | promisify-any "2.0.1" 851 | statuses "1.3.1" 852 | type-is "1.6.15" 853 | 854 | on-finished@~2.3.0: 855 | version "2.3.0" 856 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 857 | dependencies: 858 | ee-first "1.1.1" 859 | 860 | on-headers@~1.0.0: 861 | version "1.0.1" 862 | resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" 863 | 864 | once@^1.3.0: 865 | version "1.4.0" 866 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 867 | dependencies: 868 | wrappy "1" 869 | 870 | optimist@~0.3.5: 871 | version "0.3.7" 872 | resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" 873 | dependencies: 874 | wordwrap "~0.0.2" 875 | 876 | parseurl@~1.3.1: 877 | version "1.3.2" 878 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" 879 | 880 | path-is-absolute@^1.0.0: 881 | version "1.0.1" 882 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 883 | 884 | path-to-regexp@0.1.7: 885 | version "0.1.7" 886 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 887 | 888 | process-nextick-args@~1.0.6: 889 | version "1.0.7" 890 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 891 | 892 | promise@^6.0.1: 893 | version "6.1.0" 894 | resolved "https://registry.yarnpkg.com/promise/-/promise-6.1.0.tgz#2ce729f6b94b45c26891ad0602c5c90e04c6eef6" 895 | dependencies: 896 | asap "~1.0.0" 897 | 898 | promise@~2.0: 899 | version "2.0.0" 900 | resolved "https://registry.yarnpkg.com/promise/-/promise-2.0.0.tgz#46648aa9d605af5d2e70c3024bf59436da02b80e" 901 | dependencies: 902 | is-promise "~1" 903 | 904 | promisify-any@2.0.1: 905 | version "2.0.1" 906 | resolved "https://registry.yarnpkg.com/promisify-any/-/promisify-any-2.0.1.tgz#403e00a8813f175242ab50fe33a69f8eece47305" 907 | dependencies: 908 | bluebird "^2.10.0" 909 | co-bluebird "^1.1.0" 910 | is-generator "^1.0.2" 911 | 912 | proxy-addr@~1.0.10: 913 | version "1.0.10" 914 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.0.10.tgz#0d40a82f801fc355567d2ecb65efe3f077f121c5" 915 | dependencies: 916 | forwarded "~0.1.0" 917 | ipaddr.js "1.0.5" 918 | 919 | qs@4.0.0: 920 | version "4.0.0" 921 | resolved "https://registry.yarnpkg.com/qs/-/qs-4.0.0.tgz#c31d9b74ec27df75e543a86c78728ed8d4623607" 922 | 923 | range-parser@~1.0.3: 924 | version "1.0.3" 925 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.0.3.tgz#6872823535c692e2c2a0103826afd82c2e0ff175" 926 | 927 | raw-body@~2.1.2: 928 | version "2.1.7" 929 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.1.7.tgz#adfeace2e4fb3098058014d08c072dcc59758774" 930 | dependencies: 931 | bytes "2.4.0" 932 | iconv-lite "0.4.13" 933 | unpipe "1.0.0" 934 | 935 | readable-stream@1.1: 936 | version "1.1.13" 937 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" 938 | dependencies: 939 | core-util-is "~1.0.0" 940 | inherits "~2.0.1" 941 | isarray "0.0.1" 942 | string_decoder "~0.10.x" 943 | 944 | readable-stream@2.2.7: 945 | version "2.2.7" 946 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.7.tgz#07057acbe2467b22042d36f98c5ad507054e95b1" 947 | dependencies: 948 | buffer-shims "~1.0.0" 949 | core-util-is "~1.0.0" 950 | inherits "~2.0.1" 951 | isarray "~1.0.0" 952 | process-nextick-args "~1.0.6" 953 | string_decoder "~1.0.0" 954 | util-deprecate "~1.0.1" 955 | 956 | readable-stream@2.3.3: 957 | version "2.3.3" 958 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" 959 | dependencies: 960 | core-util-is "~1.0.0" 961 | inherits "~2.0.3" 962 | isarray "~1.0.0" 963 | process-nextick-args "~1.0.6" 964 | safe-buffer "~5.1.1" 965 | string_decoder "~1.0.3" 966 | util-deprecate "~1.0.1" 967 | 968 | regexp-clone@0.0.1: 969 | version "0.0.1" 970 | resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-0.0.1.tgz#a7c2e09891fdbf38fbb10d376fb73003e68ac589" 971 | 972 | repeat-string@^1.5.2: 973 | version "1.6.1" 974 | resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 975 | 976 | require_optional@~1.0.0: 977 | version "1.0.1" 978 | resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" 979 | dependencies: 980 | resolve-from "^2.0.0" 981 | semver "^5.1.0" 982 | 983 | resolve-from@^2.0.0: 984 | version "2.0.0" 985 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" 986 | 987 | retry-as-promised@^2.0.0: 988 | version "2.3.2" 989 | resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-2.3.2.tgz#cd974ee4fd9b5fe03cbf31871ee48221c07737b7" 990 | dependencies: 991 | bluebird "^3.4.6" 992 | debug "^2.6.9" 993 | 994 | right-align@^0.1.1: 995 | version "0.1.3" 996 | resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" 997 | dependencies: 998 | align-text "^0.1.1" 999 | 1000 | safe-buffer@5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1001 | version "5.1.1" 1002 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 1003 | 1004 | samsam@1.1.2: 1005 | version "1.1.2" 1006 | resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" 1007 | 1008 | samsam@~1.1: 1009 | version "1.1.3" 1010 | resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621" 1011 | 1012 | semver@5.3.0: 1013 | version "5.3.0" 1014 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" 1015 | 1016 | semver@^5.0.1, semver@^5.1.0: 1017 | version "5.5.0" 1018 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" 1019 | 1020 | send@0.13.1: 1021 | version "0.13.1" 1022 | resolved "https://registry.yarnpkg.com/send/-/send-0.13.1.tgz#a30d5f4c82c8a9bae9ad00a1d9b1bdbe6f199ed7" 1023 | dependencies: 1024 | debug "~2.2.0" 1025 | depd "~1.1.0" 1026 | destroy "~1.0.4" 1027 | escape-html "~1.0.3" 1028 | etag "~1.7.0" 1029 | fresh "0.3.0" 1030 | http-errors "~1.3.1" 1031 | mime "1.3.4" 1032 | ms "0.7.1" 1033 | on-finished "~2.3.0" 1034 | range-parser "~1.0.3" 1035 | statuses "~1.2.1" 1036 | 1037 | send@0.13.2: 1038 | version "0.13.2" 1039 | resolved "https://registry.yarnpkg.com/send/-/send-0.13.2.tgz#765e7607c8055452bba6f0b052595350986036de" 1040 | dependencies: 1041 | debug "~2.2.0" 1042 | depd "~1.1.0" 1043 | destroy "~1.0.4" 1044 | escape-html "~1.0.3" 1045 | etag "~1.7.0" 1046 | fresh "0.3.0" 1047 | http-errors "~1.3.1" 1048 | mime "1.3.4" 1049 | ms "0.7.1" 1050 | on-finished "~2.3.0" 1051 | range-parser "~1.0.3" 1052 | statuses "~1.2.1" 1053 | 1054 | sequelize@^3.23.1: 1055 | version "3.32.1" 1056 | resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-3.32.1.tgz#f957155412346a33d4d6c8460a20dc58878188de" 1057 | dependencies: 1058 | bluebird "^3.3.4" 1059 | depd "^1.1.0" 1060 | dottie "^1.0.0" 1061 | generic-pool "2.4.2" 1062 | inflection "^1.6.0" 1063 | lodash "4.12.0" 1064 | moment "^2.13.0" 1065 | moment-timezone "^0.5.4" 1066 | retry-as-promised "^2.0.0" 1067 | semver "^5.0.1" 1068 | shimmer "1.1.0" 1069 | terraformer-wkt-parser "^1.1.0" 1070 | toposort-class "^1.0.1" 1071 | uuid "^3.0.0" 1072 | validator "^5.2.0" 1073 | wkx "0.2.0" 1074 | 1075 | serve-favicon@~2.3.0: 1076 | version "2.3.2" 1077 | resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.3.2.tgz#dd419e268de012ab72b319d337f2105013f9381f" 1078 | dependencies: 1079 | etag "~1.7.0" 1080 | fresh "0.3.0" 1081 | ms "0.7.2" 1082 | parseurl "~1.3.1" 1083 | 1084 | serve-static@~1.10.2: 1085 | version "1.10.3" 1086 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.10.3.tgz#ce5a6ecd3101fed5ec09827dac22a9c29bfb0535" 1087 | dependencies: 1088 | escape-html "~1.0.3" 1089 | parseurl "~1.3.1" 1090 | send "0.13.2" 1091 | 1092 | shelljs@0.3.x: 1093 | version "0.3.0" 1094 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" 1095 | 1096 | shimmer@1.1.0: 1097 | version "1.1.0" 1098 | resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.1.0.tgz#97d7377137ffbbab425522e429fe0aa89a488b35" 1099 | 1100 | should-equal@0.3.1: 1101 | version "0.3.1" 1102 | resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-0.3.1.tgz#bd8ea97a6748e39fad476a3be6fd72ebc2e72bf0" 1103 | dependencies: 1104 | should-type "0.0.4" 1105 | 1106 | should-format@0.0.7: 1107 | version "0.0.7" 1108 | resolved "https://registry.yarnpkg.com/should-format/-/should-format-0.0.7.tgz#1e2ef86bd91da9c2e0412335b56ababd9a2fde12" 1109 | dependencies: 1110 | should-type "0.0.4" 1111 | 1112 | should-type@0.0.4: 1113 | version "0.0.4" 1114 | resolved "https://registry.yarnpkg.com/should-type/-/should-type-0.0.4.tgz#0132a05417a6126866426acf116f1ed5623a5cd0" 1115 | 1116 | should@^5.0.1: 1117 | version "5.2.0" 1118 | resolved "https://registry.yarnpkg.com/should/-/should-5.2.0.tgz#9a4519b447b8b5eedce9eed96af3420d451a540b" 1119 | dependencies: 1120 | should-equal "0.3.1" 1121 | should-format "0.0.7" 1122 | should-type "0.0.4" 1123 | 1124 | sinon@^1.13.0: 1125 | version "1.17.7" 1126 | resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" 1127 | dependencies: 1128 | formatio "1.1.1" 1129 | lolex "1.3.2" 1130 | samsam "1.1.2" 1131 | util ">=0.10.3 <1" 1132 | 1133 | sliced@0.0.5: 1134 | version "0.0.5" 1135 | resolved "https://registry.yarnpkg.com/sliced/-/sliced-0.0.5.tgz#5edc044ca4eb6f7816d50ba2fc63e25d8fe4707f" 1136 | 1137 | sliced@1.0.1: 1138 | version "1.0.1" 1139 | resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" 1140 | 1141 | source-map@0.4.x: 1142 | version "0.4.4" 1143 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" 1144 | dependencies: 1145 | amdefine ">=0.0.4" 1146 | 1147 | source-map@~0.1.7: 1148 | version "0.1.43" 1149 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" 1150 | dependencies: 1151 | amdefine ">=0.0.4" 1152 | 1153 | source-map@~0.5.1: 1154 | version "0.5.7" 1155 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1156 | 1157 | sqlstring@2.3.0: 1158 | version "2.3.0" 1159 | resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.0.tgz#525b8a4fd26d6f71aa61e822a6caf976d31ad2a8" 1160 | 1161 | statuses@1: 1162 | version "1.4.0" 1163 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" 1164 | 1165 | statuses@1.3.1: 1166 | version "1.3.1" 1167 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" 1168 | 1169 | statuses@~1.2.1: 1170 | version "1.2.1" 1171 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.2.1.tgz#dded45cc18256d51ed40aec142489d5c61026d28" 1172 | 1173 | string_decoder@~0.10.x: 1174 | version "0.10.31" 1175 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 1176 | 1177 | string_decoder@~1.0.0, string_decoder@~1.0.3: 1178 | version "1.0.3" 1179 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 1180 | dependencies: 1181 | safe-buffer "~5.1.0" 1182 | 1183 | strip-json-comments@1.0.x: 1184 | version "1.0.4" 1185 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" 1186 | 1187 | supports-color@3.1.2: 1188 | version "3.1.2" 1189 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" 1190 | dependencies: 1191 | has-flag "^1.0.0" 1192 | 1193 | terraformer-wkt-parser@^1.1.0: 1194 | version "1.1.2" 1195 | resolved "https://registry.yarnpkg.com/terraformer-wkt-parser/-/terraformer-wkt-parser-1.1.2.tgz#336a0c8fc82094a5aff83288f69aedecd369bf0c" 1196 | dependencies: 1197 | terraformer "~1.0.5" 1198 | 1199 | terraformer@~1.0.5: 1200 | version "1.0.8" 1201 | resolved "https://registry.yarnpkg.com/terraformer/-/terraformer-1.0.8.tgz#51e0ad89746fcf2161dc6f65aa70e42377c8b593" 1202 | dependencies: 1203 | "@types/geojson" "^1.0.0" 1204 | 1205 | toposort-class@^1.0.1: 1206 | version "1.0.1" 1207 | resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988" 1208 | 1209 | transformers@2.1.0: 1210 | version "2.1.0" 1211 | resolved "https://registry.yarnpkg.com/transformers/-/transformers-2.1.0.tgz#5d23cb35561dd85dc67fb8482309b47d53cce9a7" 1212 | dependencies: 1213 | css "~1.0.8" 1214 | promise "~2.0" 1215 | uglify-js "~2.2.5" 1216 | 1217 | type-is@1.6.15: 1218 | version "1.6.15" 1219 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" 1220 | dependencies: 1221 | media-typer "0.3.0" 1222 | mime-types "~2.1.15" 1223 | 1224 | type-is@~1.6.6: 1225 | version "1.6.16" 1226 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" 1227 | dependencies: 1228 | media-typer "0.3.0" 1229 | mime-types "~2.1.18" 1230 | 1231 | uglify-js@2.7.5: 1232 | version "2.7.5" 1233 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" 1234 | dependencies: 1235 | async "~0.2.6" 1236 | source-map "~0.5.1" 1237 | uglify-to-browserify "~1.0.0" 1238 | yargs "~3.10.0" 1239 | 1240 | uglify-js@^2.4.19: 1241 | version "2.8.29" 1242 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" 1243 | dependencies: 1244 | source-map "~0.5.1" 1245 | yargs "~3.10.0" 1246 | optionalDependencies: 1247 | uglify-to-browserify "~1.0.0" 1248 | 1249 | uglify-js@~2.2.5: 1250 | version "2.2.5" 1251 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.2.5.tgz#a6e02a70d839792b9780488b7b8b184c095c99c7" 1252 | dependencies: 1253 | optimist "~0.3.5" 1254 | source-map "~0.1.7" 1255 | 1256 | uglify-to-browserify@~1.0.0: 1257 | version "1.0.2" 1258 | resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" 1259 | 1260 | unpipe@1.0.0, unpipe@~1.0.0: 1261 | version "1.0.0" 1262 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1263 | 1264 | util-deprecate@~1.0.1: 1265 | version "1.0.2" 1266 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1267 | 1268 | "util@>=0.10.3 <1": 1269 | version "0.10.3" 1270 | resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" 1271 | dependencies: 1272 | inherits "2.0.1" 1273 | 1274 | utils-merge@1.0.0: 1275 | version "1.0.0" 1276 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" 1277 | 1278 | uuid@^3.0.0: 1279 | version "3.2.1" 1280 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" 1281 | 1282 | validator@^5.2.0: 1283 | version "5.7.0" 1284 | resolved "https://registry.yarnpkg.com/validator/-/validator-5.7.0.tgz#7a87a58146b695ac486071141c0c49d67da05e5c" 1285 | 1286 | vary@~1.0.1: 1287 | version "1.0.1" 1288 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10" 1289 | 1290 | void-elements@~2.0.1: 1291 | version "2.0.1" 1292 | resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" 1293 | 1294 | window-size@0.1.0: 1295 | version "0.1.0" 1296 | resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" 1297 | 1298 | with@~4.0.0: 1299 | version "4.0.3" 1300 | resolved "https://registry.yarnpkg.com/with/-/with-4.0.3.tgz#eefd154e9e79d2c8d3417b647a8f14d9fecce14e" 1301 | dependencies: 1302 | acorn "^1.0.1" 1303 | acorn-globals "^1.0.3" 1304 | 1305 | wkx@0.2.0: 1306 | version "0.2.0" 1307 | resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.2.0.tgz#76c24f16acd0cd8f93cd34aa331e0f7961256e84" 1308 | 1309 | wordwrap@0.0.2: 1310 | version "0.0.2" 1311 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" 1312 | 1313 | wordwrap@~0.0.2: 1314 | version "0.0.3" 1315 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" 1316 | 1317 | wrappy@1: 1318 | version "1.0.2" 1319 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1320 | 1321 | yargs@~3.10.0: 1322 | version "3.10.0" 1323 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" 1324 | dependencies: 1325 | camelcase "^1.0.2" 1326 | cliui "^2.1.0" 1327 | decamelize "^1.0.0" 1328 | window-size "0.1.0" 1329 | --------------------------------------------------------------------------------