mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
SEA + GUN thanks to @mhelander !!! Tested by PANIC!
Sea
This commit is contained in:
commit
b026a9c9f2
8
gun.js
8
gun.js
@ -749,15 +749,19 @@
|
||||
};
|
||||
if(this.ack){ msg['@'] = this.ack }
|
||||
obj_map(node, each, this);
|
||||
cat.on('node', msg);
|
||||
}
|
||||
function each(val, key){
|
||||
var graph = this.graph, soul = this.soul, at = (this.at._), tmp;
|
||||
graph[soul] = Gun.state.to(this.node, key, graph[soul]);
|
||||
at.put = Gun.state.to(this.node, key, at.put);
|
||||
}
|
||||
function map(msg, soul){
|
||||
function map(msg, soul){ var tmp;
|
||||
if(!msg.gun){ return }
|
||||
if((tmp = this.gun._).tag.node){
|
||||
return tmp.on('node', function(msg){ this.off();
|
||||
(msg.gun._).on('in', msg);
|
||||
}).on.on('node', msg);
|
||||
}
|
||||
(msg.gun._).on('in', msg);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
"start": "node examples/http.js 8080",
|
||||
"prepublish": "npm run unbuild",
|
||||
"test": "mocha",
|
||||
"testsea": "mocha test/sea.js",
|
||||
"e2e": "mocha e2e/distributed.js",
|
||||
"docker": "hooks/build",
|
||||
"unbuild": "node lib/unbuild.js && uglifyjs gun.js -o gun.min.js -c -m"
|
||||
|
163
sea.js
163
sea.js
@ -128,19 +128,21 @@
|
||||
return reject(err);
|
||||
}
|
||||
// then figuring out all possible candidates having matching username
|
||||
var aliases = [];
|
||||
var aliases = [], c = 0;
|
||||
Gun.obj.map(rat.put, function(at, pub){
|
||||
if(!pub.slice || 'pub/' !== pub.slice(0,4)){ return }
|
||||
c++;
|
||||
// grab the account associated with this public key.
|
||||
root.get(pub).get(function(at, ev){
|
||||
if(!pub.slice || 'pub/' !== pub.slice(0,4)){ return }
|
||||
pub = pub.slice(4);
|
||||
ev.off();
|
||||
if(!at.put){ return }
|
||||
aliases.push({pub: pub, at: at});
|
||||
ev.off(); c--;
|
||||
if(at.put){
|
||||
aliases.push({pub: pub, at: at});
|
||||
}
|
||||
if(!c && (c = -1)){ resolve(aliases) }
|
||||
});
|
||||
});
|
||||
return aliases.length && resolve(aliases)
|
||||
|| reject('Public key does not exist!');
|
||||
if(!c){ reject('Public key does not exist!') }
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -158,7 +160,7 @@
|
||||
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.auth, pub).then(function(auth){
|
||||
var auth = at.put.auth; // SEA.read(at.put.auth, pub).then(function(auth){ // NOTE: aliasquery uses `gun.get` which internally SEA.read verifies the data for us, so we do not need to re-verify it here.
|
||||
auth = auth.slice ? JSON.parse(auth) : auth;
|
||||
return SEA.proof(pass, auth.salt)
|
||||
.catch(function(e){ reject({err: 'Failed to create proof!'}) })
|
||||
@ -173,12 +175,10 @@
|
||||
if(sea){
|
||||
user.priv = sea.priv;
|
||||
user.salt = auth.salt; // TODO: needed?
|
||||
SEA.read(at.put.epub, pub).then(function(epub){
|
||||
var epub = at.put.epub; //SEA.read(at.put.epub, pub).then(function(epub){ // NOTE: see above "NOTE"!
|
||||
Object.assign(user, {epub: epub, epriv: sea.epriv});
|
||||
resolve(user);
|
||||
}).catch(function(){
|
||||
return !remaining && reject({err: 'Public key does not exist!'});
|
||||
});
|
||||
//}).catch(function(){ return !remaining && reject({err: 'Public key does not exist!'}) });
|
||||
} else if(!remaining){
|
||||
reject({err: 'Public key does not exist!'});
|
||||
}
|
||||
@ -188,7 +188,7 @@
|
||||
// : reject({err: 'Failed to decrypt private key!'});
|
||||
}).catch(function(e){ reject({err: 'Failed read secret!'})} );
|
||||
});
|
||||
}).catch(function(e){ reject({err: 'Failed to create proof!'}) });
|
||||
//}).catch(function(e){ reject({err: 'Failed to create proof!'}) });
|
||||
});
|
||||
}).catch(function(e){ reject({err: e}) });
|
||||
});
|
||||
@ -329,7 +329,7 @@
|
||||
};
|
||||
|
||||
// Already authenticated?
|
||||
if(Gun.obj.has(root._.user._, 'pub') && Gun.obj.has(root._.user._, 'sea')){
|
||||
if(root._.user && Gun.obj.has(root._.user._, 'pub') && Gun.obj.has(root._.user._, 'sea')){
|
||||
return resolve(root._.user._);
|
||||
}
|
||||
// No, got alias?
|
||||
@ -383,9 +383,9 @@
|
||||
return !remaining && reject({err: 'Failed to decrypt private key!'});
|
||||
}).then(function(sea){
|
||||
if(!sea){ return }
|
||||
return SEA.read(at.put.epub, pub).then(function(epub){
|
||||
var epub = at.put.epub; //return SEA.read(at.put.epub, pub).then(function(epub){ // NOTE: queryalias uses `gun.get` which internally verifies data with `SEA.read` so we do not need to do it again.
|
||||
return {pub: pub, priv: sea.priv, epriv: sea.epriv, epub: epub};
|
||||
});
|
||||
//});
|
||||
}).then(function(key){
|
||||
// now we have AES decrypted the private key,
|
||||
// if we were successful, then that means we're logged in!
|
||||
@ -431,8 +431,9 @@
|
||||
// This internal func executes logout actions
|
||||
function authleave(root, alias){
|
||||
return function(resolve, reject){
|
||||
var user = root._.user;
|
||||
alias = alias || (user._ && user._.alias);
|
||||
var user = root._.user || {_:{}};
|
||||
root._.user = null;
|
||||
alias = alias || user._.alias;
|
||||
var doIt = function(){
|
||||
// TODO: is this correct way to 'logout' user from Gun.User ?
|
||||
[ 'alias', 'sea', 'pub' ].forEach(function(key){
|
||||
@ -554,7 +555,6 @@
|
||||
reject({err: 'Auth attempt failed! Reason: No session data for alias & PIN'});
|
||||
});
|
||||
}
|
||||
|
||||
authenticate(alias, pass, root).then(function(keys){
|
||||
// we're logged in!
|
||||
var pin = Gun.obj.has(opts, 'pin') && {pin: opts.pin};
|
||||
@ -631,7 +631,7 @@
|
||||
// Delete user data
|
||||
root.get('pub/'+key.pub).put(null);
|
||||
// Wipe user data from memory
|
||||
var user = root._.user;
|
||||
var user = root._.user || {_: {}};
|
||||
// TODO: is this correct way to 'logout' user from Gun.User ?
|
||||
[ 'alias', 'sea', 'pub' ].forEach(function(key){
|
||||
delete user._[key];
|
||||
@ -734,22 +734,37 @@
|
||||
// This means we should ONLY trust our "friends" (our key ring) public keys, not any ones.
|
||||
// I have not yet added that to SEA yet in this alpha release. That is coming soon, but beware in the meanwhile!
|
||||
function each(msg){ // TODO: Warning: Need to switch to `gun.on('node')`! Do not use `Gun.on('node'` in your apps!
|
||||
var ctx = this.as;
|
||||
var own = ctx.sea.own, soul = msg.get;
|
||||
var pub = own[soul] || soul.slice(4), vertex = (msg.gun._).put;
|
||||
Gun.node.is(msg.put, function(val, key, node){ // for each property on the node.
|
||||
SEA.read(val, pub).then(function(data){
|
||||
vertex[key] = node[key] = val = data; // verify signature and get plain value.
|
||||
if(val && val['#'] && (key = Gun.val.rel.is(val))){ // if it is a relation / edge
|
||||
if('alias/' === soul.slice(0,6)){ return } // if it is itself
|
||||
own[key] = pub; // associate the public key with a node
|
||||
}
|
||||
// NOTE: THE SECURITY FUNCTION HAS ALREADY VERIFIED THE DATA!!!
|
||||
// WE DO NOT NEED TO RE-VERIFY AGAIN, JUST TRANSFORM IT TO PLAINTEXT.
|
||||
var to = this.to, vertex = (msg.gun._).put, c = 0;
|
||||
Gun.node.is(msg.put, function(val, key, node){ c++; // for each property on the node
|
||||
SEA.read(val, false).then(function(data){ c--; // false just extracts the plain data.
|
||||
vertex[key] = node[key] = val = data; // transform to plain value.
|
||||
if(!c && (c = -1)){ to.next(msg) }
|
||||
});
|
||||
});
|
||||
if(!c){ to.next(msg) }
|
||||
return;
|
||||
/*var to = this.to, ctx = this.as;
|
||||
var own = ctx.sea.own, soul = msg.get, c = 0;
|
||||
var pub = own[soul] || soul.slice(4), vertex = (msg.gun._).put;
|
||||
Gun.node.is(msg.put, function(val, key, node){ c++; // for each property on the node.
|
||||
SEA.read(val, pub).then(function(data){ c--;
|
||||
vertex[key] = node[key] = val = data; // verify signature and get plain value.
|
||||
if(val && val['#'] && (key = Gun.val.rel.is(val))){ // if it is a relation / edge
|
||||
if('alias/' !== soul.slice(0,6)){ own[key] = pub; } // associate the public key with a node if it is itself
|
||||
}
|
||||
if(!c && (c = -1)){ to.next(msg) }
|
||||
});
|
||||
});
|
||||
if(!c){ to.next(msg) }*/
|
||||
}
|
||||
|
||||
// signature handles data output, it is a proxy to the security function.
|
||||
function signature(msg){
|
||||
if(msg.user){
|
||||
return this.to.next(msg);
|
||||
}
|
||||
var ctx = this.as;
|
||||
msg.user = ctx.user;
|
||||
security.call(this, msg);
|
||||
@ -776,7 +791,7 @@
|
||||
}
|
||||
if(msg.put){
|
||||
// potentially parallel async operations!!!
|
||||
var check = {}, on = Gun.on(), each = {};
|
||||
var check = {}, on = Gun.on(), each = {}, u;
|
||||
each.node = function(node, soul){
|
||||
if(Gun.obj.empty(node, '_')){ return check['node'+soul] = 0 } // ignore empty updates, don't reject them.
|
||||
Gun.obj.map(node, each.way, {soul: soul, node: node});
|
||||
@ -785,56 +800,62 @@
|
||||
var soul = this.soul, node = this.node, tmp;
|
||||
if('_' === key){ return } // ignore meta data
|
||||
if('alias' === soul){ // special case for shared system data, the list of aliases.
|
||||
each.alias(val, key, node, soul);
|
||||
each.alias(val, key, node, soul); return;
|
||||
}
|
||||
if('alias/' === soul.slice(0,6)){ // special case for shared system data, the list of public keys for an alias.
|
||||
each.pubs(val, key, node, soul);
|
||||
each.pubs(val, key, node, soul); return;
|
||||
}
|
||||
if('pub/' === soul.slice(0,4)){ // special case, account data for a public key.
|
||||
each.pub(val, key, node, soul, soul.slice(4));
|
||||
each.pub(val, key, node, soul, soul.slice(4), msg.user); return;
|
||||
}
|
||||
if(at.user && at.user._.sea){ // not special case, if we are logged in, then
|
||||
var u = at.user._, p = u.sea;
|
||||
return each.end({err: "No other data allowed!"});
|
||||
/*if(!(tmp = at.user)){ return }
|
||||
if(soul.slice(4) === (tmp = tmp._).pub){ // not a special case, if we are logged in and have outbound data on us.
|
||||
each.user(val, key, node, soul, {
|
||||
pub: u.pub, priv: p.priv, epub: u.epub, epriv: p.epriv
|
||||
pub: tmp.pub, priv: tmp.sea.priv, epub: tmp.sea.epub, epriv: tmp.sea.epriv
|
||||
});
|
||||
}
|
||||
if((tmp = sea.own[soul])){ // not special case, if we receive an update on an ID associated with a public key, then
|
||||
each.own(val, key, node, soul, tmp);
|
||||
}
|
||||
}*/
|
||||
};
|
||||
each.alias = function(val, key, node, soul){
|
||||
if(!val){ return on.to('end', {err: "Data must exist!"}) } // data MUST exist
|
||||
if('alias/'+key !== Gun.val.rel.is(val)){ // in fact, it must be EXACTLY equal to itself
|
||||
return on.to('end', {err: "Mismatching alias."}); // if it isn't, reject.
|
||||
}
|
||||
each.alias = function(val, key, node, soul){ // Example: {_:#alias, alias/alice: {#alias/alice}}
|
||||
if(!val){ return each.end({err: "Data must exist!"}) } // data MUST exist
|
||||
if('alias/'+key === Gun.val.rel.is(val)){ return check['alias'+key] = 0 } // in fact, it must be EXACTLY equal to itself
|
||||
each.end({err: "Mismatching alias."}); // if it isn't, reject.
|
||||
};
|
||||
each.pubs = function(val, key, node, soul){
|
||||
if(!val){ return on.to('end', {err: "Alias must exist!"}) } // data MUST exist
|
||||
each.pubs = function(val, key, node, soul){ // Example: {_:#alias/alice, pub/asdf: {#pub/asdf}}
|
||||
if(!val){ return each.end({err: "Alias must exist!"}) } // data MUST exist
|
||||
if(key === Gun.val.rel.is(val)){ return check['pubs'+soul+key] = 0 } // and the ID must be EXACTLY equal to its property
|
||||
return on.to('end', {err: "Alias must match!"}); // that way nobody can tamper with the list of public keys.
|
||||
each.end({err: "Alias must match!"}); // that way nobody can tamper with the list of public keys.
|
||||
};
|
||||
each.pub = function(val, key, node, soul, pub){
|
||||
//console.log("WE ARE HERE", key, val, soul, node, pub);
|
||||
each.pub = function(val, key, node, soul, pub, user){ // Example: {_:#pub/asdf, hello:SEA['world',fdsa]}
|
||||
if('pub' === key){
|
||||
if(val === pub){ return check['pub'+soul+key] = 0 } // the account MUST have a `pub` property that equals the ID of the public key.
|
||||
return on.to('end', {err: "Account must match!"});
|
||||
if(val === pub){ return (check['pub'+soul+key] = 0) } // the account MUST match `pub` property that equals the ID of the public key.
|
||||
return each.end({err: "Account must match!"});
|
||||
}
|
||||
/*
|
||||
if(at.user && at.user._){ // if we are logged in
|
||||
if(pub === at.user._.pub){ // as this user
|
||||
SEA.write(val, at.user._.sea).then(function(data){
|
||||
val = node[key] = data; // then sign our updates as we output them.
|
||||
check['user'+soul+key] = 1;
|
||||
if(user && (user = user._) && user.sea){
|
||||
if(pub === user.pub){
|
||||
SEA.write(val, Gun.obj.to(user.sea, {pub: user.pub, epub: user.epub}), function(data){
|
||||
node[key] = data;
|
||||
check['user'+soul+key] = 0;
|
||||
each.end({ok: 1});
|
||||
});
|
||||
} // (if we are lying about our signature, other peer's will reject our update)
|
||||
} else {
|
||||
each.end({err: "Please stop trying to hack/impersonate somebody else!"});
|
||||
}
|
||||
return;
|
||||
}
|
||||
SEA.read(val, pub).then(function(data){
|
||||
if(u === (val = data)){ // make sure the signature matches the account it claims to be on.
|
||||
return no = true; // reject any updates that are signed with a mismatched account.
|
||||
if(u === data){ // make sure the signature matches the account it claims to be on.
|
||||
return each.end({err: "Unverified data."}); // reject any updates that are signed with a mismatched account.
|
||||
}
|
||||
check['user'+soul+key] = 0;
|
||||
each.end({ok: 1});
|
||||
});
|
||||
*/
|
||||
};
|
||||
/*
|
||||
each.user = function(val, key, node, soul, tmp){
|
||||
check['user'+soul+key] = 1;
|
||||
SEA.write(val, tmp, function(data){ // TODO: BUG! Convert to use imported.
|
||||
@ -853,8 +874,9 @@
|
||||
on.to('end', {no: tmp = (u === (val = data)), err: tmp && "Signature mismatch!"});
|
||||
});
|
||||
};
|
||||
on.to('end', function(ctx){ // TODO: Can't you just switch this to each.end = cb?
|
||||
if(each.err || !each.end){ return }
|
||||
*/
|
||||
each.end = function(ctx){ // TODO: Can't you just switch this to each.end = cb?
|
||||
if(each.err || !each.end.ed){ return }
|
||||
if((each.err = ctx.err) || ctx.no){
|
||||
console.log('NO!', each.err);
|
||||
return;
|
||||
@ -863,9 +885,9 @@
|
||||
if(no){ return true }
|
||||
})){ return }
|
||||
to.next(msg);
|
||||
});
|
||||
};
|
||||
Gun.obj.map(msg.put, each.node);
|
||||
on.to('end', {end: each.end = true});
|
||||
each.end({end: each.end.ed = true});
|
||||
return; // need to manually call next after async.
|
||||
}
|
||||
to.next(msg); // pass forward any data we do not know how to handle or process (this allows custom security protocols).
|
||||
@ -1070,14 +1092,15 @@
|
||||
var doIt = function(resolve, reject) {
|
||||
// TODO: something's bugging double 'SEA[]' treatment to mm...
|
||||
var m = mm;
|
||||
if(mm.slice){
|
||||
if(m && m.slice && 'SEA[' === m.slice(0,4)){ return resolve(m) }
|
||||
if(mm && mm.slice){
|
||||
// Needs to remove previous signature envelope
|
||||
while('SEA[' === m.slice(0,4)){
|
||||
try{ m = JSON.parse(m.slice(3))[0];
|
||||
}catch(e){ break }
|
||||
}
|
||||
}
|
||||
m = m.slice ? m : JSON.stringify(m);
|
||||
m = (m && m.slice) ? m : JSON.stringify(m);
|
||||
SEA.sign(m, p).then(function(signature){
|
||||
resolve('SEA'+JSON.stringify([m,signature]));
|
||||
}).catch(function(e){Gun.log(e); reject(e)});
|
||||
@ -1086,12 +1109,18 @@
|
||||
};
|
||||
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){ if(false === p){ return resolve(m) }
|
||||
return resolve();
|
||||
}
|
||||
if(!m.slice || 'SEA[' !== m.slice(0,4)){
|
||||
if(false === p){ return resolve(m) }
|
||||
return resolve()
|
||||
}
|
||||
m = m.slice(3);
|
||||
try{ m = m.slice ? JSON.parse(m) : m;
|
||||
}catch(e){ return reject(e) }
|
||||
m = m || '';
|
||||
if(false === p){ resolve(m[0]) }
|
||||
SEA.verify(m[0], p, m[1]).then(function(ok){
|
||||
resolve(ok && m[0]);
|
||||
}).catch(function(e){reject(e)});
|
||||
|
262
test/panic/users.js
Normal file
262
test/panic/users.js
Normal file
@ -0,0 +1,262 @@
|
||||
var config = {
|
||||
IP: require('ip').address(),
|
||||
port: 8080,
|
||||
servers: 2,
|
||||
browsers: 2,
|
||||
route: {
|
||||
'/': __dirname + '/index.html',
|
||||
'/gun.js': __dirname + '/../../gun.js',
|
||||
'/jquery.js': __dirname + '/../../examples/jquery.js',
|
||||
'/cryptomodules.js': __dirname + '/../../lib/cryptomodules.js',
|
||||
'/sea.js': __dirname + '/../../sea.js'
|
||||
}
|
||||
}
|
||||
|
||||
var panic = require('panic-server');
|
||||
panic.server().on('request', function(req, res){
|
||||
config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res);
|
||||
}).listen(config.port);
|
||||
|
||||
var clients = panic.clients;
|
||||
var manager = require('panic-manager')();
|
||||
|
||||
manager.start({
|
||||
clients: Array(config.servers).fill().map(function(u, i){
|
||||
return {
|
||||
type: 'node',
|
||||
port: config.port + (i + 1)
|
||||
}
|
||||
}),
|
||||
panic: 'http://' + config.IP + ':' + config.port
|
||||
});
|
||||
|
||||
var servers = clients.filter('Node.js');
|
||||
var server = servers.pluck(1);
|
||||
var spawn = servers.excluding(server).pluck(1);
|
||||
var browsers = clients.excluding(servers);
|
||||
var alice = browsers.pluck(1);
|
||||
var bob = browsers.excluding(alice).pluck(1);
|
||||
var again = {};
|
||||
|
||||
describe("End-to-End Encryption on User Accounts", function(){
|
||||
//this.timeout(5 * 60 * 1000);
|
||||
this.timeout(10 * 60 * 1000);
|
||||
|
||||
it("Servers have joined!", function(){
|
||||
return servers.atLeast(config.servers);
|
||||
});
|
||||
|
||||
it("GUN started!", function(){
|
||||
return server.run(function(test){
|
||||
var env = test.props;
|
||||
test.async();
|
||||
try{ require('fs').unlinkSync(env.i+'data') }catch(e){}
|
||||
try{ require('fs').unlinkSync((env.i+1)+'data') }catch(e){}
|
||||
var port = env.config.port + env.i;
|
||||
var server = require('http').createServer(function(req, res){
|
||||
res.end("I am "+ env.i +"!");
|
||||
});
|
||||
var Gun = require('gun');
|
||||
var gun = Gun({file: env.i+'data', web: server});
|
||||
server.listen(port, function(){
|
||||
test.done();
|
||||
});
|
||||
}, {i: 1, config: config});
|
||||
});
|
||||
|
||||
it(config.browsers +" browser(s) have joined!", function(){
|
||||
console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
|
||||
return browsers.atLeast(config.browsers);
|
||||
});
|
||||
|
||||
it("Browsers load SEA!", function(){
|
||||
var tests = [], i = 0;
|
||||
browsers.each(function(client, id){
|
||||
tests.push(client.run(function(test){
|
||||
test.async();
|
||||
console.log("load?");
|
||||
function load(src, cb){
|
||||
var script = document.createElement('script');
|
||||
script.onload = cb; script.src = src;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
load('cryptomodules.js', function(){
|
||||
load('sea.js', function(){
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
}, {i: i += 1, config: config}));
|
||||
});
|
||||
return Promise.all(tests);
|
||||
});
|
||||
|
||||
it("Browsers initialized gun!", function(){
|
||||
var tests = [], i = 0;
|
||||
browsers.each(function(client, id){
|
||||
tests.push(client.run(function(test){
|
||||
localStorage.clear();
|
||||
var env = test.props;
|
||||
var gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun');
|
||||
window.gun = gun;
|
||||
window.user = gun.user();
|
||||
}, {i: i += 1, config: config}));
|
||||
});
|
||||
return Promise.all(tests);
|
||||
});
|
||||
|
||||
it("Create Alice", function(){
|
||||
return alice.run(function(test){
|
||||
console.log("I AM ALICE");
|
||||
test.async();
|
||||
window.user.create('alice', 'xyzabcmnopq', function(ack){
|
||||
if(ack.err || !ack.pub){ return }
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Create Bob", function(){
|
||||
return bob.run(function(test){
|
||||
test.async();
|
||||
window.user.create('bob', 'zyxcbaqponm', function(ack){
|
||||
alert("???");
|
||||
if(ack.err || !ack.pub){ return }
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Auth Alice", function(){
|
||||
return alice.run(function(test){
|
||||
test.async();
|
||||
window.user.auth('alice', 'xyzabcmnopq', function(ack){
|
||||
if(ack.err || !ack.pub){ return }
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
it("Auth Bob typo", function(){
|
||||
return bob.run(function(test){
|
||||
test.async();
|
||||
window.user.auth('bob', 'zyxcbaqponmb', function(ack){
|
||||
if(ack.err && !ack.pub){ console.log("BAD SAUCE"); return test.done() }
|
||||
});
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
it("Auth Bob", function(){
|
||||
return bob.run(function(test){
|
||||
test.async();
|
||||
window.user.auth('bob', 'zyxcbaqponm', function(ack){
|
||||
if(ack.err || !ack.pub){ return }
|
||||
console.log("AWESOME");
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Alice save & subscribe to Bob", function(){
|
||||
return alice.run(function(test){
|
||||
test.async();
|
||||
window.user.on(function(alice){
|
||||
console.log('alice!', alice);
|
||||
if(alice.hello === 'world'){
|
||||
test.done();
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function(){
|
||||
window.user.get('hello').put('world');
|
||||
}, 100);
|
||||
|
||||
window.gun.get('alias/bob').map().on(function(data){
|
||||
console.log("WOOOHOOOOOO!!!", data);
|
||||
window.MARS = data.hello;
|
||||
window.PUB = data.pub;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Bob save", function(){
|
||||
return bob.run(function(test){
|
||||
test.async();
|
||||
window.user.on(function(bob){
|
||||
console.log('bob!', bob);
|
||||
if(bob.hello === 'mars'){
|
||||
test.done();
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function(){
|
||||
window.user.get('hello').put('mars');
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
it("Alice should have Bob", function(){
|
||||
return alice.run(function(test){
|
||||
test.async();
|
||||
setTimeout(function(){
|
||||
if(window.PUB && 'mars' === window.MARS){
|
||||
test.done();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
it("Alice tries to crack Bob", function(){
|
||||
return alice.run(function(test){
|
||||
test.async();
|
||||
gun.get('pub/' + window.PUB).get('crackers').put('gonna crack');
|
||||
setTimeout(function(){
|
||||
test.done();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
it("Alice has no cracked Bob", function(){
|
||||
return alice.run(function(test){
|
||||
test.async();
|
||||
gun.get('pub/' + window.PUB).val(function(data){
|
||||
if(data.pub === window.PUB
|
||||
&& data.hello === 'mars'
|
||||
&& data.alias === 'bob'){
|
||||
test.done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("Bob has no cracked Bob", function(){
|
||||
return bob.run(function(test){
|
||||
test.async();
|
||||
user.val(function(data){
|
||||
if(data.hello === 'mars'
|
||||
&& data.alias === 'bob'){
|
||||
test.done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("All finished!", function(done){
|
||||
console.log("Done! Cleaning things up...");
|
||||
setTimeout(function(){
|
||||
done();
|
||||
},1000);
|
||||
});
|
||||
|
||||
after("Everything shut down.", function(){
|
||||
browsers.run(function(){
|
||||
//location.reload();
|
||||
//setTimeout(function(){
|
||||
//}, 15 * 1000);
|
||||
});
|
||||
return servers.run(function(){
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
});
|
@ -509,7 +509,8 @@ Gun().user && describe('Gun', function(){
|
||||
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' ]);
|
||||
//expect(gun.back(-1)._.user).to.not.have.keys([ 'sea', 'pub' ]);
|
||||
expect(gun.back(-1)._.user).to.not.be.ok();
|
||||
}catch(e){ done(e); return }
|
||||
done();
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user