mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
Finished User.delete tests & fixed mysterious password update bug
This commit is contained in:
parent
41c0f9ed79
commit
bff2fdece9
93
sea.js
93
sea.js
@ -75,38 +75,52 @@
|
||||
function authenticate(alias,pass,root){
|
||||
return new Promise(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){
|
||||
ev.off();
|
||||
if(!at.put){
|
||||
root.get('alias/'+alias).get(function(rat, rev){
|
||||
rev.off();
|
||||
if(!rat.put){
|
||||
// if no user, don't do anything.
|
||||
var err = 'No user!';
|
||||
Gun.log(err);
|
||||
return reject({err: err});
|
||||
}
|
||||
// then attempt to log into each one until we find ours!
|
||||
// (if two users have the same username AND the same password... that would be bad)
|
||||
Gun.obj.map(at.put, function(val, key){
|
||||
// then figuring out all possible candidates having matching username
|
||||
var aliases = [];
|
||||
Gun.obj.map(rat.put, function(at, key){
|
||||
// grab the account associated with this public key.
|
||||
root.get(key).get(function(at, ev){
|
||||
if(!key.slice || 'pub/' !== key.slice(0,4)){return}
|
||||
key = key.slice(4);
|
||||
ev.off();
|
||||
if(!at.put){return} // reject({err: 'Public key does not exist!'})
|
||||
// attempt to PBKDF2 extend the password with the salt. (Verifying the signature gives us the plain text salt.)
|
||||
SEA.read(at.put.salt, key).then(function(salt){
|
||||
return SEA.proof(pass, salt);
|
||||
}).then(function(proof){
|
||||
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
||||
return SEA.read(at.put.auth, key).then(function(auth){
|
||||
return SEA.de(auth, proof);
|
||||
}).catch(function(){reject({err: 'Failed to decrypt private key!'})});
|
||||
if(!at.put){return}
|
||||
aliases.push({key: key, at: at});
|
||||
});
|
||||
});
|
||||
if (!aliases.length){return reject({err: 'Public key does not exist!'})}
|
||||
// then attempt to log into each one until we find ours!
|
||||
// (if two users have the same username AND the same password... that would be bad)
|
||||
aliases.forEach(function(one, index){
|
||||
var at = one.at, key = one.key;
|
||||
var remaining = (aliases.length - index) > 1;
|
||||
if(!at.put){
|
||||
return (!remaining) && reject({err: 'Public key does not exist!'})
|
||||
}
|
||||
// attempt to PBKDF2 extend the password with the salt. (Verifying the signature gives us the plain text salt.)
|
||||
SEA.read(at.put.salt, key).then(function(salt){
|
||||
return SEA.proof(pass, salt);
|
||||
}).then(function(proof){
|
||||
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
||||
return SEA.read(at.put.auth, key).then(function(auth){
|
||||
return SEA.de(auth, proof);
|
||||
}).catch(function(e){
|
||||
}).then(function(priv){
|
||||
// now we have AES decrypted the private key, from when we encrypted it with the proof at registration.
|
||||
// if we were successful, then that meanswe're logged in!
|
||||
return (priv && resolve({pub: key, priv: priv, at: at}))
|
||||
return remaining ? undefined // Not done yet
|
||||
: priv ? resolve({pub: key, priv: priv, at: at})
|
||||
// Or else we failed to log in...
|
||||
|| reject({err: 'Failed to decrypt private key!'});
|
||||
}).catch(function(){reject({err: 'Failed to create proof!'})});
|
||||
});
|
||||
: reject({err: 'Failed to decrypt private key!'});
|
||||
});
|
||||
}).catch(function(){reject({err: 'Failed to create proof!'})});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -189,19 +203,14 @@
|
||||
var newsalt = Gun.text.random(64);
|
||||
SEA.proof(opts.newpass, newsalt).then(function(proof){
|
||||
SEA.en(key.priv, proof).then(function(encVal){
|
||||
return SEA.write(encVal, key.priv).then(function(sAuth){
|
||||
return { pub: key.pub, auth: sAuth };
|
||||
});
|
||||
return {
|
||||
alias: alias,
|
||||
pub: key.pub,
|
||||
auth: encVal,
|
||||
salt: newsalt
|
||||
};
|
||||
}).then(function(user){
|
||||
return SEA.write(alias, key.priv).then(function(sAlias){
|
||||
user.alias = sAlias; return user;
|
||||
});
|
||||
}).then(function(user){
|
||||
return SEA.write(newsalt, key.priv).then(function(sSalt){
|
||||
user.salt = sSalt; return user;
|
||||
});
|
||||
}).then(function(user){
|
||||
var tmp = 'pub/'+key.pub;
|
||||
var tmp = 'pub/'+user.pub;
|
||||
// awesome, now we can update the user using public key ID.
|
||||
root.get(tmp).put(user);
|
||||
// then we're done
|
||||
@ -211,10 +220,9 @@
|
||||
} else {
|
||||
doLogin();
|
||||
}
|
||||
return;
|
||||
}).catch(function(e){
|
||||
Gun.log('Failed to sign in!');
|
||||
reject({err: 'Auth attempt failed'});
|
||||
reject({err: 'Auth attempt failed! Reason: '+(e && e.err) || e || ''});
|
||||
});
|
||||
};
|
||||
if (cb){doIt(cb, cb)} else {return new Promise(doIt)}
|
||||
@ -395,13 +403,11 @@
|
||||
// Does enc/dec key like OpenSSL - works with CryptoJS encryption/decryption
|
||||
function makeKey(p,s){
|
||||
var ps = Buffer.concat([new Buffer(p, 'utf8'), s]);
|
||||
var h128 = new Buffer(nodeCrypto.createHash('md5').update(ps).digest('hex'), 'hex');
|
||||
var h128 = nodeCrypto.createHash('md5').update(ps).digest();
|
||||
// TODO: 'md5' is insecure, do we need OpenSSL compatibility anymore ?
|
||||
return Buffer.concat([
|
||||
h128,
|
||||
new Buffer(nodeCrypto.createHash('md5').update(
|
||||
Buffer.concat([h128, ps]).toString('base64'), 'base64'
|
||||
).digest('hex'), 'hex')
|
||||
nodeCrypto.createHash('md5').update(Buffer.concat([h128, ps])).digest()
|
||||
]);
|
||||
}
|
||||
|
||||
@ -525,8 +531,13 @@
|
||||
};
|
||||
if(cb){doIt(cb, function(){cb()})} else {return new Promise(doIt)}
|
||||
};
|
||||
SEA.write = function(m,p,cb){
|
||||
SEA.write = function(mm,p,cb){
|
||||
var doIt = function(resolve, reject) {
|
||||
var m = mm;
|
||||
if(!m.slice || 'SEA[' !== m.slice(0,4)){m = mm}
|
||||
m = m.slice(3);
|
||||
try{m = JSON.parse(m);
|
||||
}catch(e){m = mm}
|
||||
SEA.sign(m, p).then(function(signature){
|
||||
resolve('SEA'+JSON.stringify([m,signature]));
|
||||
}).catch(function(e){Gun.log(e); reject(e)});
|
||||
@ -536,14 +547,12 @@
|
||||
SEA.read = function(m,p,cb){
|
||||
var doIt = function(resolve, reject) {
|
||||
if(!m){ return resolve(); }
|
||||
if(!m.slice || 'SEA[' !== m.slice(0,4)){ return resolve(m); }
|
||||
if(!m.slice || 'SEA[' !== m.slice(0,4)){return resolve(m)}
|
||||
m = m.slice(3);
|
||||
try{m = JSON.parse(m);
|
||||
}catch(e){ return reject(e); }
|
||||
m = m || '';
|
||||
SEA.verify(m[0], p, m[1]).then(function(ok){
|
||||
resolve(ok && m[0]);
|
||||
});
|
||||
SEA.verify(m[0], p, m[1]).then(function(ok){resolve(ok && m[0])});
|
||||
};
|
||||
if(cb){doIt(cb, function(){cb()})} else {return new Promise(doIt)}
|
||||
};
|
||||
|
132
test/common.js
132
test/common.js
@ -19,8 +19,8 @@ var root;
|
||||
//Gun.log.squelch = true;
|
||||
var gleak = {globals: {}, check: function(){ // via tobyho
|
||||
var leaked = []
|
||||
for (var key in gleak.globe){ if (!(key in gleak.globals)){ leaked.push(key)} }
|
||||
if (leaked.length > 0){ console.log("GLOBAL LEAK!", leaked); return leaked }
|
||||
for (var key in gleak.globe){ if(!(key in gleak.globals)){ leaked.push(key)} }
|
||||
if(leaked.length > 0){ console.log("GLOBAL LEAK!", leaked); return leaked }
|
||||
}};
|
||||
(function(env){
|
||||
for (var key in (gleak.globe = env)){ gleak.globals[key] = true }
|
||||
@ -6900,7 +6900,7 @@ describe('Gun', function(){
|
||||
var now = new Date().getTime();
|
||||
var cb;
|
||||
for (var i = 1; i <= num; i++) {
|
||||
if (i === num) {
|
||||
if(i === num) {
|
||||
cb = function (err, ok) {
|
||||
console.log(num + 'ops: ' + (new Date().getTime() - now)/1000 + 's');
|
||||
}
|
||||
@ -6929,7 +6929,7 @@ describe('Gun', function(){
|
||||
var now = new Date().getTime();
|
||||
var cb;
|
||||
for (var i = 1; i <= num; i++) {
|
||||
if (i === num) {
|
||||
if(i === num) {
|
||||
cb = function () {
|
||||
console.log(num + ' API ops: ' + (new Date().getTime() - now)/1000 + 's');
|
||||
t && done();
|
||||
@ -7117,7 +7117,7 @@ describe('Gun', function(){
|
||||
var now = new Date().getTime();
|
||||
var cb;
|
||||
for (var i = 1; i <= num; i++) {
|
||||
if (i === num) {
|
||||
if(i === num) {
|
||||
cb = function (err, ok) {
|
||||
console.log(num + 'MUTANT ops: ' + (new Date().getTime() - now)/1000 + 's');
|
||||
t && done();
|
||||
@ -7265,7 +7265,7 @@ describe('Gun', function(){
|
||||
gun.map(function (player, number) {
|
||||
players[number] = player;
|
||||
players[number].history = [];
|
||||
if (!player.taken && !me) {
|
||||
if(!player.taken && !me) {
|
||||
this.put({
|
||||
taken: true,
|
||||
history: {
|
||||
@ -7645,7 +7645,7 @@ describe('Gun', function(){
|
||||
Gun.log.debug = 1; console.log("------------------");
|
||||
gun.path('1.2.data').on(function (data) {
|
||||
console.log("??????", data);
|
||||
if (data) {
|
||||
if(data) {
|
||||
// gun will never receive the "true" update
|
||||
done();
|
||||
}
|
||||
@ -8196,19 +8196,25 @@ describe('Gun', function(){
|
||||
}catch(e){done(e); return};
|
||||
done();
|
||||
};
|
||||
user.auth(alias+type, pass+' new').then(function(usr){
|
||||
try{
|
||||
expect(usr).to.not.be(undefined);
|
||||
expect(usr).to.not.be('');
|
||||
expect(usr).to.not.have.key('err');
|
||||
expect(usr).to.have.key('put');
|
||||
}catch(e){done(e); return};
|
||||
// Gun.user.leave - performs logout for authenticated user
|
||||
if(type === 'callback'){
|
||||
user.leave(check);
|
||||
} else {
|
||||
user.leave().then(check).catch(done);
|
||||
}
|
||||
var usr = alias+type+'leave';
|
||||
user.create(usr, pass).then(function(ack){
|
||||
expect(ack).to.not.be(undefined);
|
||||
expect(ack).to.not.be('');
|
||||
expect(ack).to.have.keys(['ok','pub']);
|
||||
user.auth(usr, pass).then(function(usr){
|
||||
try{
|
||||
expect(usr).to.not.be(undefined);
|
||||
expect(usr).to.not.be('');
|
||||
expect(usr).to.not.have.key('err');
|
||||
expect(usr).to.have.key('put');
|
||||
}catch(e){done(e); return};
|
||||
// Gun.user.leave - performs logout for authenticated user
|
||||
if(type === 'callback'){
|
||||
user.leave(check);
|
||||
} else {
|
||||
user.leave().then(check).catch(done);
|
||||
}
|
||||
}).catch(done);
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
@ -8222,20 +8228,28 @@ describe('Gun', function(){
|
||||
}catch(e){done(e); return};
|
||||
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);
|
||||
}
|
||||
});
|
||||
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', function(){
|
||||
it('existing authenticated user', function(done){
|
||||
var check = function(ack){
|
||||
var usr = alias+type+'del';
|
||||
|
||||
var createUser = function(a, p){
|
||||
return user.create(a, p).then(function(ack){
|
||||
expect(ack).to.not.be(undefined);
|
||||
expect(ack).to.not.be('');
|
||||
expect(ack).to.have.keys(['ok','pub']);
|
||||
return ack;
|
||||
});
|
||||
};
|
||||
var check = function(done){
|
||||
return function(ack){
|
||||
try{
|
||||
expect(ack).to.not.be(undefined);
|
||||
expect(ack).to.not.be('');
|
||||
@ -8245,32 +8259,56 @@ describe('Gun', function(){
|
||||
}catch(e){done(e); return};
|
||||
done();
|
||||
};
|
||||
var aalias = alias+type+'del';
|
||||
user.create(aalias, pass).catch(check).then(function(ack){
|
||||
try{
|
||||
expect(ack).to.not.be(undefined);
|
||||
expect(ack).to.not.be('');
|
||||
expect(ack).to.have.keys(['ok','pub']);
|
||||
}catch(e){done(e); return};
|
||||
user.auth(aalias, pass).then(function(usr){
|
||||
};
|
||||
|
||||
it('existing authenticated user', function(done){
|
||||
createUser(usr, pass).then(function(){
|
||||
user.auth(usr, pass).then(function(ack){
|
||||
try{
|
||||
expect(usr).to.not.be(undefined);
|
||||
expect(usr).to.not.be('');
|
||||
expect(usr).to.not.have.key('err');
|
||||
expect(usr).to.have.key('put');
|
||||
expect(ack).to.not.be(undefined);
|
||||
expect(ack).to.not.be('');
|
||||
expect(ack).to.not.have.key('err');
|
||||
expect(ack).to.have.key('put');
|
||||
}catch(e){done(e); return};
|
||||
// Gun.user.delete - deöetes existing user account
|
||||
// Gun.user.delete - deletes existing user account
|
||||
if(type === 'callback'){
|
||||
user.delete(alias+type, pass+' new', check);
|
||||
user.delete(usr, pass, check(done));
|
||||
} else {
|
||||
user.delete(alias+type, pass+' new').then(check).catch(done);
|
||||
user.delete(usr, pass).then(check(done)).catch(done);
|
||||
}
|
||||
}).catch(done);
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('unauthenticated existing user', function(done){
|
||||
createUser(usr, pass).catch(function(){})
|
||||
.then(function(){
|
||||
if(type === 'callback'){
|
||||
user.delete(usr, pass, check(done));
|
||||
} else {
|
||||
user.delete(usr, pass).then(check(done)).catch(done);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('unauthenticated existing user');
|
||||
it.skip('unauthenticated other user');
|
||||
it('non-existing user', function(done){
|
||||
var notFound = function(ack){
|
||||
try{
|
||||
expect(ack).to.not.be(undefined);
|
||||
expect(ack).to.not.be('');
|
||||
expect(ack).to.not.have.key('put');
|
||||
expect(ack).to.have.key('err');
|
||||
}catch(e){done(e); return};
|
||||
done();
|
||||
};
|
||||
if(type === 'callback'){
|
||||
user.delete('someone', 'password guess', notFound);
|
||||
} else {
|
||||
user.delete('someone', 'password guess').then(function(){
|
||||
done('Unexpectedly deleted guessed user!');
|
||||
}).catch(notFound);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('recall', function(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user