Refactored back with twist User.auth, added User.leave & test cases

This commit is contained in:
mhelander 2017-08-31 12:28:19 +03:00
parent 68f5725899
commit 95a35547cf
2 changed files with 92 additions and 31 deletions

25
sea.js
View File

@ -44,7 +44,8 @@
var user = root._.user || (root._.user = root.chain()); // create a user context. var user = root._.user || (root._.user = root.chain()); // create a user context.
user.create = User.create; // attach a factory method to it. user.create = User.create; // attach a factory method to it.
user.auth = User.auth; // and a login method. 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! return user; // return the user!
} }
@ -120,9 +121,10 @@
if (cb){doCreate(cb, cb)} else {return new Promise(doCreate)} if (cb){doCreate(cb, cb)} else {return new Promise(doCreate)}
}; };
// now that we have created a user, we want to authenticate them! // now that we have created a user, we want to authenticate them!
User.auth = function(props, cb){ User.auth = function(alias, pass, cb, opt){
var alias = props.alias, pass = props.pass, newpass = props.newpass; var opts = opt || (typeof cb !== 'function' && cb) || {};
var root = this.back(-1); var root = this.back(-1);
cb = typeof cb === 'function' && cb;
var doAuth = function(resolve, reject){ var doAuth = function(resolve, reject){
// load all public keys associated with the username alias we want to log in with. // load all public keys associated with the username alias we want to log in with.
root.get('alias/'+alias).get(function(at, ev){ root.get('alias/'+alias).get(function(at, ev){
@ -168,10 +170,10 @@
// emit an auth event, useful for page redirects and stuff. // emit an auth event, useful for page redirects and stuff.
Gun.on('auth', user._); Gun.on('auth', user._);
} }
if(newpass) { if(opts.newpass) {
// password update so encrypt private key using new pwd + salt // password update so encrypt private key using new pwd + salt
var newsalt = Gun.text.random(64); 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){ SEA.en(priv, proof).then(function(encVal){
return SEA.write(encVal, priv).then(function(sAuth){ return SEA.write(encVal, priv).then(function(sAuth){
return { pub: key, auth: sAuth }; return { pub: key, auth: sAuth };
@ -211,13 +213,14 @@
}; };
if (cb){doAuth(cb, cb)} else {return new Promise(doAuth)} if (cb){doAuth(cb, cb)} else {return new Promise(doAuth)}
}; };
// now that we have created a user, we want to authenticate them! // now that we authenticated a user, we want to support logout too!
User.remember = function(props, cb){ User.leave = function(cb){
var doRemember = function(resolve, reject){ var root = this.back(-1);
Gun.log('User.remember is TODO: still'); var doLogout = function(resolve, reject){
reject({ err: 'Not implemented.' }); 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. // After we have a GUN extension to make user registration/login easy, we then need to handle everything else.

View File

@ -7843,7 +7843,7 @@ describe('Gun', function(){
var encKeys = ['ct', 'iv', 's']; var encKeys = ['ct', 'iv', 's'];
['callback', 'Promise'].forEach(function(type){ ['callback', 'Promise'].forEach(function(type){
describe(type, function(){ describe(type+':', function(){
it('proof', function(done){ it('proof', function(done){
var check = function(proof){ var check = function(proof){
expect(proof).to.not.be(undefined); expect(proof).to.not.be(undefined);
@ -8037,11 +8037,12 @@ describe('Gun', function(){
console.log('TODO: User! THIS IS AN EARLY ALPHA!!!'); console.log('TODO: User! THIS IS AN EARLY ALPHA!!!');
var alias = 'dude'; var alias = 'dude';
var pass = 'my secret password'; var pass = 'my secret password';
var user = Gun().user(); var gun = Gun();
var user = gun.user();
Gun.log.off = true; // Supress all console logging Gun.log.off = true; // Supress all console logging
['callback', 'Promise'].forEach(function(type){ ['callback', 'Promise'].forEach(function(type){
describe(type, function(){ describe(type+':', function(){
describe('create', function(){ describe('create', function(){
it('new', function(done){ it('new', function(done){
var check = function(ack){ var check = function(ack){
@ -8086,12 +8087,11 @@ describe('Gun', function(){
expect(ack).to.not.have.key('err'); expect(ack).to.not.have.key('err');
done(); done();
}; };
var props = {alias: alias+type, pass: pass};
// Gun.user.auth - authenticates existing user // Gun.user.auth - authenticates existing user
if(type === 'callback'){ if(type === 'callback'){
user.auth(props, check); user.auth(alias+type, pass, check);
} else { } 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(''); expect(ack.err).to.not.be('');
done(); done();
}; };
var props = {alias: alias+type, pass: pass+'not'};
if(type === 'callback'){ if(type === 'callback'){
user.auth(props, check); user.auth(alias+type, pass+'not', check);
} else { } else {
user.auth(props).then(function(ack){ user.auth(alias+type, pass+'not').then(function(ack){
done('Unexpected login success!'); done('Unexpected login success!');
}).catch(check); }).catch(check);
} }
@ -8123,11 +8122,10 @@ describe('Gun', function(){
expect(ack.err).to.not.be(''); expect(ack.err).to.not.be('');
done(); done();
}; };
var props = {alias: alias+type+'not', pass: pass};
if(type === 'callback'){ if(type === 'callback'){
user.auth(props, check); user.auth(alias+type+'not', pass, check);
} else { } else {
user.auth(props).then(function(ack){ user.auth(alias+type+'not', pass).then(function(ack){
done('Unexpected login success!'); done('Unexpected login success!');
}).catch(check); }).catch(check);
} }
@ -8140,12 +8138,12 @@ describe('Gun', function(){
expect(ack).to.not.have.key('err'); expect(ack).to.not.have.key('err');
done(); done();
}; };
var props = {alias: alias+type, pass: pass, newpass: pass+' new'};
// Gun.user.auth - with newpass props sets new password // Gun.user.auth - with newpass props sets new password
if(type === 'callback'){ if(type === 'callback'){
user.auth(props, check); user.auth(alias+type, pass, check, {newpass: pass+' new'});
} else { } 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'}; var props = {alias: alias+type, pass: pass+'not', newpass: pass+' new'};
if(type === 'callback'){ if(type === 'callback'){
user.auth(props, check); user.auth(alias+type, pass+'not', check, {newpass: pass+' new'});
} else { } else {
user.auth(props).then(function(ack){ user.auth(alias+type, pass+'not', {newpass: pass+' new'})
.then(function(ack){
done('Unexpected password change success!'); done('Unexpected password change success!');
}).catch(check); }).catch(check);
} }
}); });
it.skip('no recall no session storing');
}); });
describe('remember', function(){ describe('leave', function(){
it.skip('TBD', function(done){ it('valid session', function(done){
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');
}); });
}); });
}); });