From 95a35547cf407a189e4cab9001d7129b0aa51320 Mon Sep 17 00:00:00 2001 From: mhelander Date: Thu, 31 Aug 2017 12:28:19 +0300 Subject: [PATCH] Refactored back with twist User.auth, added User.leave & test cases --- sea.js | 25 +++++++------ test/common.js | 98 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 92 insertions(+), 31 deletions(-) diff --git a/sea.js b/sea.js index face5334..067da9dc 100644 --- a/sea.js +++ b/sea.js @@ -44,7 +44,8 @@ var user = root._.user || (root._.user = root.chain()); // create a user context. user.create = User.create; // attach a factory method to it. user.auth = User.auth; // and a login method. - user.remember = User.remember; // and a credentials persisting method. + user.leave = User.leave; // and a logout method. + // TODO: definitely needed this: user.delete = User.delete; return user; // return the user! } @@ -120,9 +121,10 @@ if (cb){doCreate(cb, cb)} else {return new Promise(doCreate)} }; // now that we have created a user, we want to authenticate them! - User.auth = function(props, cb){ - var alias = props.alias, pass = props.pass, newpass = props.newpass; + User.auth = function(alias, pass, cb, opt){ + var opts = opt || (typeof cb !== 'function' && cb) || {}; var root = this.back(-1); + cb = typeof cb === 'function' && cb; var doAuth = function(resolve, reject){ // load all public keys associated with the username alias we want to log in with. root.get('alias/'+alias).get(function(at, ev){ @@ -168,10 +170,10 @@ // emit an auth event, useful for page redirects and stuff. Gun.on('auth', user._); } - if(newpass) { + if(opts.newpass) { // password update so encrypt private key using new pwd + salt var newsalt = Gun.text.random(64); - SEA.proof(newpass, newsalt).then(function(proof){ + SEA.proof(opts.newpass, newsalt).then(function(proof){ SEA.en(priv, proof).then(function(encVal){ return SEA.write(encVal, priv).then(function(sAuth){ return { pub: key, auth: sAuth }; @@ -211,13 +213,14 @@ }; if (cb){doAuth(cb, cb)} else {return new Promise(doAuth)} }; - // now that we have created a user, we want to authenticate them! - User.remember = function(props, cb){ - var doRemember = function(resolve, reject){ - Gun.log('User.remember is TODO: still'); - reject({ err: 'Not implemented.' }); + // now that we authenticated a user, we want to support logout too! + User.leave = function(cb){ + var root = this.back(-1); + var doLogout = function(resolve, reject){ + root._.user = root.chain(); + resolve({ok: 0}); } - if (cb){doRemember(cb, cb)} else {return new Promise(doRemember)} + if (cb){doLogout(cb, cb)} else {return new Promise(doLogout)} }; // After we have a GUN extension to make user registration/login easy, we then need to handle everything else. diff --git a/test/common.js b/test/common.js index 5e972897..4a246d4a 100644 --- a/test/common.js +++ b/test/common.js @@ -7843,7 +7843,7 @@ describe('Gun', function(){ var encKeys = ['ct', 'iv', 's']; ['callback', 'Promise'].forEach(function(type){ - describe(type, function(){ + describe(type+':', function(){ it('proof', function(done){ var check = function(proof){ expect(proof).to.not.be(undefined); @@ -8037,11 +8037,12 @@ describe('Gun', function(){ console.log('TODO: User! THIS IS AN EARLY ALPHA!!!'); var alias = 'dude'; var pass = 'my secret password'; - var user = Gun().user(); + var gun = Gun(); + var user = gun.user(); Gun.log.off = true; // Supress all console logging ['callback', 'Promise'].forEach(function(type){ - describe(type, function(){ + describe(type+':', function(){ describe('create', function(){ it('new', function(done){ var check = function(ack){ @@ -8086,12 +8087,11 @@ describe('Gun', function(){ expect(ack).to.not.have.key('err'); done(); }; - var props = {alias: alias+type, pass: pass}; // Gun.user.auth - authenticates existing user if(type === 'callback'){ - user.auth(props, check); + user.auth(alias+type, pass, check); } else { - user.auth(props).then(check).catch(done); + user.auth(alias+type, pass).then(check).catch(done); } }); @@ -8104,11 +8104,10 @@ describe('Gun', function(){ expect(ack.err).to.not.be(''); done(); }; - var props = {alias: alias+type, pass: pass+'not'}; if(type === 'callback'){ - user.auth(props, check); + user.auth(alias+type, pass+'not', check); } else { - user.auth(props).then(function(ack){ + user.auth(alias+type, pass+'not').then(function(ack){ done('Unexpected login success!'); }).catch(check); } @@ -8123,11 +8122,10 @@ describe('Gun', function(){ expect(ack.err).to.not.be(''); done(); }; - var props = {alias: alias+type+'not', pass: pass}; if(type === 'callback'){ - user.auth(props, check); + user.auth(alias+type+'not', pass, check); } else { - user.auth(props).then(function(ack){ + user.auth(alias+type+'not', pass).then(function(ack){ done('Unexpected login success!'); }).catch(check); } @@ -8140,12 +8138,12 @@ describe('Gun', function(){ expect(ack).to.not.have.key('err'); done(); }; - var props = {alias: alias+type, pass: pass, newpass: pass+' new'}; // Gun.user.auth - with newpass props sets new password if(type === 'callback'){ - user.auth(props, check); + user.auth(alias+type, pass, check, {newpass: pass+' new'}); } else { - user.auth(props).then(check).catch(done); + user.auth(alias+type, pass, {newpass: pass+' new'}).then(check) + .catch(done); } }); @@ -8160,19 +8158,79 @@ describe('Gun', function(){ }; var props = {alias: alias+type, pass: pass+'not', newpass: pass+' new'}; if(type === 'callback'){ - user.auth(props, check); + user.auth(alias+type, pass+'not', check, {newpass: pass+' new'}); } else { - user.auth(props).then(function(ack){ + user.auth(alias+type, pass+'not', {newpass: pass+' new'}) + .then(function(ack){ done('Unexpected password change success!'); }).catch(check); } }); + + it.skip('no recall no session storing'); }); - describe('remember', function(){ - it.skip('TBD', function(done){ - done(); + describe('leave', function(){ + it('valid session', function(done){ + var check = function(ack){ + expect(ack).to.not.be(undefined); + expect(ack).to.not.be(''); + expect(ack).to.not.have.key('err'); + expect(ack).to.have.key('ok'); + expect(gun.back(-1)._.user).to.not.have.keys(['sea', 'pub']); + done(); + }; + user.auth(alias+type, pass+' new').then(function(usr){ + expect(usr).to.not.be(undefined); + expect(usr).to.not.be(''); + expect(usr).to.not.have.key('err'); + expect(usr).to.have.key('put'); + // Gun.user.leave - performs logout for authenticated user + if(type === 'callback'){ + user.leave(check); + } else { + user.leave().then(check).catch(done); + } + }).catch(done); }); + + it('no session', function(done){ + var check = function(ack){ + expect(ack).to.not.be(undefined); + expect(ack).to.not.be(''); + expect(ack).to.not.have.key('err'); + expect(ack).to.have.key('ok'); + done(); + }; + user.leave().then(function(ack){ + expect(gun.back(-1)._.user).to.not.have.keys(['sea', 'pub']); + if(type === 'callback'){ + user.leave(check); + } else { + user.leave().then(check).catch(done); + } + }); + }); + }); + + describe('delete - TODO: how?', function(){ + it.skip('existing authenticated user'); + it.skip('unauthenticated user'); + }); + + describe('recall', function(){ + it.skip('with zero validity auth skips storing'); + it.skip('with validity auth stores session'); + it.skip('valid session'); + it.skip('expired session'); + it.skip('changed password'); + it.skip('no session'); + }); + + describe('alive', function(){ + it.skip('valid session'); + it.skip('expired session'); + it.skip('recall hook session manipulation'); }); }); });