Initial import from local backup (Documents-Playground/pakerpale)

This commit is contained in:
jeonghwa
2026-07-03 05:27:31 +09:00
commit 3a8de01ba0
1794 changed files with 137027 additions and 0 deletions

2
node_modules/simple-oauth-server/.jshintignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules
example/node_modules

10
node_modules/simple-oauth-server/.jshintrc generated vendored Normal file
View File

@@ -0,0 +1,10 @@
{
"node": true,
"curly": true,
"latedef": true,
"quotmark": true,
"undef": true,
"unused": true,
"trailing": true
}

16
node_modules/simple-oauth-server/.npmignore generated vendored Normal file
View File

@@ -0,0 +1,16 @@
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
node_modules
*.log
.DS_Store

20
node_modules/simple-oauth-server/LICENCE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

119
node_modules/simple-oauth-server/README.md generated vendored Normal file
View File

@@ -0,0 +1,119 @@
# Simple OAuth Server
This is based on [OAuth](https://github.com/wpreul/OAuth) but now supports error first, async calls for all service methods.
## Installation
`npm install simple-oauth-server`
## Usage
var OAuthServer = require('simple-oauth-server'),
oauthServer = new OAuthServer(
clientService,
tokenService,
authorizationService,
membershipService,
3600,
['profile', 'status', 'avatar']
);
See [Example](#example) for an actual usage senario
## Expectations
You will need to construct the Simple OAuth Server object by passing in the following parameters.
1. TokenService object with the below signature. This service is used to generate unique tokens and authentication codes.
{
generateToken: function(callback) {}, // callback error or a token
generateAuthorizationCode: function(callback) {} // callback error or a authorization code
}
2. ClientService object with the below signature. getById will be passed an ID and will be expected to pass a client object to the callback function.
{
getById: function(id, callback) {}, // callback error or a client object
isValidRedirectUri: function(client, requestedUri) {} // return true or false if the request uri is valid
}
A client object should have the following properties at a minimum:
{
id: '1', // unique identifier
secret: 'kittens', // seceret key
grantTypes: ['implicit', 'password', 'client_credentials', 'authorization_code'] // array of supported grant types
}
A client should also store valid redirect domain(s) to ensure the user is only redirected to valid domains. As this could be one or many and storage may differ the isValidRedirectUri function needs to be implemented as above.
3. MembershipService object with the below signature.
{
areUserCredentialsValid: function(userName, password, scope, callback) {} // callback error or a boolean indicating of the credentals are valid
}
The membership service is only used if the `password` grant type is supported, if not it can be passed as null.
5. An object passed in the authorizationService parameter with the following functions:
{
saveAuthorizationCode: function(codeData, callback) {}, // callback error or code object
saveAccessToken: function(tokenData, callback) {}, // callback error or token object
getAuthorizationCode: function(code, callback) {}, // callback error or code object
getAccessToken: function(token, callback) {} // callback error or token object
}
An authorization code object should have these properties at a minimum:
{
code: '2ac2ab84-bed8-4cd9-a255-54212074b7ce', // complex unique identifier
expiresDate: '2014-07-02T18:40:59.595Z' // expiry date
}
A token object will have these properties when passed to the save function:
{
access_token: '9d357269-fe29-4ace-80b6-1ccc14744bd0', // complex unique identifier
expires_in: '2014-07-02T18:40:59.595Z' // expiry date
refresh_token: 'f961820e-ef0e-4ff9-8c89-bcebd95b2bda' // optional complex unique identifier
}
## Example
Please refer to the example folder for a demonstration of using the server.
The example uses `beeline` as a simple router and `node-uuid` to generate example tokens, but Simple OAuth Server does not do any route handling or token creation itself.
To use the example please navigate into the folder and run `npm install` to install the modules needed for the example. (You will also need to npm install in the root project directory)
Below are some manual steps you can run to show the example code in action.
1. Make a GET request to `http://localhost:8080/oauth/authorize?client_id=1&response_type=code&redirect_uri=http://google.com&scope=profile`
This will return an object similar to the below:
{
"redirectUri": "http://google.com?code=d494bbe3-d7e7-4f46-a2c7-ba1b680cae6c&expires_in=3600&scope=profile,"
}
2. Using the output from step 1, make a GET request to `http://localhost:8080/oauth/token?client_id=1&grant_type=authorization_code&client_secret=kittens&code=[THE CODE FROM STEP 1]`
This will return an object similar to the below:
{
"token_type": "Bearer",
"expires_in": "2014-06-29T18:49:00.332Z",
"access_token": "a90cd0df-786d-4a8d-a7fc-5b6c7f08d555",
"refresh_token": "2e1ae953-e1e6-439b-927f-7d4063760920"
}
3. Using the output from step 2, make a GET request to `http://localhost:8080/api/test` with the `Authorization` header set to "Bearer [ACCESS TOKEN FROM STEP 2]"
This will return an object similar to the below:
{
"isValid":true
}

71
node_modules/simple-oauth-server/example/index.js generated vendored Normal file
View File

@@ -0,0 +1,71 @@
var http = require('http'),
port = 8080,
server = http.createServer(),
beeline = require('beeline'),
supportedScopes = ['profile', 'status', 'avatar'],
expiresIn = 3600,
OAuthServer = require('../'),
services = require('./services'),
oauthServer = new OAuthServer(
services.clientService,
services.tokenService,
services.authorizationService,
services.membershipService,
expiresIn,
supportedScopes
);
function authorize(request, response) {
oauthServer.authorizeRequest(request, 'accountid', function(error, authorizationResult) {
if(error){
response.statusCode = 400;
return response.end(JSON.stringify(error));
}
// var code = require('url').parse(authorizationResult.redirectUri, true).query.code;
// response.statusCode = 302;
// response.setHeader('Location', 'http://localhost:8080/oauth/token?client_id=1&grant_type=authorization_code&client_secret=kittens&code=' + code);
response.end(JSON.stringify(authorizationResult));
});
}
function grantToken(request, response) {
oauthServer.grantAccessToken(request, function(error, token) {
if(error){
response.statusCode = 400;
return response.end(JSON.stringify(error));
}
response.end(JSON.stringify(token));
});
}
function apiEndpoint(request, response) {
oauthServer.validateAccessToken(request, function(error, validationResult) {
if(error){
response.statusCode = 401;
return response.end(JSON.stringify(error));
}
response.end(JSON.stringify(validationResult));
});
}
var routes = {
'/oauth/authorize': authorize,
'/oauth/token': grantToken,
'/api/test': apiEndpoint
};
server.on('request', beeline.route(routes));
server.listen(port, function(error){
if(error){
console.error(error);
return process.exit(-1);
}
console.log('Listening on port: ' + port);
});

View File

@@ -0,0 +1,8 @@
{
"devDependencies": {
"beeline": "^0.2.2"
},
"dependencies": {
"kgo": "^1.0.0"
}
}

50
node_modules/simple-oauth-server/example/services.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
var uuid = require('node-uuid'),
authCodes = {},
accessTokens = {},
clients = {
'1': {
id: '1',
secret: 'kittens',
grantTypes: ['implicit', 'password', 'client_credentials', 'authorization_code']
}
};
module.exports = {
clientService: {
getById: function(id, callback) {
return callback(null, clients[id]);
},
isValidRedirectUri: function(/*client, requestedUri*/) {
return true;
}
},
tokenService: {
generateToken: function(callback) {
callback(null, uuid.v4());
},
generateAuthorizationCode: function(callback) {
callback(null, uuid.v4());
}
},
authorizationService: {
saveAuthorizationCode: function(codeData, callback) {
authCodes[codeData.code] = codeData;
return callback(null, authCodes[codeData.code]);
},
saveAccessToken: function(tokenData, callback) {
accessTokens[tokenData.access_token] = tokenData;
return callback(null, accessTokens[tokenData.access_token]);
},
getAuthorizationCode: function(code, callback) {
return callback(null, authCodes[code]);
},
getAccessToken: function(token, callback) {
return callback(null, accessTokens[token]);
}
},
membershipService: {
areUserCredentialsValid: function(userName, password, scope, callback) {
return callback(null, true);
}
}
};

40
node_modules/simple-oauth-server/index.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
var lib = require('./lib');
function AuthServer(clientService, tokenService, authorizationService, membershipService, expiresIn, supportedScopes) {
var authServer = this;
if(!(authServer instanceof AuthServer)) {
return new AuthServer(clientService, tokenService, authorizationService, membershipService, expiresIn, supportedScopes);
}
authServer.clientService = clientService;
authServer.tokenService = tokenService;
authServer.authorizationService = authorizationService;
authServer.membershipService = membershipService;
authServer.expiresIn = expiresIn || 3600;
authServer.supportedScopes = supportedScopes ? supportedScopes : [];
}
AuthServer.prototype.getExpiresDate = function () {
return new Date(Date.now() + this.expiresIn * 60000);
};
AuthServer.prototype.isSupportedScope = function (scopes) {
if(!Array.isArray(scopes)){
scopes = [scopes];
}
for(var i = 0; i < scopes.length; i++){
if(!~this.supportedScopes.indexOf(scopes[i])){
return false;
}
}
return true;
};
AuthServer.prototype.authorizeRequest = lib.authorizeRequest;
AuthServer.prototype.getTokenData = lib.getTokenData;
AuthServer.prototype.grantAccessToken = lib.grantAccessToken;
AuthServer.prototype.validateAccessToken = lib.validateAccessToken;
module.exports = AuthServer;

View File

@@ -0,0 +1,118 @@
var errors = require('./errors'),
url = require('url');
function buildAuthorizationUri(context, expiresIn, code, token) {
var redirect = url.parse(context.redirect_uri, true);
delete redirect.search;
if (context.scope) {
redirect.query.scope = context.scope.join(',');
}
if (context.state) {
redirect.query.state = context.state;
}
if (expiresIn) {
redirect.query.expires_in = expiresIn;
}
if (code) {
redirect.query.code = code;
}
if (token) {
redirect.query.access_token = token;
redirect.query.token_type = 'Bearer';
}
return url.format(redirect);
}
function authorizeRequestWithClient(authServer, client, context, accountId, callback) {
if (!client) {
return callback(errors.invalidClient(context));
}
if (!context.redirect_uri || !authServer.clientService.isValidRedirectUri(client, context.redirect_uri)) {
return callback(errors.redirectUriMismatch(context));
}
function finalResponse(error, data) {
if(error){
return callback(error);
}
callback(
null,
{
redirectUri: buildAuthorizationUri(context, authServer.expiresIn, data.code, data.access_token),
state: context
}
);
}
if (context.response_type === 'code') {
authServer.tokenService.generateAuthorizationCode(function(error, code){
if(error){
return callback(error);
}
authServer.authorizationService.saveAuthorizationCode({
code: code,
redirectUri: context.redirect_uri,
clientId: client.id,
expiresDate: authServer.getExpiresDate(),
accountId: accountId
}, finalResponse);
});
return;
}
if (context.response_type === 'token') {
authServer.tokenService.generateToken(function(error, token){
if(error){
return callback(error);
}
authServer.authorizationService.saveAccessToken({
clientId: client.id,
access_token: token,
expires_in: authServer.getExpiresDate(),
accountId: accountId,
token_type: 'Bearer'
}, finalResponse);
});
return;
}
callback(errors.invalidResponseType(context.state));
}
function authorizeRequest(context, accountId, callback) {
var authServer = this;
if (!context || !context.response_type) {
return callback(errors.invalidRequest(context));
}
if (context.response_type !== 'token' && context.response_type !== 'code') {
return callback(errors.unsupportedResponseType(context));
}
if (!authServer.isSupportedScope(context.scope)) {
return callback(errors.invalidScope(context));
}
authServer.clientService.getById(context.client_id, function(error, client){
if(error){
return callback(error);
}
authorizeRequestWithClient(authServer, client, context, accountId, callback);
});
}
module.exports = authorizeRequest;

119
node_modules/simple-oauth-server/lib/errors.js generated vendored Normal file
View File

@@ -0,0 +1,119 @@
function invalidRequest(state) {
return {
error: 'invalid_request',
error_description: 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.',
state: state
};
}
function unauthorizedClient(state) {
return {
error: 'unauthorized_client',
error_description: 'The client is not authorized to request an authorization code using this method.',
state: state
};
}
function accessDenied(state) {
return {
error: 'access_denied',
error_description: 'The resource owner or authorization server denied the request.',
state: state
};
}
function unsupportedResponseType(state) {
return {
error: 'unsupported_response_type',
error_description: 'The authorization server does not support obtaining an authorization code using this method.',
state: state
};
}
function redirectUriMismatch(state) {
return {
error: 'invalid_request',
error_description: 'The redirect URI doesn\'t match what is stored for this client',
state: state
};
}
function invalidScope(state) {
return {
error: 'invalid_scope',
error_description: 'The requested scope is invalid, unknown, or malformed.',
state: state
};
}
function invalidResponseType(state) {
return {
error: 'unsupported_response_type',
error_description: 'The authorization server does not support this response type.',
state: state
};
}
function clientCredentialsInvalid(state) {
return {
error: 'unauthorized_client',
error_description: 'The client credentials are invalid.',
state: state
};
}
function userCredentialsInvalid(state) {
return {
error: 'access_denied',
error_description: 'The user credentials are invalid.',
state: state
};
}
function unsupportedGrantType(state) {
return {
error: 'unsupported_grant_type',
error_description: 'The authorization grant type is not supported by the authorization server.',
state: state
};
}
function unsupportedGrantTypeForClient(state) {
return {
error: 'unauthorized_client',
error_description: 'The grant type is not supported for this client.',
state: state
};
}
function invalidAuthorizationCode(state) {
return {
error: 'invalid_grant',
error_description: 'The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.',
state: state
};
}
function invalidClient(state) {
return {
error: 'invalid_client',
error_description: 'Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).',
state: state
};
}
module.exports = {
invalidRequest: invalidRequest,
unauthorizedClient: unauthorizedClient,
accessDenied: accessDenied,
unsupportedResponseType: unsupportedResponseType,
redirectUriMismatch: redirectUriMismatch,
invalidScope: invalidScope,
invalidResponseType: invalidResponseType,
clientCredentialsInvalid: clientCredentialsInvalid,
userCredentialsInvalid: userCredentialsInvalid,
unsupportedGrantType: unsupportedGrantType,
unsupportedGrantTypeForClient: unsupportedGrantTypeForClient,
invalidAuthorizationCode: invalidAuthorizationCode,
invalidClient: invalidClient
};

View File

@@ -0,0 +1,75 @@
var url = require('url'),
queryString = require('querystring');
function getPostData(request, callback){
if(!request.readable){
//In some circumstances the body has already been
//parsed. Check the commonly used "body" property.
return callback(null, request.body);
}
var data = '';
request.on('data',function(chunk){
if(data.length > (1e6)){
// flood attack, kill.
return request.connection.destroy();
}
data += chunk.toString();
});
request.on('end', function(){
if (data) {
return callback(null, queryString.parse(data));
}
callback();
});
}
function getBearerToken(request) {
if (request && request.headers && request.headers.authorization &&
request.headers.authorization.toLowerCase().indexOf('bearer ') === 0) {
return request.headers.authorization.split(' ').pop();
}
}
function getOauthParameters(callback) {
return function(){
var authServer = this,
args = Array.prototype.slice.call(arguments),
request = args.shift();
getPostData(request, function(error, data){
if(error){
// non error callback but non valid context so OAuth errors will be returned.
return callback(error);
}
if(!data){
data = {};
}
var query = url.parse(request.url, true).query;
for(var key in query){
data[key] = query[key];
}
if(data.scope){
data.scope = data.scope.split(',');
}
if(!data.access_token){
data.access_token = getBearerToken(request);
}
args.unshift(data);
callback.apply(authServer, args);
});
};
}
module.exports = getOauthParameters;

82
node_modules/simple-oauth-server/lib/getTokenData.js generated vendored Normal file
View File

@@ -0,0 +1,82 @@
var errors = require('./errors'),
grantTypes = require('./grantTypes'),
kgo = require('kgo');
function isValidAuthorizationCode(authorizationCode, context) {
return authorizationCode &&
context.code === authorizationCode.code &&
authorizationCode.expiresDate > new Date() &&
'' + context.client_id === '' + authorizationCode.clientId;
}
function getTokenData(context, callback) {
var authServer = this,
tokenData = {
token_type: 'Bearer',
expires_in: authServer.getExpiresDate(),
clientId: context.client_id
};
if (context.grant_type === grantTypes.AUTHORIZATIONCODE) {
authServer.authorizationService.getAuthorizationCode(context.code, function(error, authorizationCode){
if(error){
return callback(error);
}
if(!isValidAuthorizationCode(authorizationCode, context)){
return callback(errors.invalidAuthorizationCode(context));
}
tokenData.accountId = authorizationCode.accountId;
kgo
('token', authServer.tokenService.generateToken)
('refreshToken', authServer.tokenService.generateToken)
('tokenData', ['token', 'refreshToken'], function(token, refreshToken, done){
tokenData.access_token = token;
tokenData.refresh_token = refreshToken;
done(null, tokenData);
})
(['*', 'tokenData'], callback);
});
return;
}
if (context.grant_type === grantTypes.PASSWORD) {
authServer.membershipService.areUserCredentialsValid(context.username, context.password, context.scope, function (error, isValidPassword) {
if(error){
return callback(error);
}
if(!isValidPassword){
return callback(errors.userCredentialsInvalid(context));
}
kgo
('token', authServer.tokenService.generateToken)
('refreshToken', authServer.tokenService.generateToken)
('tokenData', ['token', 'refreshToken'], function(token, refreshToken, done){
tokenData.access_token = token;
tokenData.refresh_token = refreshToken;
done(null, tokenData);
})
(['*', 'tokenData'], callback);
});
return;
}
if (context.grant_type === grantTypes.CLIENTCREDENTIALS) {
kgo
('token', authServer.tokenService.generateToken)
('tokenData', ['token'], function(token, done){
tokenData.access_token = token;
done(null, tokenData);
})
(['*', 'tokenData'], callback);
return;
}
return callback(errors.unsupportedGrantType(context));
}
module.exports = getTokenData;

View File

@@ -0,0 +1,65 @@
var errors = require('./errors'),
getTokenData = require('./getTokenData'),
grantTypes = require('./grantTypes');
function isAllowed(grantType, oauthProvider) {
return grantType === grantTypes.IMPLICIT ||
(grantType === grantTypes.AUTHORIZATIONCODE && oauthProvider.authorizationService) ||
(grantType === grantTypes.CLIENTCREDENTIALS && oauthProvider.clientService) ||
(grantType === grantTypes.PASSWORD && oauthProvider.membershipService) ||
false;
}
function grantAccessToken(context, callback) {
var authServer = this;
if (!context.grant_type) {
return callback(errors.invalidRequest(context));
}
if (!isAllowed(context.grant_type, authServer)) {
return callback(errors.unsupportedGrantType(context));
}
authServer.clientService.getById(context.client_id, function (error, client) {
if(error){
return callback(error);
}
if(!client) {
return callback(errors.invalidClient(context));
}
if(!client.grantTypes || !~client.grantTypes.indexOf(context.grant_type)) {
return callback(errors.unsupportedGrantTypeForClient(context));
}
if(
(
context.grant_type === grantTypes.AUTHORIZATIONCODE ||
context.grant_type === grantTypes.CLIENTCREDENTIALS
) &&
context.client_secret !== client.secret
){
return callback(errors.clientCredentialsInvalid(context));
}
getTokenData.call(authServer, context, function (error, tokenData) {
if(error){
return callback(error);
}
authServer.authorizationService.saveAccessToken(tokenData, function (error, token) {
if(error){
return callback(error);
}
delete token.accountId;
delete token.clientId;
callback(null, token);
});
});
});
}
module.exports = grantAccessToken;

6
node_modules/simple-oauth-server/lib/grantTypes.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
PASSWORD: 'password',
IMPLICIT: 'implict',
AUTHORIZATIONCODE: 'authorization_code',
CLIENTCREDENTIALS: 'client_credentials'
};

8
node_modules/simple-oauth-server/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
var getOauthParameters = require('./getOauthParameters');
module.exports = {
authorizeRequest: getOauthParameters(require('./authorizeRequest')),
getTokenData: getOauthParameters(require('./getTokenData')),
grantAccessToken: getOauthParameters(require('./grantAccessToken')),
validateAccessToken: getOauthParameters(require('./validateAccessToken'))
};

View File

@@ -0,0 +1,32 @@
function validateAccessToken(context, callback) {
this.authorizationService.getAccessToken(context.access_token, function (error, tokenData) {
if(error){
return callback(error);
}
if (!tokenData || !tokenData.access_token || '' + context.client_id !== '' + tokenData.clientId) {
return callback({
isValid: false,
error: 'Access token not found'
});
}
if (tokenData.expiresDate < new Date()) {
return callback({
isValid: false,
error: 'Access token has expired'
});
}
callback(
null,
{
isValid: true,
accountId: tokenData.accountId,
clientId: tokenData.clientId
}
);
});
}
module.exports = validateAccessToken;

View File

@@ -0,0 +1,2 @@
node_modules
*.browser.js

View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014 Kory Nunn
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,175 @@
kgo
===
Stupidly easy flow control.
## Why
flow contol should be seamless, you should be able to say what you want done, and say kgo.
## Usage
kgo(result name, [dependencies], asynchronous function);
where result name is an arbitrary string that can be concidered a name for the output of the function,
dependencies is an array of strings that map to the output of another function,
and asynchronous function is a function that, when complete, calls a callback with its results.
kgo returns its-self, so it can be chained:
kgo
(name, deps, fn)
(name, deps, fn)
(name, deps, fn);
## Example
require kgo:
var kgo = require('./kgo');
use kgo:
kgo
('things', function(done){
//Something async
setTimeout(function(){
done(null, 1);
}, 100);
})
('stuff', function(done){
//Something async
setTimeout(function(){
done(null, 2);
}, 100);
})
('whatsits', ['things', 'stuff'], function(things, stuff, done){
//Something async
setTimeout(function(){
done(null, things + stuff);
}, 100);
})
('dooby', ['things'], function(things, done){
//Something async
setTimeout(function(){
done(null, things/2);
}, 100);
})
(['whatsits', 'dooby'], function(whatsits, dooby, done){
//Done
console.log(whatsits, dooby);
})
.on('complete', function(){
// All dones have been called OR an error occured
});
.on('error', function(error, stepNames){
// handle the error for the given step.
});
The above will log 3, 0.5;
## Async Mapping
Removed as of version 2. Use (foreign)[https://www.npmjs.com/package/foreign] instead.
## Ignoring dependency results
You will often not need the result of a dependency, and it's annoying to have unused parameters in your functions.
You can specify that you have a dependancy, whos result you don't want, by prefixing the dependancy name with an exclamation mark:
kgo
('a', function(done){
done(null, 'foo');
})
('b', ['!a'], function(done){
done(null, 'bar');
})
(['b'], function(b){
// here b will be "bar"
});
## Defaults
You can define default data for use in later tasks by passing an object into kgo, where the keys in the objects will map to dependency names:
kgo
({
foo: 1
})
('bar', function(done){
done(null, 2);
})
('baz', ['foo', 'bar'], function(foo, bar, done){
});
This is especially useful when you want to use named functions that need additional parameters to run:
var fs = require('fs');
kgo
({
'sourcePath': '/foo/bar'
})
('files', ['sourcePath'], fs.readdir);
### Note: You may only define defaults once in a kgo block. Extra calls will result in an error.
## Multiple results
You can return more than one result in a single task by giving your task multiple names, and returning more results in the callback
kgo
('foo', 'bar', function(done){
done(null, 2, 4);
})
('baz', ['foo', 'bar'], function(foo, bar, done){
// foo === 2
// bar === 4
});
## Errors
Yeah them annoying things.
kgo has EventEmitter methods on it, so you can bind to 'error'
The handler gets passed the error, and the name of the step that returned the error.
kgo
(task)
(another task)
.on('error', function(error, stepName){
});
## Complete
the `complete` event will be emitted when either an error has been returned, or all tasks done methods have been called.
kgo
(task)
(another task)
.on('complete', function(){
});

View File

@@ -0,0 +1,111 @@
var run = require('./run'),
EventEmitter = require('events').EventEmitter;
var defer = typeof setImmediate === 'function' ? setImmediate : setTimeout;
function newKgo(){
var returnlessId = 0,
tasks = {},
results = {},
inFlight,
defaultsDefined;
function kgoFn(){
if(!arguments.length){
throw new Error('kgo must must be called with a task or defaults');
}
if(inFlight){
throw new Error('No tasks or defaults may be set after kgo is in flight');
}
var argIndex = 0;
while(typeof arguments[argIndex] === 'string'){
argIndex++;
}
var names = Array.prototype.slice.call(arguments, 0, argIndex),
dependencies,
fn;
if(!names.length){
names.push((returnlessId++).toString() + '__returnless');
}
if(typeof arguments[argIndex] === 'object' && !Array.isArray(arguments[argIndex])){
var defaults = arguments[argIndex];
if(defaultsDefined){
throw new Error('Defaults may be defined only once per kgo');
}
for(var key in defaults){
if(key in tasks){
throw new Error('A task is already defined for ' + key);
}
results[key] = defaults[key];
}
defaultsDefined = true;
return kgoFn;
}
if(Array.isArray(arguments[argIndex])){
dependencies = arguments[argIndex];
argIndex++;
}
if(typeof arguments[argIndex] === 'function'){
fn = arguments[argIndex];
}
if(typeof fn !== 'function'){
throw new Error('No function provided for task number ' + Object.keys(tasks).length + ' (' + names + ')');
}
for(var i = 0; i < names.length; i++){
if(names[i] in results){
throw new Error('A default with the same name as this task (' + names[i] + ') has already been set');
}
}
if(!dependencies){
dependencies = [];
}
dependencies.map(function(dependency){
if(typeof dependency !== 'string'){
throw new Error('dependency was not a string: ' + dependency + ' in task: ' + names);
}
});
names.map(function(name){
if(name in tasks){
throw new Error('A task with the same name (' + name + ') is aready defined');
}
tasks[name] = {
names: names,
args: dependencies,
fn: fn
};
});
return kgoFn;
}
for(var key in EventEmitter.prototype){
kgoFn[key] = EventEmitter.prototype[key];
}
kgoFn.apply(null, arguments);
defer(function(){
inFlight = true;
run(tasks, results, kgoFn);
});
return kgoFn;
}
module.exports = newKgo;

View File

@@ -0,0 +1,70 @@
{
"_from": "kgo@^2.2.1",
"_id": "kgo@2.2.1",
"_inBundle": false,
"_integrity": "sha1-9ijnEnFsZzinYqB/hdPnqGdWVWw=",
"_location": "/simple-oauth-server/kgo",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "kgo@^2.2.1",
"name": "kgo",
"escapedName": "kgo",
"rawSpec": "^2.2.1",
"saveSpec": null,
"fetchSpec": "^2.2.1"
},
"_requiredBy": [
"/simple-oauth-server"
],
"_resolved": "https://registry.npmjs.org/kgo/-/kgo-2.2.1.tgz",
"_shasum": "f628e712716c6738a762a07f85d3e7a86756556c",
"_spec": "kgo@^2.2.1",
"_where": "D:\\dev\\xmap\\cm-oauth\\node_modules\\simple-oauth-server",
"author": {
"name": "Kory Nunn",
"email": "knunn187@gmail.com"
},
"bugs": {
"url": "https://github.com/korynunn/kgo/issues"
},
"bundleDependencies": false,
"dependencies": {
"stack-slice": "^1.0.0"
},
"deprecated": false,
"description": "Flow control the super easy way",
"devDependencies": {
"tape": "^4.0.0"
},
"directories": {
"test": "test"
},
"homepage": "https://github.com/korynunn/kgo",
"license": "MIT",
"main": "kgo.js",
"name": "kgo",
"repository": {
"type": "git",
"url": "git+https://github.com/korynunn/kgo.git"
},
"scripts": {
"test": "node test",
"watch": "watchify test/index.js -o test/index.browser.js -d"
},
"testling": {
"files": "./test/index.js",
"browsers": [
"ie/6..latest",
"chrome/22..latest",
"firefox/16..latest",
"safari/latest",
"opera/11.0..latest",
"iphone/6",
"ipad/6",
"android-browser/latest"
]
},
"version": "2.2.1"
}

View File

@@ -0,0 +1,167 @@
var stackSlice = require('stack-slice'),
ignoreDependency = /^\!.+/,
errorSymbol = '*';
function Step(task, args, done){
this._task = task;
this._args = args;
this._done = done;
}
Step.prototype.run = function(){
var step = this,
didError;
this._task.fn.apply(this, this._args.concat([function(error){
var result = Array.prototype.slice.call(arguments, 1);
if(error){
didError = true;
step.done(error);
}else if(!didError){
step.done(null, result);
}
}]));
};
Step.prototype.done = function(error, result){
if(error){
if(error instanceof Error){
stackSlice(error, __dirname, true);
}
return this._done(error);
}
this._done(null, result);
};
function runTask(task, results, aboutToRun, done, error){
var names = task.names,
dependants = task.args,
args = [];
if(dependants){
var useError = dependants[0] === errorSymbol;
if(useError && !error && dependants.length === 1){
return;
}
for(var i = 0; i < dependants.length; i++) {
var isErrorDep = dependants[i] === errorSymbol,
dependantName = dependants[i],
ignore = dependantName.match(ignoreDependency);
if(isErrorDep){
args.push(error);
continue;
}
if(useError && error){
args.push(undefined);
continue;
}
if(error){
return;
}
if(ignore){
dependantName = dependantName.slice(1);
}
if(!(dependantName in results)){
return;
}
if(!ignore){
args.push(results[dependantName]);
}
}
}
var step = new Step(task, args, function(error, results){
done(names, error, results);
});
aboutToRun(names);
step.run();
}
function run(tasks, results, emitter, error){
var currentTask,
noMoreTasks = true;
if(emitter._complete){
return;
}
for(var key in tasks){
noMoreTasks = false;
currentTask = tasks[key];
runTask(
currentTask,
results,
function(names){
names.map(function(name){
delete tasks[name];
});
},
function(names, taskError, taskResults){
if(emitter._complete){
return;
}
if(taskError){
run(tasks, results, emitter, taskError);
emitter._complete = true;
if(!error){
emitter.emit('error', taskError, names);
emitter.emit('complete');
}
return;
}
for(var i = 0; i < names.length; i++){
results[names[i]] = taskResults[i];
}
run(tasks, results, emitter);
},
error
);
}
if(noMoreTasks && Object.keys(results).length === emitter._taskCount){
emitter._complete = true;
emitter.emit('complete');
}
}
function cloneAndRun(tasks, results, emitter){
var todo = {},
hasErrorTask;
emitter._taskCount = Object.keys(results).length;
function checkDependencyIsDefined(result, dependencyName){
dependencyName = dependencyName.match(/\!?(.*)/)[1];
if(dependencyName !== errorSymbol && !(dependencyName in tasks) && !(dependencyName in results)){
throw new Error('No task or result has been defined for dependency: ' + dependencyName);
}
return result || dependencyName === errorSymbol;
}
for(var key in tasks){
todo[key] = tasks[key];
emitter._taskCount ++;
hasErrorTask = tasks[key].args.reduce(checkDependencyIsDefined, false) || hasErrorTask;
}
if(hasErrorTask){
emitter.on('error', function(){});
}
run(todo, results, emitter);
}
module.exports = cloneAndRun;

View File

@@ -0,0 +1 @@
<script src="index.browser.js"></script>

View File

@@ -0,0 +1,495 @@
var test = require('tape'),
kgo = require('../');
function doAsync(done){
var args = Array.prototype.slice.call(arguments, 1);
setTimeout(function(){
done.apply(null, args);
}, 100);
}
test('no function', function(t){
t.plan(1);
t.throws(function(){
kgo('things');
});
});
test('waterfall', function(t){
t.plan(2);
kgo('things', function(done){
doAsync(done, null, 1);
})('stuff', ['things'], function(things, done){
doAsync(done, null, 2 + things);
})(['stuff'], function(stuff, done){
t.equal(stuff, 3);
done();
})
.on('complete', function(){
t.pass();
});
});
test('parallel', function(t){
t.plan(3);
kgo('things', function(done){
doAsync(done, null, 1);
})('stuff', function(done){
doAsync(done, null, 2);
})(['things', 'stuff'], function(things, stuff, done){
t.equal(things, 1);
t.equal(stuff, 2);
done();
})
.on('complete', function(){
t.pass();
});
});
test('errors', function(t){
t.plan(3);
kgo
('things', function(done){
doAsync(done, null, 1);
})
('stuff', ['things'], function(things, done){
done(new Error('stuff screwed up'));
})
(['stuff'], function(stuff, done){
t.equal(stuff, 3);
done();
})
.on('error', function(error, names){
t.equal(names[0], 'stuff');
t.equal(error.message, 'stuff screwed up');
})
.on('complete', function(){
t.pass();
});
});
test('multiple errors', function(t){
t.plan(2);
kgo
('foo', function(done){
doAsync(done, new Error('foo screwed up'), 1);
})
('bar', function(done){
doAsync(done, new Error('bar screwed up'), 1);
})
.on('error', function(){
t.pass();
})
.on('complete', function(){
t.pass();
});
});
test('multiple errors 2', function(t){
t.plan(2);
kgo
('foo', function(done){
done(new Error('foo screwed up'));
})
('bar', function(done){
done(new Error('bar screwed up'));
})
.on('error', function(){
t.pass();
})
.on('complete', function(){
t.pass();
});
});
test('returnless', function(t){
t.plan(3);
kgo
('a', function(done){
doAsync(done, null, 1);
})
('b', ['a'], function(a, done){
doAsync(done, null, 1);
})
(['b'], function(b, done){
t.pass('got first task');
done();
})
(['b'], function(b, done){
t.pass('got second task');
done();
})
.on('complete', function(){
t.pass();
});
});
test('ignore dependencies', function(t){
t.plan(2);
kgo
('a', function(done){
doAsync(done, null, 1);
})
('b', ['!a'], function(done){
doAsync(done, null, 1);
})
(['b'], function(b, done){
t.equal(b, 1, 'got correct parameter');
done();
})
.on('complete', function(){
t.pass();
});
});
test('defaults', function(t){
t.plan(3);
kgo
({
things: 1,
stuff: 2
})
(['things', 'stuff'], function(things, stuff, done){
t.equal(things, 1);
t.equal(stuff, 2);
done();
})
.on('complete', function(){
t.pass();
});
});
test('defaults with same taskname', function(t){
t.plan(1);
t.throws(function(){
kgo
({
things: 1,
stuff: 2
})
('stuff', function(done){
doAsync(done, null, 2);
})
(['things', 'stuff'], function(things, stuff, done){
t.fail('task ran but should not have');
done();
});
}, 'cannot define a task with the same name as that of a default');
});
test('defaults with same taskname, after task', function(t){
t.plan(1);
t.throws(function(){
kgo
('stuff', function(done){
doAsync(done, null, 2);
})
({
things: 1,
stuff: 2
})
(['things', 'stuff'], function(things, stuff, done){
t.fail('task ran but should not have');
done();
});
}, 'set defaults containing a key that conflicts with a task name');
});
test('double defaults', function(t){
t.plan(1);
t.throws(function(){
kgo
({
things: 1
})
({
stuff: 2
})
(['things', 'stuff'], function(things, stuff, done){
t.fail('task ran but should not have');
done();
});
}, 'cannot define defaults twice');
});
test('multiple datas', function(t){
t.plan(3);
kgo
('foo', 'bar', function(done){
done(null, 1,2);
})
(['foo'], function(foo, done){
t.equal(foo, 1);
done();
})
(['bar'], function(bar, done){
t.equal(bar, 2);
done();
})
.on('complete', function(){
t.pass();
});
});
test('complete', function(t){
t.plan(3);
var a,b,c;
kgo
(function(done){
setTimeout(function(){
a = 1;
done();
},100);
})
(function(done){
setTimeout(function(){
b = 2;
done();
},100);
})
(function(done){
setTimeout(function(){
c = 3;
done();
},100);
})
.on('complete', function(){
t.equal(a,1);
t.equal(b,2);
t.equal(c,3);
});
});
test('error handler pass', function(t){
t.plan(2);
kgo
('result', function(done){
setTimeout(function(){
done(null, true);
}, 100);
})
(['*', 'result'], function(error, result){
t.notOk(error);
t.ok(result);
});
});
test('error handler fail', function(t){
t.plan(2);
kgo
('result', function(done){
setTimeout(function(){
done(true);
}, 100);
})
(['*', 'result'], function(error, result){
t.ok(error);
t.notOk(result);
});
});
test('error handler fail different step', function(t){
t.plan(4);
kgo
('initial', function(done){
setTimeout(function(){
done(null, true);
}, 100);
})
('result', ['initial'], function(initial, done){
setTimeout(function(){
done(true);
}, 100);
})
(['*', 'initial'], function(error, initial){
t.ok(initial);
t.notOk(error);
})
(['*', 'result'], function(error, result){
t.ok(error);
t.notOk(result);
});
});
test('error handler fail not passed successful results', function(t){
t.plan(3);
kgo
('initial', function(done){
setTimeout(function(){
done(null, true);
}, 100);
})
('result', ['initial'], function(initial, done){
setTimeout(function(){
done(true);
}, 100);
})
(['*', 'initial', 'result'], function(error, initial, result){
t.ok(error);
t.notOk(initial);
t.notOk(result);
});
});
test('multiple error handlers', function(t){
t.plan(2);
kgo
('result', function(done){
setTimeout(function(){
done(true);
}, 100);
})
(['*', 'result'], function(error, result){
t.ok(error, 'result handler got error');
})
(['*'], function(error){
t.ok(error, 'error only handler got error');
});
});
test('generic error handlers', function(t){
t.plan(1);
kgo
('initial', function(done){
setTimeout(function(){
done(null, true);
}, 100);
})
('result', ['initial'], function(initial, done){
setTimeout(function(){
done(null, initial);
}, 100);
})
(['result'], function(result){
t.ok(result);
})
(['*'], function(error){
t.fail();
});
});
test('complete style error handling', function(t){
t.plan(2);
kgo
('initial', function(done){
setTimeout(function(){
done(null, true);
}, 100);
})
('result', ['initial'], function(initial, done){
setTimeout(function(){
done(null, initial);
}, 100);
})
(['*', '!result'], function(error, shouldBeDoneFn){
t.notOk(error);
t.equal(typeof shouldBeDoneFn, 'function');
});
});
test('stupid dep list', function(t){
t.plan(1);
t.throws(
function(){
kgo
('foo', 'bar', function(done) {
done(null, 1, 2);
})
(['foo', ['bar']], function(){});
},
/dependency was not a string: bar in task: 0__returnless/
);
});
test('task with missing dependency', function(t){
t.plan(2);
var d = require('domain').create();
d.on('error', function(error){
t.ok(error instanceof Error, 'error is instance of Error');
t.equal(error.message, 'No task or result has been defined for dependency: foo');
});
d.run(function(){
kgo
(['foo'], function(){});
});
});
test('tasks with ! in dependency name', function(t){
t.plan(2);
kgo
('fo!o', function(done){
done(null, 'foo');
})
('ba!r', ['fo!o'], function(foo, done){
t.equal(foo, 'foo');
done(null, 'bar');
})
(['!fo!o', 'ba!r'], function(bar){
t.equal(bar, 'bar');
});
});
test('must have argmuents', function(t){
t.plan(2);
t.throws(
function(){
kgo();
},
/kgo must must be called with a task or defaults/
);
t.throws(
function(){
kgo({})();
},
/kgo must must be called with a task or defaults/
);
});
test('must have argmuents', function(t){
t.plan(1);
function someTask(done){
done(new Error('bang'));
}
kgo
('someTask', someTask)
(['*'], function(error){
t.notOk(~error.stack.indexOf('kgo'));
});
});

79
node_modules/simple-oauth-server/package.json generated vendored Normal file
View File

@@ -0,0 +1,79 @@
{
"_from": "simple-oauth-server@^1.0.6",
"_id": "simple-oauth-server@1.0.6",
"_inBundle": false,
"_integrity": "sha1-wpNSGXIFCGnN86clBdr4WBysP3E=",
"_location": "/simple-oauth-server",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "simple-oauth-server@^1.0.6",
"name": "simple-oauth-server",
"escapedName": "simple-oauth-server",
"rawSpec": "^1.0.6",
"saveSpec": null,
"fetchSpec": "^1.0.6"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/simple-oauth-server/-/simple-oauth-server-1.0.6.tgz",
"_shasum": "c293521972050869cdf3a72505daf8581cac3f71",
"_spec": "simple-oauth-server@^1.0.6",
"_where": "D:\\dev\\xmap\\cm-oauth",
"author": {
"name": "Maurice Butler",
"email": "maurice.butler@gmail.com"
},
"bugs": {
"url": "https://github.com/MauriceButler/simple-oauth-server/issues"
},
"bundleDependencies": false,
"dependencies": {
"kgo": "^2.2.1",
"mockery": "^1.4.0"
},
"deprecated": false,
"description": "A simple implementation of OAuth 2 providing async hooks to call to your own services",
"devDependencies": {
"husky": "^0.10.2",
"kgo": "^3.1.2",
"mockery": "^1.4.0",
"tape": "^4.2.2",
"timekeeper": "0.0.4"
},
"directories": {
"example": "example",
"test": "tests"
},
"homepage": "https://github.com/MauriceButler/simple-oauth-server",
"keywords": [
"simple",
"oauth",
"server",
"client",
"credentials",
"grant",
"oauth2",
"CCG",
"implict",
"authorization",
"code",
"passport",
"authom"
],
"license": "MIT",
"main": "./index.js",
"name": "simple-oauth-server",
"repository": {
"type": "git",
"url": "git+https://github.com/MauriceButler/simple-oauth-server.git"
},
"scripts": {
"prepush": "jshint . && npm test",
"test": "node ./tests"
},
"version": "1.0.6"
}

165
node_modules/simple-oauth-server/tests/index.js generated vendored Normal file
View File

@@ -0,0 +1,165 @@
var test = require('tape'),
mockery = require('mockery'),
timekeeper = require('timekeeper'),
pathToObjectUnderTest = '../',
testClientService = {},
testTokenService = {},
testAuthorizationService = {},
testMembershipService = {},
testExpiresIn = 123456,
testSupportedScopes = ['foo', 'bar', 'meh'];
mockery.registerAllowables([pathToObjectUnderTest]);
function resetMocks(){
mockery.registerMock('./lib', {
authorizeRequest: function(){},
getTokenData: function(){},
grantAccessToken: function(){},
validateAccessToken: function(){}
});
}
function getCleanTestObject(){
delete require.cache[require.resolve(pathToObjectUnderTest)];
mockery.enable({ useCleanCache: true, warnOnReplace: false });
var objectUnderTest = require(pathToObjectUnderTest);
mockery.disable();
resetMocks();
return objectUnderTest;
}
resetMocks();
test('AuthServer exists', function(t){
t.plan(1);
var AuthServer = getCleanTestObject();
t.equal(typeof AuthServer, 'function', 'AuthServer is a function');
});
test('AuthServer constructs correct object', function(t){
t.plan(7);
var AuthServer = getCleanTestObject(),
result = new AuthServer(
testClientService,
testTokenService,
testAuthorizationService,
testMembershipService,
testExpiresIn,
testSupportedScopes
);
t.equal(result.clientService, testClientService, 'got correct clientService');
t.equal(result.tokenService, testTokenService, 'got correct tokenService');
t.equal(result.authorizationService, testAuthorizationService, 'got correct authorizationService');
t.equal(result.membershipService, testMembershipService, 'got correct membershipService');
t.equal(result.expiresIn, testExpiresIn, 'got correct expiresIn');
t.equal(typeof result.isSupportedScope, 'function', 'isSupportedScope is a function');
t.equal(typeof result.getExpiresDate, 'function', 'isSupportedScope is a function');
});
test('AuthServer constructs correct object without new keyword', function(t){
t.plan(7);
var AuthServer = getCleanTestObject(),
result = AuthServer(
testClientService,
testTokenService,
testAuthorizationService,
testMembershipService,
testExpiresIn,
testSupportedScopes
);
t.equal(result.clientService, testClientService, 'got correct clientService');
t.equal(result.tokenService, testTokenService, 'got correct tokenService');
t.equal(result.authorizationService, testAuthorizationService, 'got correct authorizationService');
t.equal(result.membershipService, testMembershipService, 'got correct membershipService');
t.equal(result.expiresIn, testExpiresIn, 'got correct expiresIn');
t.equal(typeof result.isSupportedScope, 'function', 'isSupportedScope is a function');
t.equal(typeof result.getExpiresDate, 'function', 'isSupportedScope is a function');
});
test('AuthServer.isSupportedScope returns based on provided Supported Scopes', function(t){
t.plan(5);
var AuthServer = getCleanTestObject(),
withScopes = new AuthServer(
null,
null,
null,
null,
null,
testSupportedScopes
),
withoutScopes = new AuthServer();
t.equal(withScopes.isSupportedScope(), false, 'isSupportedScope returns false if undefined');
t.equal(withScopes.isSupportedScope([testSupportedScopes[0], 'majigger']), false, 'isSupportedScope returns false if atleast 1 is invalid');
t.equal(withScopes.isSupportedScope(testSupportedScopes), true, 'isSupportedScope returns true if valid');
t.equal(withScopes.isSupportedScope(testSupportedScopes[0]), true, 'isSupportedScope handels a string');
t.equal(withoutScopes.isSupportedScope(testSupportedScopes), false, 'isSupportedScope returns false if none provided');
});
test('AuthServer.getExpiresDate returns based on provided expiresIn value', function(t){
t.plan(4);
var AuthServer = getCleanTestObject(),
now = new Date(),
expectedWithExpires = now.getTime() + testExpiresIn * 60000,
expectedWithoutExpires = now.getTime() + 3600 * 60000,
withExpiresValue,
withoutExpiresValue;
timekeeper.freeze(now);
withExpiresValue = new AuthServer(null, null, null, null, testExpiresIn);
withoutExpiresValue = new AuthServer();
t.ok(withExpiresValue.getExpiresDate() instanceof Date, 'getExpiresDate returns a Date object when provided Expires');
t.equal(+withExpiresValue.getExpiresDate(), expectedWithExpires, 'getExpiresDate returns now + provided Expires');
t.ok(withoutExpiresValue.getExpiresDate() instanceof Date, 'getExpiresDate returns a Date object when not provided Expires');
t.equal(+withoutExpiresValue.getExpiresDate(), expectedWithoutExpires, 'getExpiresDate returns now + default Expires');
timekeeper.reset();
});
test('AuthServer.prototype.authorizeRequest exists', function(t){
t.plan(1);
var AuthServer = getCleanTestObject();
t.equal(typeof AuthServer.prototype.authorizeRequest, 'function', 'AuthServer.prototype.authorizeRequest is a function');
});
test('AuthServer.prototype.getTokenData exists', function(t){
t.plan(1);
var AuthServer = getCleanTestObject();
t.equal(typeof AuthServer.prototype.getTokenData, 'function', 'AuthServer.prototype.getTokenData is a function');
});
test('AuthServer.prototype.grantAccessToken exists', function(t){
t.plan(1);
var AuthServer = getCleanTestObject();
t.equal(typeof AuthServer.prototype.grantAccessToken, 'function', 'AuthServer.prototype.grantAccessToken is a function');
});
test('AuthServer.prototype.validateAccessToken exists', function(t){
t.plan(1);
var AuthServer = getCleanTestObject();
t.equal(typeof AuthServer.prototype.validateAccessToken, 'function', 'AuthServer.prototype.validateAccessToken is a function');
});
require('./lib');

View File

@@ -0,0 +1,569 @@
var test = require('tape'),
errors = require('../../lib/errors'),
url = require('url'),
testError = 'boom!!!',
pathToObjectUnderTest = '../../lib/authorizeRequest',
authorizeRequest = require(pathToObjectUnderTest);
function buildAuthorizationUri(context, expiresIn, code, token) {
var redirect = url.parse(context.redirect_uri, true);
delete redirect.search;
if (context.scope) {
redirect.query.scope = context.scope.join(',');
}
if (context.state) {
redirect.query.state = context.state;
}
if (expiresIn) {
redirect.query.expires_in = expiresIn;
}
if (code) {
redirect.query.code = code;
}
if (token) {
redirect.query.access_token = token;
redirect.query.token_type = 'Bearer';
}
return url.format(redirect);
}
test('authorizeRequest exists', function(t){
t.plan(2);
t.ok(authorizeRequest, 'authorizeRequest Exists');
t.equal(typeof authorizeRequest, 'function', 'authorizeRequest is a function');
});
test('authorizeRequest errors with no context', function(t){
t.plan(2);
var context = null,
accountId = null;
authorizeRequest(context, accountId, function(error){
t.ok(error, 'got error');
t.deepEqual(error, errors.invalidRequest(context), 'got correct error and data');
});
});
test('authorizeRequest errors with no context.response_type', function(t){
t.plan(2);
var context = {},
accountId = null;
authorizeRequest(context, accountId, function(error){
t.ok(error, 'got error');
t.deepEqual(error, errors.invalidRequest(context), 'got correct error and data');
});
});
test('authorizeRequest errors with invalid context.response_type', function(t){
t.plan(2);
var context = {
response_type: 'foo'
},
accountId = null;
authorizeRequest(context, accountId, function(error){
t.ok(error, 'got error');
t.deepEqual(error, errors.unsupportedResponseType(context), 'got correct error and data');
});
});
test('authorizeRequest continues with valid context.response_type', function(t){
t.plan(4);
var context = {
response_type: 'token'
},
accountId = null,
authServer = {
isSupportedScope: function(){
return false;
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'got error');
t.notDeepEqual(error, errors.unsupportedResponseType(context), 'got correct error and data');
});
context.response_type = 'code';
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'got error');
t.notDeepEqual(error, errors.unsupportedResponseType(context), 'got correct error and data');
});
});
test('authorizeRequest errors with invalid context.scope', function(t){
t.plan(3);
var context = {
response_type: 'token',
scope: 'foo'
},
accountId = null,
authServer = {
isSupportedScope: function(scope){
t.equal(scope, context.scope, 'got correct scope');
return false;
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'got error');
t.deepEqual(error, errors.invalidScope(context), 'got correct error and data');
});
});
test('authorizeRequest handels getByIdErrors', function(t){
t.plan(3);
var context = {
response_type: 'token',
client_id: 123
},
accountId = null,
authServer = {
isSupportedScope: function(){
return true;
},
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(testError);
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'got error');
t.equal(error, testError, 'got correct error and data');
});
});
test('authorizeRequestWithClient requires client', function(t){
t.plan(2);
var context = {
response_type: 'token',
client_id: 123
},
accountId = null,
authServer = {
isSupportedScope: function(){
return true;
},
clientService: {
getById: function(clientId, callback){
callback();
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'got error');
t.deepEqual(error, errors.invalidClient(context), 'got correct error and data');
});
});
test('authorizeRequestWithClient requires context.redirect_uri', function(t){
t.plan(2);
var context = {
response_type: 'token',
client_id: 123
},
accountId = null,
testClient = {},
authServer = {
isSupportedScope: function(){
return true;
},
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'got error');
t.deepEqual(error, errors.redirectUriMismatch(context), 'got correct error and data');
});
});
test('authorizeRequestWithClient errors on redirect_uri mismatch', function(t){
t.plan(4);
var context = {
response_type: 'token',
redirect_uri: 'foo'
},
accountId = null,
testClient = {},
authServer = {
isSupportedScope: function(){
return true;
},
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
},
isValidRedirectUri: function(client, redirectUri){
t.equal(client, testClient, 'got correct client');
t.equal(redirectUri, context.redirect_uri, 'got correct redirect_uri');
return false;
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'got error');
t.deepEqual(error, errors.redirectUriMismatch(context), 'got correct error and data');
});
});
test('authorizeRequestWithClient generate code if response_type is code', function(t){
t.plan(6);
var now = new Date(),
context = {
response_type: 'code',
redirect_uri: 'http://foo.com/?things=stuff',
scope: ['things', 'stuff'],
state: 'foo'
},
accountId = 123,
testClient = {
id: 789
},
generatedCode = 'generated code',
expectedCodeData = {
code: generatedCode,
redirectUri: context.redirect_uri,
clientId: testClient.id,
expiresDate: now,
accountId: accountId
},
authServer = {
isSupportedScope: function(){
return true;
},
getExpiresDate: function(){
return now;
},
expiresIn: 1234,
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
},
isValidRedirectUri: function(client, redirectUri){
t.equal(client, testClient, 'got correct client');
t.equal(redirectUri, context.redirect_uri, 'got correct redirect_uri');
return true;
}
},
tokenService: {
generateAuthorizationCode: function(callback){
t.pass('generated code');
callback(null, generatedCode);
}
},
authorizationService: {
saveAuthorizationCode: function(codeData, callback){
t.deepEqual(codeData, expectedCodeData, 'created code with correct data');
callback(null, expectedCodeData);
}
}
},
expectedResult = {
redirectUri: buildAuthorizationUri(context, authServer.expiresIn, expectedCodeData.code),
state: context
};
authorizeRequest.call(authServer, context, accountId, function(error, result){
t.notOk(error, 'no error');
t.deepEqual(result, expectedResult, 'got correct result');
});
});
test('authorizeRequestWithClient generate code handels save code error', function(t){
t.plan(2);
var now = new Date(),
context = {
response_type: 'code',
redirect_uri: 'http://foo.com/?things=stuff'
},
accountId = 123,
testClient = {
id: 789
},
generatedCode = 'generated code',
authServer = {
isSupportedScope: function(){
return true;
},
getExpiresDate: function(){
return now;
},
expiresIn: 1234,
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
},
isValidRedirectUri: function(){
return true;
}
},
tokenService: {
generateAuthorizationCode: function(callback){
callback(null, generatedCode);
}
},
authorizationService: {
saveAuthorizationCode: function(codeData, callback){
callback(testError);
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'no error');
t.equal(error, testError, 'got correct error');
});
});
test('authorizeRequestWithClient generate code handels generate code error', function(t){
t.plan(2);
var now = new Date(),
context = {
response_type: 'code',
redirect_uri: 'http://foo.com/?things=stuff'
},
accountId = 123,
testClient = {
id: 789
},
authServer = {
isSupportedScope: function(){
return true;
},
getExpiresDate: function(){
return now;
},
expiresIn: 1234,
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
},
isValidRedirectUri: function(){
return true;
}
},
tokenService: {
generateAuthorizationCode: function(callback){
callback(testError);
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'no error');
t.equal(error, testError, 'got correct error');
});
});
test('authorizeRequestWithClient generate code handels get client error', function(t){
t.plan(2);
var now = new Date(),
context = {
response_type: 'code',
redirect_uri: 'http://foo.com/?things=stuff'
},
accountId = 123,
authServer = {
isSupportedScope: function(){
return true;
},
getExpiresDate: function(){
return now;
},
expiresIn: 1234,
clientService: {
getById: function(clientId, callback){
callback(testError);
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'no error');
t.equal(error, testError, 'got correct error');
});
});
test('authorizeRequestWithClient generate token if response_type is token', function(t){
t.plan(6);
var now = new Date(),
context = {
response_type: 'token',
redirect_uri: 'http://foo.com/?things=stuff',
scope: ['things', 'stuff'],
state: 'foo'
},
accountId = 123,
testClient = {
id: 789
},
generatedToken = 'generated token',
expectedTokenData = {
clientId: testClient.id,
access_token: generatedToken,
expires_in: now,
accountId: accountId,
token_type: 'Bearer'
},
authServer = {
isSupportedScope: function(){
return true;
},
getExpiresDate: function(){
return now;
},
expiresIn: 1234,
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
},
isValidRedirectUri: function(client, redirectUri){
t.equal(client, testClient, 'got correct client');
t.equal(redirectUri, context.redirect_uri, 'got correct redirect_uri');
return true;
}
},
tokenService: {
generateToken: function(callback){
t.pass('generated token');
callback(null, generatedToken);
}
},
authorizationService: {
saveAccessToken: function(tokenData, callback){
t.deepEqual(tokenData, expectedTokenData, 'created token with correct data');
callback(null, expectedTokenData);
}
}
},
expectedResult = {
redirectUri: buildAuthorizationUri(context, authServer.expiresIn, undefined, expectedTokenData.access_token),
state: context
};
authorizeRequest.call(authServer, context, accountId, function(error, result){
t.notOk(error, 'no error');
t.deepEqual(result, expectedResult, 'got correct result');
});
});
test('authorizeRequestWithClient generate token handels save token error', function(t){
t.plan(2);
var now = new Date(),
context = {
response_type: 'token',
redirect_uri: 'http://foo.com/?things=stuff'
},
accountId = 123,
testClient = {
id: 789
},
generatedToken = 'generated token',
authServer = {
isSupportedScope: function(){
return true;
},
getExpiresDate: function(){
return now;
},
expiresIn: 1234,
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
},
isValidRedirectUri: function(){
return true;
}
},
tokenService: {
generateToken: function(callback){
callback(null, generatedToken);
}
},
authorizationService: {
saveAccessToken: function(tokenData, callback){
callback(testError);
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'no error');
t.equal(error, testError, 'got correct error');
});
});
test('authorizeRequestWithClient generate token handels generate token error', function(t){
t.plan(2);
var now = new Date(),
context = {
response_type: 'token',
redirect_uri: 'http://foo.com/?things=stuff'
},
accountId = 123,
testClient = {
id: 789
},
authServer = {
isSupportedScope: function(){
return true;
},
getExpiresDate: function(){
return now;
},
expiresIn: 1234,
clientService: {
getById: function(clientId, callback){
callback(null, testClient);
},
isValidRedirectUri: function(){
return true;
}
},
tokenService: {
generateToken: function(callback){
callback(testError);
}
}
};
authorizeRequest.call(authServer, context, accountId, function(error){
t.ok(error, 'no error');
t.equal(error, testError, 'got correct error');
});
});

52
node_modules/simple-oauth-server/tests/lib/errors.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
var test = require('tape'),
pathToObjectUnderTest = '../../lib/errors',
errors = require(pathToObjectUnderTest),
testState = { foo: 'bar'},
excpectedErrorData = {
invalidRequest: {error:'invalid_request', error_description: 'The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.'},
unauthorizedClient: {error:'unauthorized_client', error_description: 'The client is not authorized to request an authorization code using this method.'},
accessDenied: {error:'access_denied', error_description: 'The resource owner or authorization server denied the request.'},
unsupportedResponseType: {error:'unsupported_response_type', error_description: 'The authorization server does not support obtaining an authorization code using this method.'},
redirectUriMismatch: {error:'invalid_request', error_description: 'The redirect URI doesn\'t match what is stored for this client'},
invalidScope: {error:'invalid_scope', error_description: 'The requested scope is invalid, unknown, or malformed.'},
invalidResponseType: {error:'unsupported_response_type', error_description: 'The authorization server does not support this response type.'},
clientCredentialsInvalid: {error:'unauthorized_client', error_description: 'The client credentials are invalid.'},
userCredentialsInvalid: {error:'access_denied', error_description: 'The user credentials are invalid.'},
unsupportedGrantType: {error:'unsupported_grant_type', error_description: 'The authorization grant type is not supported by the authorization server.'},
unsupportedGrantTypeForClient: {error:'unauthorized_client', error_description: 'The grant type is not supported for this client.'},
invalidAuthorizationCode: {error:'invalid_grant', error_description: 'The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'},
invalidClient: {error:'invalid_client', error_description: 'Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).'}
};
function testErrorMethod(expecedError, method){
test('errors.' + method + ' exists and returns correct details', function(t){
t.plan(4);
t.equal(typeof errors[method], 'function', 'errors.' + method + ' is a function');
var result = errors[method](testState);
t.equal(result.state, testState, 'set correct state');
t.equal(result.error, expecedError.error, 'set correct error code');
t.equal(result.error_description, expecedError.error_description, 'set correct error_description');
});
}
test('errors exists', function(t){
t.plan(1);
t.equal(typeof errors, 'object', 'errors is an object');
});
test('errors methods exists and returns correct details', function(t){
for(var key in excpectedErrorData){
testErrorMethod(excpectedErrorData[key], key);
}
t.plan(1);
t.deepEqual(Object.keys(errors), Object.keys(excpectedErrorData), 'all errors accounted for');
});

View File

@@ -0,0 +1,176 @@
var test = require('tape'),
pathToObjectUnderTest = '../../lib/getOauthParameters',
getOauthParameters = require(pathToObjectUnderTest);
test('getOauthParameters exists and returns a function', function(t){
t.plan(4);
t.ok(getOauthParameters, 'getOauthParameters Exists');
t.equal(typeof getOauthParameters, 'function', 'getOauthParameters is a function');
var resultingFunction = getOauthParameters();
t.ok(resultingFunction, 'resultingFunction Exists');
t.equal(typeof resultingFunction, 'function', 'resultingFunction is a function');
});
test('getOauthParameters gets all context data from request and query string', function(t){
t.plan(3);
var authServer = {},
endEvent,
fakeRequest = {
url: '/?meh=majigger&scope=qwe,asd',
headers: {
authorization: 'bearer 123456'
},
readable: true,
on: function(event, callback){
if(event === 'data'){
setTimeout(function(){
callback('foo=bar');
callback('&stuff=thing');
callback('&meh=ishouldntbehere');
endEvent();
}, 0);
}
if(event === 'end'){
endEvent = callback;
}
}
},
expectedContext = {
foo: 'bar',
stuff: 'thing',
meh: 'majigger',
access_token: '123456',
scope: [
'qwe',
'asd'
]
},
scopedVersion = getOauthParameters.bind(authServer, function(){
t.deepEqual(arguments[0], expectedContext, 'got correct context');
t.equal(arguments[1], 'foo', 'arguments[1] correct');
t.equal(arguments[2], 'bar', 'arguments[2] correct');
}),
resultingFunction = scopedVersion();
resultingFunction(fakeRequest, 'foo', 'bar');
});
test('getOauthParameters handels no data from request', function(t){
t.plan(3);
var authServer = {},
fakeRequest = {
url: '/?meh=majigger&scope=qwe,asd',
headers: {
authorization: 'bearer 123456'
},
readable: true,
on: function(event, callback){
if(event === 'end'){
callback();
}
}
},
expectedContext = {
meh: 'majigger',
access_token: '123456',
scope: [
'qwe',
'asd'
]
},
scopedVersion = getOauthParameters.bind(authServer, function(){
t.deepEqual(arguments[0], expectedContext, 'got correct context');
t.equal(arguments[1], 'foo', 'arguments[1] correct');
t.equal(arguments[2], 'bar', 'arguments[2] correct');
}),
resultingFunction = scopedVersion();
resultingFunction(fakeRequest, 'foo', 'bar');
});
test('getOauthParameters handels access_token in url', function(t){
t.plan(3);
var authServer = {},
fakeRequest = {
url: '/?meh=majigger&scope=qwe,asd&access_token=123456',
readable: false
},
expectedContext = {
meh: 'majigger',
access_token: '123456',
scope: [
'qwe',
'asd'
]
},
scopedVersion = getOauthParameters.bind(authServer, function(){
t.deepEqual(arguments[0], expectedContext, 'got correct context');
t.equal(arguments[1], 'foo', 'arguments[1] correct');
t.equal(arguments[2], 'bar', 'arguments[2] correct');
}),
resultingFunction = scopedVersion();
resultingFunction(fakeRequest, 'foo', 'bar');
});
test('getOauthParameters gets all context data from request and query string', function(t){
t.plan(1);
var authServer = {},
endEvent,
destroyed,
fakeRequest = {
url: '/?meh=majigger&scope=qwe,asd',
headers: {
authorization: 'bearer 123456'
},
readable: true,
on: function(event, callback){
if(destroyed){
return;
}
if(event === 'data'){
setTimeout(function(){
for (var i = 0; i < 1e6 + 2; i++) {
if(destroyed){
break;
}
callback('1');
}
endEvent();
}, 0);
}
if(event === 'end'){
endEvent = function(){
if(!destroyed){
callback();
}
};
}
},
connection: {
destroy: function() {
t.pass('connection destroyed');
destroyed = true;
}
}
},
scopedVersion = getOauthParameters.bind(authServer, function(){
t.fail('should have destroyed connection');
}),
resultingFunction = scopedVersion();
resultingFunction(fakeRequest);
});

View File

@@ -0,0 +1,476 @@
var test = require('tape'),
errors = require('../../lib/errors'),
grantTypes = require('../../lib/grantTypes'),
testError = 'boom!!!',
pathToObjectUnderTest = '../../lib/getTokenData';
test('getTokenData exists', function(t){
t.plan(2);
var getTokenData = require(pathToObjectUnderTest);
t.ok(getTokenData, 'getTokenData Exists');
t.equal(typeof getTokenData, 'function', 'getTokenData is a function');
});
test('getTokenData errors with invalid grantType', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
authServer = {
getExpiresDate: function(){}
},
context = {},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, errors.unsupportedGrantType(context), 'correct error and data');
});
});
test('getTokenData gets token with grant type AUTHORIZATIONCODE', function(t){
t.plan(3);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
testToken = '1234567890',
context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
code: 123,
client_id: 456
},
authorizationCode = {
code: context.code,
clientId: context.client_id,
accountId: 789,
expiresDate: new Date(now.getTime() + 9999999)
},
authServer = {
getExpiresDate: function(){
return now;
},
authorizationService: {
getAuthorizationCode: function(code, callback){
t.equal(code, context.code, 'correct code');
callback(null, authorizationCode);
}
},
tokenService: {
generateToken: function(callback){
callback(null, testToken);
}
}
},
expectedTokenData = {
token_type: 'Bearer',
expires_in: authServer.getExpiresDate(),
clientId: context.client_id,
accountId: authorizationCode.accountId,
access_token: testToken,
refresh_token: testToken
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error, tokenData){
t.notOk(error, 'no error');
t.deepEqual(tokenData, expectedTokenData, 'correct tokenData');
});
});
test('getTokenData handels generate token error with grant type AUTHORIZATIONCODE', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
doneOnce,
context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
code: 123,
client_id: 456
},
authorizationCode = {
code: context.code,
clientId: context.client_id,
accountId: 789,
expiresDate: new Date(now.getTime() + 9999999)
},
authServer = {
getExpiresDate: function(){
return now;
},
authorizationService: {
getAuthorizationCode: function(code, callback){
callback(null, authorizationCode);
}
},
tokenService: {
generateToken: function(callback){
if(!doneOnce){
doneOnce = true;
callback(testError);
}
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.equal(error, testError, 'correct error');
});
});
test('getTokenData isValidAuthorizationCode handels different client ids', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
code: 123,
client_id: 456
},
authorizationCode = {
code: context.code,
clientId: context.client_id + 'foo',
accountId: 789,
expiresDate: new Date(now.getTime() + 9999999)
},
authServer = {
getExpiresDate: function(){
return now;
},
authorizationService: {
getAuthorizationCode: function(code, callback){
callback(null, authorizationCode);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, errors.invalidAuthorizationCode(context), 'correct error and data');
});
});
test('getTokenData isValidAuthorizationCode handels expired date', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
code: 123,
client_id: 456
},
authorizationCode = {
code: context.code,
clientId: context.client_id,
accountId: 789,
expiresDate: now
},
authServer = {
getExpiresDate: function(){
return now;
},
authorizationService: {
getAuthorizationCode: function(code, callback){
callback(null, authorizationCode);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, errors.invalidAuthorizationCode(context), 'correct error and data');
});
});
test('getTokenData isValidAuthorizationCode handels differnet codes', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
code: 123,
client_id: 456
},
authorizationCode = {
code: context.code + 'foo',
clientId: context.client_id,
accountId: 789,
expiresDate: now
},
authServer = {
getExpiresDate: function(){
return now;
},
authorizationService: {
getAuthorizationCode: function(code, callback){
callback(null, authorizationCode);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, errors.invalidAuthorizationCode(context), 'correct error and data');
});
});
test('getTokenData isValidAuthorizationCode handels missing authorization', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
code: 123,
client_id: 456
},
authorizationCode = null,
authServer = {
getExpiresDate: function(){
return now;
},
authorizationService: {
getAuthorizationCode: function(code, callback){
callback(null, authorizationCode);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, errors.invalidAuthorizationCode(context), 'correct error and data');
});
});
test('getTokenData handels getAuthorizationCode error', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
code: 123,
client_id: 456
},
authServer = {
getExpiresDate: function(){
return now;
},
authorizationService: {
getAuthorizationCode: function(code, callback){
callback(testError);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, testError, 'correct error');
});
});
test('getTokenData gets token with grant type PASSWORD', function(t){
t.plan(5);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
testToken = '1234567890',
context = {
grant_type: grantTypes.PASSWORD,
username: 'foo',
password: 'bar',
scope: 'meh',
client_id: 456
},
authServer = {
getExpiresDate: function(){
return now;
},
membershipService: {
areUserCredentialsValid: function(username, password, scope, callback){
t.equal(username, context.username, 'correct username');
t.equal(password, context.password, 'correct password');
t.equal(scope, context.scope, 'correct scope');
callback(null, true);
}
},
tokenService: {
generateToken: function(callback){
callback(null, testToken);
}
}
},
expectedTokenData = {
token_type: 'Bearer',
expires_in: authServer.getExpiresDate(),
clientId: context.client_id,
access_token: testToken,
refresh_token: testToken
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error, tokenData){
t.notOk(error, 'no error');
t.deepEqual(tokenData, expectedTokenData, 'correct tokenData');
});
});
test('getTokenData with grant type PASSWORD handels generate token error', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
doneOnce,
context = {
grant_type: grantTypes.PASSWORD,
username: 'foo',
password: 'bar',
scope: 'meh',
client_id: 456
},
authServer = {
getExpiresDate: function(){
return now;
},
membershipService: {
areUserCredentialsValid: function(username, password, scope, callback){
callback(null, true);
}
},
tokenService: {
generateToken: function(callback){
if(!doneOnce){
doneOnce = true;
callback(testError);
}
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.equal(error, testError, 'correct error');
});
});
test('getTokenData with grant type PASSWORD handels invalid credentials', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.PASSWORD,
username: 'foo',
password: 'bar',
scope: 'meh',
client_id: 456
},
authServer = {
getExpiresDate: function(){
return now;
},
membershipService: {
areUserCredentialsValid: function(username, password, scope, callback){
callback(null, false);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, errors.userCredentialsInvalid(context), 'correct error and data');
});
});
test('getTokenData with grant type PASSWORD handels credential error', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.PASSWORD,
username: 'foo',
password: 'bar',
scope: 'meh',
client_id: 456
},
authServer = {
getExpiresDate: function(){
return now;
},
membershipService: {
areUserCredentialsValid: function(username, password, scope, callback){
callback(testError);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.deepEqual(error, testError, 'correct error');
});
});
test('getTokenData gets token with grant type CLIENTCREDENTIALS', function(t){
t.plan(2);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
testToken = '1234567890',
context = {
grant_type: grantTypes.CLIENTCREDENTIALS,
client_id: 456
},
authServer = {
getExpiresDate: function(){
return now;
},
tokenService: {
generateToken: function(callback){
callback(null, testToken);
}
}
},
expectedTokenData = {
token_type: 'Bearer',
expires_in: authServer.getExpiresDate(),
clientId: context.client_id,
access_token: testToken
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error, tokenData){
t.notOk(error, 'no error');
t.deepEqual(tokenData, expectedTokenData, 'correct tokenData');
});
});
test('getTokenData with grant type CLIENTCREDENTIALS handels generate token error', function(t){
t.plan(1);
var getTokenData = require(pathToObjectUnderTest),
now = new Date(),
context = {
grant_type: grantTypes.CLIENTCREDENTIALS,
client_id: 456
},
authServer = {
getExpiresDate: function(){
return now;
},
tokenService: {
generateToken: function(callback){
callback(testError);
}
}
},
boundFunction = getTokenData.bind(authServer);
boundFunction(context, function(error){
t.equal(error, testError, 'correct error');
});
});

View File

@@ -0,0 +1,466 @@
var test = require('tape'),
errors = require('../../lib/errors'),
grantTypes = require('../../lib/grantTypes'),
kgo = require('kgo'),
testError = 'boom!!!',
mockery = require('mockery'),
pathToObjectUnderTest = '../../lib/grantAccessToken';
mockery.registerAllowables([pathToObjectUnderTest, './errors', './grantTypes']);
function resetMocks(){
mockery.registerMock('kgo', kgo);
mockery.registerMock('./getTokenData', {});
}
function getCleanTestObject(){
delete require.cache[require.resolve(pathToObjectUnderTest)];
mockery.enable({ useCleanCache: true, warnOnReplace: false });
var objectUnderTest = require(pathToObjectUnderTest);
mockery.disable();
resetMocks();
return objectUnderTest;
}
resetMocks();
test('grantAccessToken exists', function(t){
t.plan(2);
var grantAccessToken = getCleanTestObject();
t.ok(grantAccessToken, 'grantAccessToken Exists');
t.equal(typeof grantAccessToken, 'function', 'grantAccessToken is a function');
});
test('grantAccessToken requires grant_type', function(t){
t.plan(1);
var context = {
grant_type: undefined
},
grantAccessToken = getCleanTestObject();
grantAccessToken(context, function(error){
t.deepEqual(error, errors.invalidRequest(context), 'correct error and data');
});
});
test('grantAccessToken IMPLICIT is an allowed grant_type', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.IMPLICIT
},
authServer = {
clientService: {
getById: function(){
t.pass('IMPLICIT grant type is allowed');
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(){
t.fail('should not have called back');
});
});
test('grantAccessToken AUTHORIZATIONCODE is not allowed grant_type if authorizationService not provided', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.AUTHORIZATIONCODE
},
authServer = {
authorizationService: null,
clientService: {
getById: function(){
t.fail('AUTHORIZATIONCODE grant type is allowed without authorizationService');
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.unsupportedGrantType(context), 'correct error and data');
});
});
test('grantAccessToken AUTHORIZATIONCODE is allowed grant_type if authorizationService provided', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.AUTHORIZATIONCODE
},
authServer = {
authorizationService: {},
clientService: {
getById: function(){
t.pass('AUTHORIZATIONCODE grant type is allowed with authorizationService');
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(){
t.fail('should not have called back');
});
});
test('grantAccessToken CLIENTCREDENTIALS is not allowed grant_type if clientService provided', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.CLIENTCREDENTIALS
},
authServer = {
clientService: null
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.unsupportedGrantType(context), 'correct error and data');
});
});
test('grantAccessToken CLIENTCREDENTIALS is allowed grant_type if clientService provided', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.CLIENTCREDENTIALS
},
authServer = {
clientService: {
getById: function(){
t.pass('CLIENTCREDENTIALS grant type is allowed with clientService');
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(){
t.fail('should not have called back');
});
});
test('grantAccessToken PASSWORD is not allowed grant_type if membershipService not provided', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.PASSWORD
},
authServer = {
membershipService: null,
clientService: {
getById: function(){
t.fail('PASSWORD grant type is allowed without membershipService');
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.unsupportedGrantType(context), 'correct error and data');
});
});
test('grantAccessToken PASSWORD is allowed grant_type if membershipService provided', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.PASSWORD
},
authServer = {
membershipService: {},
clientService: {
getById: function(){
t.pass('PASSWORD grant type is allowed with membershipService');
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(){
t.fail('should not have called back');
});
});
test('grantAccessToken handels get client by id error', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
client_id: 123
},
authServer = {
authorizationService: {},
clientService: {
getById: function(clientId, callback){
callback(testError);
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.equal(error, testError, 'correct error');
});
});
test('grantAccessToken handels invalid client', function(t){
t.plan(1);
var context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
client_id: 123
},
authServer = {
authorizationService: {},
clientService: {
getById: function(clientId, callback){
callback();
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.invalidClient(context), 'correct error and data');
});
});
test('grantAccessToken handels missing client grantTypes', function(t){
t.plan(2);
var context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
client_id: 123
},
client = {
grantTypes: null
},
authServer = {
authorizationService: {},
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(null, client);
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.unsupportedGrantTypeForClient(context), 'correct error and data');
});
});
test('grantAccessToken handels invalid client grantTypes', function(t){
t.plan(2);
var context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
client_id: 123
},
client = {
grantTypes: [grantTypes.PASSWORD]
},
authServer = {
authorizationService: {},
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(null, client);
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.unsupportedGrantTypeForClient(context), 'correct error and data');
});
});
test('grantAccessToken checks client secret if type AUTHORIZATIONCODE', function(t){
t.plan(2);
var context = {
grant_type: grantTypes.AUTHORIZATIONCODE,
client_id: 123,
client_secret: 'foo'
},
client = {
grantTypes: [grantTypes.AUTHORIZATIONCODE],
secret: 'bar'
},
authServer = {
authorizationService: {},
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(null, client);
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.clientCredentialsInvalid(context), 'correct error and data');
});
});
test('grantAccessToken checks client secret if type CLIENTCREDENTIALS', function(t){
t.plan(2);
var context = {
grant_type: grantTypes.CLIENTCREDENTIALS,
client_id: 123,
client_secret: 'foo'
},
client = {
grantTypes: [grantTypes.CLIENTCREDENTIALS],
secret: 'bar'
},
authServer = {
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(null, client);
}
}
},
grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, errors.clientCredentialsInvalid(context), 'correct error and data');
});
});
test('grantAccessToken handels get token data error', function(t){
t.plan(4);
var context = {
grant_type: grantTypes.CLIENTCREDENTIALS,
client_id: 123,
client_secret: 'foo'
},
client = {
grantTypes: [grantTypes.CLIENTCREDENTIALS],
secret: 'foo'
},
authServer = {
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(null, client);
}
}
};
mockery.registerMock('./getTokenData', function(subContext, callback){
t.equal(this, authServer, 'bound correctly');
t.equal(subContext, context, 'correct context');
callback(testError);
});
var grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, testError, 'correct error');
});
});
test('grantAccessToken handels save token data error', function(t){
t.plan(5);
var context = {
grant_type: grantTypes.CLIENTCREDENTIALS,
client_id: 123,
client_secret: 'foo'
},
client = {
grantTypes: [grantTypes.CLIENTCREDENTIALS],
secret: 'foo'
},
authServer = {
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(null, client);
}
},
authorizationService: {
saveAccessToken: function(data, callback){
t.equal(data, tokenData, 'correct tokenData');
callback(testError);
}
}
},
tokenData = {
accountId: 123,
clientId: 456
};
mockery.registerMock('./getTokenData', function(subContext, callback){
t.equal(this, authServer, 'bound correctly');
t.equal(subContext, context, 'correct context');
callback(null, tokenData);
});
var grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error){
t.deepEqual(error, testError, 'correct error');
});
});
test('grantAccessToken saves token data correctly', function(t){
t.plan(8);
var context = {
grant_type: grantTypes.CLIENTCREDENTIALS,
client_id: 123,
client_secret: 'foo'
},
client = {
grantTypes: [grantTypes.CLIENTCREDENTIALS],
secret: 'foo'
},
authServer = {
clientService: {
getById: function(clientId, callback){
t.equal(clientId, context.client_id, 'got correct clientId');
callback(null, client);
}
},
authorizationService: {
saveAccessToken: function(data, callback){
t.equal(data, tokenData, 'correct tokenData');
callback(null, tokenData);
}
}
},
tokenData = {
accountId: 123,
clientId: 456
};
mockery.registerMock('./getTokenData', function(subContext, callback){
t.equal(this, authServer, 'bound correctly');
t.equal(subContext, context, 'correct context');
callback(null, tokenData);
});
var grantAccessToken = getCleanTestObject().bind(authServer);
grantAccessToken(context, function(error, result){
t.notOk(error, 'no error');
t.equal(result, tokenData, 'correct result');
t.notOk(result.accountId, 'accountId was removed');
t.notOk(result.clientId, 'clientId was removed');
});
});

View File

@@ -0,0 +1,14 @@
var test = require('tape'),
pathToObjectUnderTest = '../../lib/grantTypes',
grantTypes = require(pathToObjectUnderTest);
test('grantTypes exists and has correct constants', function(t){
t.plan(5);
t.equal(typeof grantTypes, 'object', 'grantTypes is an object');
t.equal(grantTypes.PASSWORD, 'password', 'PASSWORD has correct value');
t.equal(grantTypes.IMPLICIT, 'implict', 'IMPLICIT has correct value');
t.equal(grantTypes.AUTHORIZATIONCODE, 'authorization_code', 'AUTHORIZATIONCODE has correct value');
t.equal(grantTypes.CLIENTCREDENTIALS, 'client_credentials', 'CLIENTCREDENTIALS has correct value');
});

69
node_modules/simple-oauth-server/tests/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,69 @@
var test = require('tape'),
mockery = require('mockery'),
pathToObjectUnderTest = '../../lib',
fakeAuthorizeRequest = function(){},
fakeGetTokenData = function(){},
fakeGrantAccessToken = function(){},
fakeValidateAccessToken = function(){};
mockery.registerAllowables([pathToObjectUnderTest]);
function resetMocks(){
mockery.registerMock('./getOauthParameters', function(){});
mockery.registerMock('./authorizeRequest', fakeAuthorizeRequest);
mockery.registerMock('./getTokenData', fakeGetTokenData);
mockery.registerMock('./grantAccessToken', fakeGrantAccessToken);
mockery.registerMock('./validateAccessToken', fakeValidateAccessToken);
}
function getCleanTestObject(){
delete require.cache[require.resolve(pathToObjectUnderTest)];
mockery.enable({ useCleanCache: true, warnOnReplace: false });
var objectUnderTest = require(pathToObjectUnderTest);
mockery.disable();
resetMocks();
return objectUnderTest;
}
resetMocks();
test('lib Exists', function (t) {
t.plan(2);
var lib = getCleanTestObject();
t.ok(lib, 'lib Exists');
t.equal(typeof lib, 'object', 'lib is an object');
});
test('lib loads all methods and wraps in getOauthParameters', function (t) {
t.plan(8);
var methods = [
fakeAuthorizeRequest,
fakeGetTokenData,
fakeGrantAccessToken,
fakeValidateAccessToken
],
count= 0;
mockery.registerMock('./getOauthParameters', function(method){
t.equal(method, methods[count], 'called getOauthParameters ' + (count + 1) + ' time(s)');
count++;
return method;
});
var lib = getCleanTestObject();
t.equal(lib.authorizeRequest, fakeAuthorizeRequest, 'lib exposes authorizeRequest');
t.equal(lib.getTokenData, fakeGetTokenData, 'lib exposes getTokenData');
t.equal(lib.grantAccessToken, fakeGrantAccessToken, 'lib exposes grantAccessToken');
t.equal(lib.validateAccessToken, fakeValidateAccessToken, 'lib exposes validateAccessToken');
});
require('./authorizeRequest');
require('./errors');
require('./getOauthParameters');
require('./getTokenData');
require('./grantAccessToken');
require('./grantTypes');
require('./validateAccessToken');

View File

@@ -0,0 +1,156 @@
var test = require('tape'),
pathToObjectUnderTest = '../../lib/validateAccessToken',
timekeeper = require('timekeeper'),
validateAccessToken = require(pathToObjectUnderTest);
test('validateAccessToken Exists', function (t) {
t.plan(2);
t.ok(validateAccessToken, 'validateAccessToken Exists');
t.equal(typeof validateAccessToken, 'function', 'validateAccessToken is a function');
});
test('validateAccessToken gets token and calls back correct data', function (t) {
t.plan(5);
var now = new Date(),
testContext = {
access_token: 123,
client_id: 456
},
testTokenData = {
access_token: 123,
clientId: 456,
accountId: 789,
expiresDate: new Date(now.getTime() + 9999999)
},
testAuthServer = {
authorizationService: {
getAccessToken: function(token, callback){
t.equal(token, testContext.access_token, 'got correct token');
callback(null, testTokenData);
}
}
};
timekeeper.freeze(now);
validateAccessToken.call(testAuthServer, testContext, function(error, result){
t.notOk(error, 'no error');
t.ok(result.isValid, 'isValid');
t.equal(result.accountId, testTokenData.accountId, 'got correct accountId');
t.equal(result.clientId, testTokenData.clientId, 'got correct clientId');
});
timekeeper.reset();
});
test('validateAccessToken returns error if no token data', function (t) {
t.plan(2);
var testContext = {},
testTokenData = null,
expectedError = {
isValid: false,
error: 'Access token not found'
},
testAuthServer = {
authorizationService: {
getAccessToken: function(token, callback){
callback(null, testTokenData);
}
}
};
validateAccessToken.call(testAuthServer, testContext, function(error, result){
t.deepEqual(error, expectedError, 'got correct error details');
t.notOk(result, 'no result');
});
});
test('validateAccessToken returns error if no access_token', function (t) {
t.plan(2);
var testContext = {},
testTokenData = {
access_token: null
},
expectedError = {
isValid: false,
error: 'Access token not found'
},
testAuthServer = {
authorizationService: {
getAccessToken: function(token, callback){
callback(null, testTokenData);
}
}
};
validateAccessToken.call(testAuthServer, testContext, function(error, result){
t.deepEqual(error, expectedError, 'got correct error details');
t.notOk(result, 'no result');
});
});
test('validateAccessToken returns error if clientIds dont match', function (t) {
t.plan(2);
var testContext = {
client_id: 999
},
testTokenData = {
access_token: 123,
clientId: 456,
},
expectedError = {
isValid: false,
error: 'Access token not found'
},
testAuthServer = {
authorizationService: {
getAccessToken: function(token, callback){
callback(null, testTokenData);
}
}
};
validateAccessToken.call(testAuthServer, testContext, function(error, result){
t.deepEqual(error, expectedError, 'got correct error details');
t.notOk(result, 'no result');
});
});
test('validateAccessToken returns error if expired', function (t) {
t.plan(2);
var now = new Date(),
testContext = {
client_id: 456
},
testTokenData = {
access_token: 123,
clientId: 456,
expiresDate: now
},
expectedError = {
isValid: false,
error: 'Access token has expired'
},
testAuthServer = {
authorizationService: {
getAccessToken: function(token, callback){
callback(null, testTokenData);
}
}
};
timekeeper.freeze(new Date(now.getTime() + 9999999));
validateAccessToken.call(testAuthServer, testContext, function(error, result){
t.deepEqual(error, expectedError, 'got correct error details');
t.notOk(result, 'no result');
});
timekeeper.reset();
});