This commit is contained in:
Mark Nadal 2018-08-24 03:07:56 -07:00
parent aee20ebbc3
commit 80a9a67d0b
16 changed files with 71 additions and 51 deletions

2
gun.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@
let err let err
// then attempt to log into each one until we find ours! // 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) // (if two users have the same username AND the same password... that would be bad)
const [ user ] = await Promise.all(aliases.map(async ({ at: at, pub: pub }) => { const users = await Promise.all(aliases.map(async ({ at: at, pub: pub }, i) => {
// attempt to PBKDF2 extend the password with the salt. (Verifying the signature gives us the plain text salt.) // attempt to PBKDF2 extend the password with the salt. (Verifying the signature gives us the plain text salt.)
const auth = parseProps(at.put.auth) const auth = parseProps(at.put.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. // NOTE: aliasquery uses `gun.get` which internally SEA.read verifies the data for us, so we do not need to re-verify it here.
@ -30,7 +30,7 @@
const salt = auth.salt const salt = auth.salt
const sea = await SEA.decrypt(auth.ek, proof) const sea = await SEA.decrypt(auth.ek, proof)
if (!sea) { if (!sea) {
err = 'Failed to decrypt secret!' err = 'Failed to decrypt secret! ' + i +'/'+aliases.length;
return return
} }
// now we have AES decrypted the private key, from when we encrypted it with the proof at registration. // now we have AES decrypted the private key, from when we encrypted it with the proof at registration.
@ -53,7 +53,7 @@
throw { err } throw { err }
} }
})) }))
var user = Gun.list.map(users, function(acc){ if(acc){ return acc } })
if (!user) { if (!user) {
throw { err: err || 'Public key does not exist!' } throw { err: err || 'Public key does not exist!' }
} }

View File

@ -14,7 +14,7 @@
var u; var u;
// Well first we have to actually create a user. That is what this function does. // Well first we have to actually create a user. That is what this function does.
User.prototype.create = function(username, pass, cb){ User.prototype.create = function(username, pass, cb, opt){
// TODO: Needs to be cleaned up!!! // TODO: Needs to be cleaned up!!!
const gunRoot = this.back(-1) const gunRoot = this.back(-1)
var gun = this, cat = (gun._); var gun = this, cat = (gun._);
@ -24,12 +24,13 @@
return gun; return gun;
} }
cat.ing = true; cat.ing = true;
opt = opt || {};
var resolve = function(){}, reject = resolve; var resolve = function(){}, reject = resolve;
// Because more than 1 user might have the same username, we treat the alias as a list of those users. // Because more than 1 user might have the same username, we treat the alias as a list of those users.
if(cb){ resolve = reject = cb } if(cb){ resolve = reject = cb }
gunRoot.get('~@'+username).get(async (at, ev) => { gunRoot.get('~@'+username).get(async (at, ev) => {
ev.off() ev.off()
if (at.put) { if (at.put && !opt.already) {
// If we can enforce that a user name is already taken, it might be nice to try, but this is not guaranteed. // If we can enforce that a user name is already taken, it might be nice to try, but this is not guaranteed.
const err = 'User already created!' const err = 'User already created!'
Gun.log(err) Gun.log(err)
@ -165,6 +166,17 @@
return user._.sea; return user._.sea;
} }
User.prototype.leave = async function(){ User.prototype.leave = async function(){
var gun = this, user = (gun.back(-1)._).user;
if(user){
delete user.is;
delete user._.is;
delete user._.sea;
}
if(typeof window !== 'undefined'){
var tmp = window.sessionStorage;
delete tmp.alias;
delete tmp.tmp;
}
return await authLeave(this.back(-1)) return await authLeave(this.back(-1))
} }
// If authenticated user wants to delete his/her account, let's support it! // If authenticated user wants to delete his/her account, let's support it!

View File

@ -52,6 +52,7 @@
if(cb){ try{ cb(r) }catch(e){console.log(e)} } if(cb){ try{ cb(r) }catch(e){console.log(e)} }
return r; return r;
} catch(e) { } catch(e) {
console.log(e);
SEA.err = e; SEA.err = e;
if(cb){ cb() } if(cb){ cb() }
return; return;

View File

@ -4,7 +4,7 @@
// THIS IS AN EARLY ALPHA! // THIS IS AN EARLY ALPHA!
function SEA(){} function SEA(){}
if(typeof window !== "undefined"){ SEA.window = window } if(typeof window !== "undefined"){ (SEA.window = window).SEA = SEA }
module.exports = SEA; module.exports = SEA;

View File

@ -1,14 +1,12 @@
const { const shim = require('./shim');
subtle, ossl = subtle, random: getRandomBytes, TextEncoder, TextDecoder
} = require('./shim')
const Buffer = require('./buffer') const Buffer = require('./buffer')
const parse = require('./parse') const parse = require('./parse')
const { pbkdf2 } = require('./settings') const { pbkdf2 } = require('./settings')
// This internal func returns SHA-256 hashed data for signing // This internal func returns SHA-256 hashed data for signing
const sha256hash = async (mm) => { const sha256hash = async (mm) => {
const m = parse(mm) const m = parse(mm)
const hash = await ossl.digest({name: pbkdf2.hash}, new TextEncoder().encode(m)) const hash = await shim.subtle.digest({name: pbkdf2.hash}, new shim.TextEncoder().encode(m))
return Buffer.from(hash) return Buffer.from(hash)
} }
module.exports = sha256hash module.exports = sha256hash

View File

@ -28,7 +28,7 @@
}); });
try{ try{
const WebCrypto = require('node-webcrypto-ossl') const WebCrypto = require('node-webcrypto-ossl')
api.ossl = new WebCrypto({directory: 'key_storage'}).subtle // ECDH api.ossl = new WebCrypto({directory: 'ossl'}).subtle // ECDH
}catch(e){ }catch(e){
console.log("node-webcrypto-ossl is optionally needed for ECDH, please install if needed."); console.log("node-webcrypto-ossl is optionally needed for ECDH, please install if needed.");
} }

View File

@ -26,6 +26,7 @@
if(cb){ try{ cb(r) }catch(e){console.log(e)} } if(cb){ try{ cb(r) }catch(e){console.log(e)} }
return r; return r;
} catch(e) { } catch(e) {
console.log(e);
SEA.err = e; SEA.err = e;
if(cb){ cb() } if(cb){ cb() }
return; return;

View File

@ -3,9 +3,8 @@
var Gun = SEA.Gun; var Gun = SEA.Gun;
var then = require('./then'); var then = require('./then');
function User(){ function User(root){
this._ = {$: this} this._ = {$: this};
Gun.call()
} }
User.prototype = (function(){ function F(){}; F.prototype = Gun.chain; return new F() }()) // Object.create polyfill User.prototype = (function(){ function F(){}; F.prototype = Gun.chain; return new F() }()) // Object.create polyfill
User.prototype.constructor = User; User.prototype.constructor = User;

View File

@ -27,6 +27,7 @@
if(cb){ try{ cb(r) }catch(e){console.log(e)} } if(cb){ try{ cb(r) }catch(e){console.log(e)} }
return r; return r;
} catch(e) { } catch(e) {
console.log(e);
SEA.err = e; SEA.err = e;
if(cb){ cb() } if(cb){ cb() }
return; return;

View File

@ -15,15 +15,13 @@ Gun.on('create', function(root){
// See the next 'opt' code below for actual saving of data. // See the next 'opt' code below for actual saving of data.
var ev = this.to, opt = root.opt; var ev = this.to, opt = root.opt;
if(root.once){ return ev.next(root) } if(root.once){ return ev.next(root) }
if(false === opt.localStorage){ return ev.next(root) } //if(false === opt.localStorage){ return ev.next(root) } // we want offline resynce queue regardless!
opt.file = opt.file || 'gun/'; opt.prefix = opt.file || 'gun/';
var gap = Gun.obj.ify(store.getItem('gap/'+opt.file)) || {}; var gap = Gun.obj.ify(store.getItem('gap/'+opt.prefix)) || {};
var empty = Gun.obj.empty, id, to, go; var empty = Gun.obj.empty, id, to, go;
// add re-sync command. // add re-sync command.
if(!empty(gap)){ if(!empty(gap)){
root.on('localStorage', function(disk){ var disk = Gun.obj.ify(store.getItem(opt.prefix)) || {}, send = {};
this.off();
var send = {}
Gun.obj.map(gap, function(node, soul){ Gun.obj.map(gap, function(node, soul){
Gun.obj.map(node, function(val, key){ Gun.obj.map(node, function(val, key){
send[soul] = Gun.state.to(disk[soul], key, send[soul]); send[soul] = Gun.state.to(disk[soul], key, send[soul]);
@ -32,7 +30,6 @@ Gun.on('create', function(root){
setTimeout(function(){ setTimeout(function(){
root.on('out', {put: send, '#': root.ask(ack), I: root.$}); root.on('out', {put: send, '#': root.ask(ack), I: root.$});
},10); },10);
});
} }
root.on('out', function(msg){ root.on('out', function(msg){
@ -70,7 +67,7 @@ Gun.on('create', function(root){
var flush = function(){ var flush = function(){
clearTimeout(to); clearTimeout(to);
to = false; to = false;
try{store.setItem('gap/'+opt.file, JSON.stringify(gap)); try{store.setItem('gap/'+opt.prefix, JSON.stringify(gap));
}catch(e){ Gun.log(err = e || "localStorage failure") } }catch(e){ Gun.log(err = e || "localStorage failure") }
} }
}); });
@ -80,9 +77,9 @@ Gun.on('create', function(root){
var opt = root.opt; var opt = root.opt;
if(root.once){ return } if(root.once){ return }
if(false === opt.localStorage){ return } if(false === opt.localStorage){ return }
opt.file = opt.file || opt.prefix || 'gun/'; // support old option name. opt.prefix = opt.file || 'gun/';
var graph = root.graph, acks = {}, count = 0, to; var graph = root.graph, acks = {}, count = 0, to;
var disk = Gun.obj.ify(store.getItem(opt.file)) || {}; var disk = Gun.obj.ify(store.getItem(opt.prefix)) || {};
var lS = function(){}, u; var lS = function(){}, u;
root.on('localStorage', disk); // NON-STANDARD EVENT! root.on('localStorage', disk); // NON-STANDARD EVENT!
@ -130,10 +127,10 @@ Gun.on('create', function(root){
var ack = acks; var ack = acks;
acks = {}; acks = {};
if(data){ disk = data } if(data){ disk = data }
try{store.setItem(opt.file, JSON.stringify(disk)); try{store.setItem(opt.prefix, JSON.stringify(disk));
}catch(e){ }catch(e){
Gun.log(err = e || "localStorage failure"); Gun.log(err = e || "localStorage failure");
root.on('localStorage:error', {err: err, file: opt.file, flush: disk, retry: flush}); root.on('localStorage:error', {err: err, file: opt.prefix, flush: disk, retry: flush});
} }
if(!err && !Gun.obj.empty(opt.peers)){ return } // only ack if there are no peers. if(!err && !Gun.obj.empty(opt.peers)){ return } // only ack if there are no peers.
Gun.obj.map(ack, function(yes, id){ Gun.obj.map(ack, function(yes, id){

View File

@ -99,11 +99,7 @@ function Mesh(ctx){
var wire = peer.wire; var wire = peer.wire;
try{ try{
if(wire.send){ if(wire.send){
if(wire.readyState === wire.OPEN){
wire.send(raw); wire.send(raw);
} else {
(peer.queue = peer.queue || []).push(raw);
}
} else } else
if(peer.say){ if(peer.say){
peer.say(raw); peer.say(raw);

View File

@ -24,7 +24,6 @@ function output(msg){
at.on('in', at); at.on('in', at);
return; return;
}*/ }*/
//console.log("out!", at.get, get);
if(get['#'] || at.soul){ if(get['#'] || at.soul){
get['#'] = get['#'] || at.soul; get['#'] = get['#'] || at.soul;
msg['#'] || (msg['#'] = text_rand(9)); msg['#'] || (msg['#'] = text_rand(9));
@ -164,7 +163,6 @@ function relate(at, msg, from, rel){
not(at, msg); not(at, msg);
} }
tmp = from.id? ((at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from}) : {}; tmp = from.id? ((at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from}) : {};
//console.log("REL?", at.id, at.get, rel === tmp.link, tmp.pass || at.pass);
if(rel === tmp.link){ if(rel === tmp.link){
if(!(tmp.pass || at.pass)){ if(!(tmp.pass || at.pass)){
return; return;

View File

@ -33,6 +33,7 @@ var Graph = {};
if(env.soul){ if(env.soul){
at.rel = Val.rel.ify(env.soul); at.rel = Val.rel.ify(env.soul);
} }
env.shell = (as||{}).shell;
env.graph = env.graph || {}; env.graph = env.graph || {};
env.seen = env.seen || []; env.seen = env.seen || [];
env.as = env.as || as; env.as = env.as || as;
@ -45,9 +46,11 @@ var Graph = {};
at.env = env; at.env = env;
at.soul = soul; at.soul = soul;
if(Node.ify(at.obj, map, at)){ if(Node.ify(at.obj, map, at)){
//at.rel = at.rel || Val.rel.ify(Node.soul(at.node)); at.rel = at.rel || Val.rel.ify(Node.soul(at.node));
if(at.obj !== env.shell){
env.graph[Val.rel.is(at.rel)] = at.node; env.graph[Val.rel.is(at.rel)] = at.node;
} }
}
return at; return at;
} }
function map(v,k,n){ function map(v,k,n){

View File

@ -14,10 +14,8 @@ Gun.chain.map = function(cb, opt, t){
gun.map().on(function(data, key, at, ev){ gun.map().on(function(data, key, at, ev){
var next = (cb||noop).call(this, data, key, at, ev); var next = (cb||noop).call(this, data, key, at, ev);
if(u === next){ return } if(u === next){ return }
if(data === next || Gun.is(next)){ if(data === next){ return chain._.on('in', at) }
chain._.on('in', next._); if(Gun.is(next)){ return chain._.on('in', next._) }
return;
}
chain._.on('in', {get: key, put: next}); chain._.on('in', {get: key, put: next});
}); });
return chain; return chain;

View File

@ -151,8 +151,24 @@ Gun.dup = require('./dup');
} }
Gun.on.get = function(msg, gun){ Gun.on.get = function(msg, gun){
var root = gun._, soul = msg.get[_soul], node = root.graph[soul], has = msg.get[_has], tmp; var root = gun._, get = msg.get, soul = get[_soul], node = root.graph[soul], has = get[_has], tmp;
var next = root.next || (root.next = {}), at = next[soul]; var next = root.next || (root.next = {}), at = next[soul];
if(get['*']){ // TEMPORARY HACK FOR MARTTI, TESTING
var graph = {};
Gun.obj.map(root.graph, function(node, soul){
if(Gun.text.match(soul, get)){
graph[soul] = Gun.obj.copy(node);
}
});
if(!Gun.obj.empty(graph)){
root.on('in', {
'@': msg['#'],
how: '*',
put: graph,
$: gun
});
}
} // TEMPORARY HACK FOR MARTTI, TESTING
if(!node || !at){ return root.on('get', msg) } if(!node || !at){ return root.on('get', msg) }
if(has){ if(has){
if(!obj_has(node, has)){ return root.on('get', msg) } if(!obj_has(node, has)){ return root.on('get', msg) }
@ -213,7 +229,7 @@ Gun.log.once = function(w,s,o){ return (o = Gun.log.once)[w] = o[w] || 0, o[w]++
Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, feel free to ask for help on https://gitter.im/amark/gun and ask StackOverflow questions tagged with 'gun'!"); Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, feel free to ask for help on https://gitter.im/amark/gun and ask StackOverflow questions tagged with 'gun'!");
;"Please do not remove these messages unless you are paying for a monthly sponsorship, thanks!"; ;"Please do not remove these messages unless you are paying for a monthly sponsorship, thanks!";
if(typeof window !== "undefined"){ window.Gun = Gun } if(typeof window !== "undefined"){ (window.Gun = Gun).window = window }
try{ if(typeof common !== "undefined"){ common.exports = Gun } }catch(e){} try{ if(typeof common !== "undefined"){ common.exports = Gun } }catch(e){}
module.exports = Gun; module.exports = Gun;