account-handling logic

This commit is contained in:
AJ ONeal 2017-05-31 20:02:26 +00:00
parent 34ed7bfd93
commit c411c34016
1 changed files with 113 additions and 7 deletions

View File

@ -8,6 +8,9 @@ module.exports.create = function (xconfx, apiFactories, apiDeps) {
var fs = PromiseA.promisifyAll(require('fs')); var fs = PromiseA.promisifyAll(require('fs'));
var path = require('path'); var path = require('path');
var localCache = { rests: {}, pkgs: {} }; var localCache = { rests: {}, pkgs: {} };
var promisableRequest = require('./common').promisableRequest;
var rejectableRequest = require('./common').rejectableRequest;
var crypto = require('crypto');
// TODO xconfx.apispath // TODO xconfx.apispath
xconfx.restPath = path.join(__dirname, '..', '..', 'packages', 'rest'); xconfx.restPath = path.join(__dirname, '..', '..', 'packages', 'rest');
@ -103,6 +106,107 @@ module.exports.create = function (xconfx, apiFactories, apiDeps) {
}); });
} }
function accountRequiredById(req, res, next) {
var promise = req.oauth3.verifyAsync().then(function (/*result*/) {
var tok = req.oauth3.token;
var accountId = req.params.accountId || '__NO_ID_GIVEN__';
var ppid;
if (tok.sub && tok.sub.split(/,/g).filter(function (ppid) {
return ppid === accountId;
}).length) {
ppid = accountId;
}
if (tok.axs && tok.axs.filter(function (acc) {
return acc.id === accountId || acc.appScopedId === accountId;
}).length) {
ppid = accountId;
}
if (tok.acx && accountId === (tok.acx.appScopedId || tok.acx.id || tok.acx)) {
ppid = accountId;
}
if (!ppid) {
return PromiseA.reject(new Error("missing accountId '" + accountId + "' in access token"));
}
return req.oauth3.rescope(ppid).then(function (accountIdx) {
req.oauth3.accountIdx = accountIdx;
req.oauth3.ppid = ppid;
req.oauth3.accountHash = crypto.createHash('sha1').update(accountIdx).digest('hex');
next();
});
});
rejectableRequest(req, res, promise, "[com.daplie.walnut] attach account by id");
}
function accountRequired(req, res, next) {
// if this already has auth, great
if (req.oauth3.ppid) {
next();
return;
}
// being public does not disallow authentication
if (req.isPublic && !req.oauth3.encodedToken) {
next();
return;
}
if (!req.oauth3.encodedToken) {
rejectableRequest(
req
, res
, PromiseA.reject(new Error("this secure resource requires an access token"))
, "[com.daplie.walnut] required account (not /public)"
);
return;
}
// verify the auth if it's here
var promise = req.oauth3.verifyAsync().then(function (/*result*/) {
var tok = req.oauth3.token;
var ppid;
var err;
if (tok.sub) {
if (tok.sub.split(/,/g).length > 1) {
err = new Error("more than one 'sub' specified in token");
return PromiseA.reject(err);
}
ppid = tok.sub;
}
else if (tok.axs && tok.axs.length) {
if (tok.axs.length > 1) {
err = new Error("more than one 'axs' specified in token (also, update to using 'sub' instead)");
return PromiseA.reject(err);
}
ppid = tok.axs[0].appScopedId || tok.axs[0].id;
}
else if (tok.acx) {
ppid = tok.acx.appScopedId || tok.acx.id || tok.acx;
}
if (!ppid) {
return PromiseA.reject(new Error("could not determine accountId from access token"));
}
return req.oauth3.rescope(ppid).then(function (accountIdx) {
req.oauth3.accountIdx = accountIdx;
req.oauth3.ppid = ppid;
req.oauth3.accountHash = crypto.createHash('sha1').update(accountIdx).digest('hex');
next();
});
});
rejectableRequest(req, res, promise, "[com.daplie.walnut] required account (not /public)");
}
function loadRestHelper(myConf, clientUrih, pkgId) { function loadRestHelper(myConf, clientUrih, pkgId) {
var pkgPath = path.join(myConf.restPath, pkgId); var pkgPath = path.join(myConf.restPath, pkgId);
var pkgLinks = []; var pkgLinks = [];
@ -151,8 +255,8 @@ module.exports.create = function (xconfx, apiFactories, apiDeps) {
console.log('DEBUG pkgPath', pkgPath); console.log('DEBUG pkgPath', pkgPath);
myApp = express(); myApp = express();
myApp.handlePromise = require('./common').promisableRequest; myApp.handlePromise = promisableRequest;
myApp.handleRejection = require('./common').rejectableRequest; myApp.handleRejection = rejectableRequest;
myApp.grantsRequired = function (grants) { myApp.grantsRequired = function (grants) {
if (!Array.isArray(grants)) { if (!Array.isArray(grants)) {
throw new Error("Usage: app.grantsRequired([ 'name|altname|altname2', 'othergrant' ])"); throw new Error("Usage: app.grantsRequired([ 'name|altname|altname2', 'othergrant' ])");
@ -198,11 +302,6 @@ module.exports.create = function (xconfx, apiFactories, apiDeps) {
//require('oauthcommon').inject(packagedApi._getOauth3Controllers, packagedApi._api, pkgConf, pkgDeps); //require('oauthcommon').inject(packagedApi._getOauth3Controllers, packagedApi._api, pkgConf, pkgDeps);
require('oauthcommon').inject(_getOauth3Controllers, myApp/*, pkgConf, pkgDeps*/); require('oauthcommon').inject(_getOauth3Controllers, myApp/*, pkgConf, pkgDeps*/);
myApp.use('/public', function preHandler(req, res, next) {
// TODO authenticate or use guest user
next();
});
// TODO delete these caches when config changes // TODO delete these caches when config changes
var _stripe; var _stripe;
var _stripe_test; var _stripe_test;
@ -325,6 +424,13 @@ module.exports.create = function (xconfx, apiFactories, apiDeps) {
next(); next();
}); });
}); });
myApp.use('/public', function preHandler(req, res, next) {
// TODO authenticate or use guest user
req.isPublic = true;
next();
});
myApp.use('/accounts/:accountId', accountRequiredById);
myApp.use('/acl', accountRequired);
// //
// TODO handle /accounts/:accountId // TODO handle /accounts/:accountId