From 1622d3cb375f4666247866175fee4c05065b7759 Mon Sep 17 00:00:00 2001 From: nelsonic Date: Sun, 15 Mar 2015 19:12:58 +0000 Subject: [PATCH] implements GET /timer/all to retrieve all timers for a person. https://github.com/ideaq/time/issues/78 --- README.md | 2 +- api/handlers/timer_find_all.js | 18 +++++ api/handlers/timer_start.js | 10 +-- api/lib/auth_jwt_sign.js | 8 +-- api/routes.js | 2 + api/server.js | 3 +- api/test/anonymous.js | 2 +- api/test/auth_basic.js | 2 +- api/test/logout.js | 2 +- api/test/register.js | 2 +- api/test/timer_find.js | 2 +- api/test/timer_find_all.js | 128 +++++++++++++++++++++++++++++++++ api/test/timer_start.js | 2 +- api/test/z_drop.js | 4 +- models/person.js | 12 ++-- app.js => web.js | 6 +- 16 files changed, 178 insertions(+), 27 deletions(-) create mode 100644 api/handlers/timer_find_all.js create mode 100644 api/test/timer_find_all.js rename app.js => web.js (90%) diff --git a/README.md b/README.md index 8cb93a17..35ad3fb9 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ > “*The **price** of anything is the **amount** of **life** you **exchange for it**.*” ~ Henry David Thoreau -Time (a *finite* amount) is one of the few things we *all* have in common. +Time (a *finite* amount it) is one of the few things we *all* have in common. Wether we like it or not, we each only have a ***fixed amount***. It is our most precious ***non-renewable*** 'resource'. We need a *much* better way of keeping track of how we spend it. diff --git a/api/handlers/timer_find_all.js b/api/handlers/timer_find_all.js new file mode 100644 index 00000000..e25fa5a6 --- /dev/null +++ b/api/handlers/timer_find_all.js @@ -0,0 +1,18 @@ +var ES = require('esta'); + +module.exports = function(req, reply) { + var query = { + "index": "time", + "type": "timer", + "field": "person", + "text": req.auth.credentials.person.toString() // using issuer as the person + }; + ES.SEARCH(query, function(res) { + if(res.hits.total > 0) { + return reply(res); + } + else { + return reply(res).code(404); + } + }); +} diff --git a/api/handlers/timer_start.js b/api/handlers/timer_start.js index a334ca2f..10876c78 100644 --- a/api/handlers/timer_start.js +++ b/api/handlers/timer_start.js @@ -1,18 +1,18 @@ -var JWT = require('jsonwebtoken'); +// var JWT = require('jsonwebtoken'); var ES = require('esta'); -var perma = require('perma'); +var aguid = require('aguid'); var Hoek = require('hoek'); module.exports = function(req, reply) { // extract the person id from JWT - var decoded = JWT.verify(req.headers.authorization, process.env.JWT_SECRET); + var decoded = req.auth.credentials; //JWT.verify(req.headers.authorization, process.env.JWT_SECRET); var person = decoded.person; var created = new Date().toISOString(); - var id = perma(person+created); + var id = aguid(); var timer = { index: "time", type: "timer", - person: person, + person: decoded.person, session: decoded.jti, // session id from JWT ct: created, id: id diff --git a/api/lib/auth_jwt_sign.js b/api/lib/auth_jwt_sign.js index 956d412b..2d2ece1a 100644 --- a/api/lib/auth_jwt_sign.js +++ b/api/lib/auth_jwt_sign.js @@ -9,10 +9,10 @@ module.exports = function sign(request, callback) { var payload = { jti:aguid() }; // v4 random UUID used as Session ID below if (request.payload && request.payload.email) { - payload.iss = aguid(request.payload.email); + payload.person = aguid(request.payload.email); } // see: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#issDef else { // no email is set (means an anonymous person) - payload.iss = "anonymous"; + payload.person = "anonymous"; } // this will need to be extended for other auth: http://git.io/pc1c var token = JWT.sign(payload, process.env.JWT_SECRET); // http://git.io/xPBn @@ -21,9 +21,9 @@ module.exports = function sign(request, callback) { index: "time", type: "session", id : payload.jti, - person: payload.iss, + person: payload.person, ua: request.headers['user-agent'], - ct: new Date().toISOString() + created: new Date().toISOString() } ES.CREATE(session, function(esres) { diff --git a/api/routes.js b/api/routes.js index a4b62af4..ff2ba2d4 100644 --- a/api/routes.js +++ b/api/routes.js @@ -16,6 +16,8 @@ module.exports = [ config: { auth: 'jwt', handler: require('./handlers/logout.js') } }, { path: '/timer/{id}', method: 'GET', // Validate {id} to prevent injection? config: { auth: 'jwt', handler: require('./handlers/timer_find.js') } }, + { path: '/timer/all', method: 'GET', // Validate {id} to prevent injection? + config: { auth: 'jwt', handler: require('./handlers/timer_find_all.js') } }, { path: '/timer/new', method: 'POST', config: { validate: require('../models/timer'), auth: 'jwt', handler: require('./handlers/timer_start.js') diff --git a/api/server.js b/api/server.js index 2df9d52f..e854e00e 100644 --- a/api/server.js +++ b/api/server.js @@ -12,7 +12,8 @@ server.connection({ port: port }); var routes = require('./routes.js'); -server.register([ {register: Basic}, {register: AuthJWT}, { register: lout } ], function (err) { +server.register([ {register: Basic}, + {register: AuthJWT}, { register: lout } ], function (err) { server.auth.strategy('basic', 'basic', { validateFunc: require('./lib/auth_basic_validate.js') diff --git a/api/test/anonymous.js b/api/test/anonymous.js index b38e64f8..af5ff892 100644 --- a/api/test/anonymous.js +++ b/api/test/anonymous.js @@ -1,5 +1,5 @@ var test = require('tape'); -var server = require("../../app.js"); +var server = require("../../web.js"); var dir = __dirname.split('/')[__dirname.split('/').length-1]; var file = dir + __filename.replace(__dirname, '') + " -> "; diff --git a/api/test/auth_basic.js b/api/test/auth_basic.js index 2ee57a5d..87bf126f 100644 --- a/api/test/auth_basic.js +++ b/api/test/auth_basic.js @@ -1,5 +1,5 @@ var test = require('tape'); -var server = require("../../app.js"); +var server = require("../../web.js"); var dir = __dirname.split('/')[__dirname.split('/').length-1]; var file = dir + __filename.replace(__dirname, '') + " -> "; diff --git a/api/test/logout.js b/api/test/logout.js index 3b8124e0..6fa979f5 100644 --- a/api/test/logout.js +++ b/api/test/logout.js @@ -1,7 +1,7 @@ // Logout https://github.com/ideaq/time/issues/65 var ES = require('esta'); var test = require('tape'); -var server = require("../../app.js"); +var server = require("../../web.js"); var dir = __dirname.split('/')[__dirname.split('/').length-1]; var file = dir + __filename.replace(__dirname, '') + " -> "; var token; // used below diff --git a/api/test/register.js b/api/test/register.js index 4f02c35b..26607df2 100644 --- a/api/test/register.js +++ b/api/test/register.js @@ -1,5 +1,5 @@ var test = require('tape'); -var server = require("../../app.js"); +var server = require("../../web.js"); var dir = __dirname.split('/')[__dirname.split('/').length-1]; var file = dir + __filename.replace(__dirname, ''); diff --git a/api/test/timer_find.js b/api/test/timer_find.js index 545daa94..483b48c3 100644 --- a/api/test/timer_find.js +++ b/api/test/timer_find.js @@ -1,5 +1,5 @@ var test = require('tape'); -var server = require("../../app.js"); +var server = require("../../web.js"); var dir = __dirname.split('/')[__dirname.split('/').length-1]; var file = dir + __filename.replace(__dirname, '') + " -> "; diff --git a/api/test/timer_find_all.js b/api/test/timer_find_all.js new file mode 100644 index 00000000..b9865dac --- /dev/null +++ b/api/test/timer_find_all.js @@ -0,0 +1,128 @@ +var test = require('tape'); +var server = require("../../web.js"); +var dir = __dirname.split('/')[__dirname.split('/').length-1]; +var file = dir + __filename.replace(__dirname, '') + " -> "; +var token; +var records = 100; +var countdown = records; + +var drop = require('./z_drop'); +test(file+ "Teardown", function(t) { + drop(function(res){ + t.equal(res.acknowledged, true, file+"ALL Records DELETED!"); + t.end(); + }).end(); +}); + +function create(t, callback) { + var timer = { + "desc" : "My Amazing Timer #"+countdown, + "st" : new Date().toISOString() + } + var options = { + method: "POST", + url: "/timer/new", + payload: timer, + headers : { authorization : token } + }; + server.inject(options, function(res) { + countdown--; + // console.log(" >>> "+countdown + " res.created "+ T.created); + if(countdown === 0) { + var T = JSON.parse(res.payload); + t.equal(res.statusCode, 200, records+ " New timers started! " + T.st); + callback(res, t); + } + }); +} + +function finish(res, t){ + // console.log(res); + var T = JSON.parse(res.payload); + var tid = T._id; + var options = { + method: "GET", + url: "/timer/"+tid, + headers : { authorization : token } + }; + + server.inject(options, function(res) { + t.equal(res.statusCode, 200, "New timer retrieved!"+'\n'); + server.stop(); + t.end(); + }); +} + + + +// new anonymous person +test(file + "Register new person to create a few timers", function(t) { + var person = { + "email" : "multiple.timers@awesome.net", + "password" : "EveryThingisAwesome", + "firstname": "Jenny" + } + var options = { + method : "POST", + url : "/register", + payload : person + }; + server.inject(options, function(res) { + t.equal(res.statusCode, 200, "Session Created = "+res.result.created); + token = res.headers.authorization; + // can't create create functions inside a for loop so no anon callbacks! + for(var i = 0; i < records; i++) { + create(t, finish); + } // end for + }); +}); + +test(file + "GET /timer/all to list all timers", function(t) { + var options = { + method: "GET", + url: "/timer/all", + headers : { authorization : token } + }; + setTimeout(function(){ + server.inject(options, function(res) { + // console.log(res.result); + var T = JSON.parse(res.payload); + t.equal(res.statusCode, 200, "Find all records for this person"); + t.equal(T.hits.total, 100, "100 records found"); + server.stop(); + t.end(); + }); + },1000) +}); + +test(file + "GET /timer/all should fail for Timmy no timers", function(t) { + var person = { + "email" : "timmy.no.timers@awesome.net", + "password" : "EveryThingisAwesome", + "firstname": "Timmay!" + } + var options = { + method : "POST", + url : "/register", + payload : person + }; + server.inject(options, function(res) { + var newtoken = res.headers.authorization; + var options = { + method: "GET", + url: "/timer/all", + headers : { authorization : newtoken } + }; + setTimeout(function(){ + server.inject(options, function(res) { + console.log(res.result); + var T = JSON.parse(res.payload); + console.log(T); + t.equal(res.statusCode, 404, "Timmay! has no timers..."); + // t.equal(T.hits.total, 100, "100 records found"); + server.stop(); + t.end(); + }); + },1000) + }); +}); diff --git a/api/test/timer_start.js b/api/test/timer_start.js index 28c6e94c..a328a892 100644 --- a/api/test/timer_start.js +++ b/api/test/timer_start.js @@ -1,5 +1,5 @@ var test = require('tape'); -var server = require("../../app.js"); +var server = require("../../web.js"); var dir = __dirname.split('/')[__dirname.split('/').length-1]; var file = dir + __filename.replace(__dirname, '') + " -> "; var token; diff --git a/api/test/z_drop.js b/api/test/z_drop.js index fd55cfa4..584dd234 100644 --- a/api/test/z_drop.js +++ b/api/test/z_drop.js @@ -1,8 +1,8 @@ var http = require('http'); var options = { - host:"127.0.0.1", - port: 9200, // use ENV var? + host: process.env.ES_HOST, + port: process.env.ES_PORT, path: "/_all", // DELETEs EVERYTHING!! method: 'DELETE', headers: { 'Content-Type': 'application/json' } diff --git a/models/person.js b/models/person.js index 91a7525a..78086e94 100644 --- a/models/person.js +++ b/models/person.js @@ -1,11 +1,11 @@ var Joi = require('joi'); module.exports = { payload: { - person : Joi.string(), // unique id - email : Joi.string().email().required(), - password : Joi.string().required().min(4), - fn : Joi.string(), - ln : Joi.string(), - ct : Joi.forbidden() // don't allow people to set this! + person : Joi.string(), // unique id + email : Joi.string().email().required(), + password : Joi.string().required().min(4), + firstname : Joi.string(), + lastname : Joi.string(), + created : Joi.forbidden() // don't allow people to set this! } } diff --git a/app.js b/web.js similarity index 90% rename from app.js rename to web.js index 11b43bf9..b0b1fed3 100644 --- a/app.js +++ b/web.js @@ -25,7 +25,9 @@ server.register([ {register: Basic}, {register: AuthJWT} ], function (err) { }); -server.start(); -console.log('Now Visit: http://localhost:'+port); +server.start(function(){ + console.log('Now Visit: http://localhost:'+port); +}); + module.exports = server;