123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- var SEA = require('./sea')
- var Gun = SEA.Gun;
-
-
- Gun.on('opt', function(at){
- if(!at.sea){
- at.sea = {own: {}};
-
-
- at.on('put', check, at);
- }
- this.to.next(at);
- });
-
-
-
-
-
-
-
-
-
-
-
-
-
- function each(msg){
-
-
- var to = this.to, vertex = (msg.$._).put, c = 0, d;
- Gun.node.is(msg.put, function(val, key, node){
-
- var tmp = Gun.obj.ify(val) || noop;
- if(u !== tmp[':']){
- node[key] = SEA.opt.unpack(tmp);
- return;
- }
- if(!SEA.opt.check(val)){ return }
- c++;
- SEA.verify(val, false, function(data){ c--;
- node[key] = SEA.opt.unpack(data, key, node);;
- if(d && !c && (c = -1)){ to.next(msg) }
- });
- });
- if((d = true) && !c){ to.next(msg) }
- }
-
- function signature(msg){
- if((msg._||noop).user){
- return this.to.next(msg);
- }
- var ctx = this.as;
- (msg._||(msg._=function(){})).user = ctx.user;
- security.call(this, msg);
- }
- var u;
- function check(msg){
- var eve = this, at = eve.as, put = msg.put, soul = put['#'], key = put['.'], val = put[':'], state = put['>'], id = msg['#'], tmp;
- if(!soul || !key){ return }
- if((msg._||'').faith && (at.opt||'').faith && 'function' == typeof msg._){
- SEA.verify(SEA.opt.pack(put), false, function(data){
- put['='] = SEA.opt.unpack(data);
- eve.to.next(msg);
- });
- return
- }
- var no = function(why){ at.on('in', {'@': id, err: why}) };
-
- (msg._||'').DBG && ((msg._||'').DBG.c = +new Date);
- if(0 <= soul.indexOf('<?')){
-
- tmp = parseFloat(soul.split('<?')[1]||'');
- if(tmp && (state < (Gun.state() - (tmp * 1000)))){
- (tmp = msg._) && (tmp = tmp.lot) && (tmp.more--);
- return;
- }
- }
- if('~@' === soul){
- check.alias(eve, msg, val, key, soul, at, no); return;
- }
- if('~@' === soul.slice(0,2)){
- check.pubs(eve, msg, val, key, soul, at, no); return;
- }
-
- if(tmp = SEA.opt.pub(soul)){
- check.pub(eve, msg, val, key, soul, at, no, at.user||'', tmp); return;
- }
- if(0 <= soul.indexOf('#')){
- check.hash(eve, msg, val, key, soul, at, no); return;
- }
- check.any(eve, msg, val, key, soul, at, no, at.user||''); return;
- eve.to.next(msg);
- }
- check.hash = function(eve, msg, val, key, soul, at, no){
- SEA.work(val, null, function(data){
- if(data && data === key.split('#').slice(-1)[0]){ return eve.to.next(msg) }
- no("Data hash not same as hash!");
- }, {name: 'SHA-256'});
- }
- check.alias = function(eve, msg, val, key, soul, at, no){
- if(!val){ return no("Data must exist!") }
- if('~@'+key === link_is(val)){ return eve.to.next(msg) }
- no("Alias not same!");
- };
- check.pubs = function(eve, msg, val, key, soul, at, no){
- if(!val){ return no("Alias must exist!") }
- if(key === link_is(val)){ return eve.to.next(msg) }
- no("Alias not same!");
- };
- check.pub = function(eve, msg, val, key, soul, at, no, user, pub){ var tmp;
- if('pub' === key && '~'+pub === soul){
- if(val === pub){ return eve.to.next(msg) }
- return no("Account not same!");
- }
- if((tmp = user.is) && pub === tmp.pub){
- SEA.sign(SEA.opt.pack(msg.put), (user._).sea, function(data){
- if(u === data){ return no(SEA.err || 'Signature fail.') }
- if(tmp = link_is(val)){ (at.sea.own[tmp] = at.sea.own[tmp] || {})[pub] = 1 }
- msg.put[':'] = JSON.stringify({':': tmp = SEA.opt.unpack(data.m), '~': data.s});
- msg.put['='] = tmp;
- eve.to.next(msg);
- }, {raw: 1});
- return;
- }
- SEA.verify(SEA.opt.pack(msg.put), pub, function(data){ var tmp;
- data = SEA.opt.unpack(data);
- if(u === data){ return no("Unverified data.") }
- if((tmp = link_is(data)) && pub === SEA.opt.pub(tmp)){ (at.sea.own[tmp] = at.sea.own[tmp] || {})[pub] = 1 }
- msg.put['='] = data;
- eve.to.next(msg);
- });
- };
- check.any = function(eve, msg, val, key, soul, at, no, user){ var tmp, pub;
- if(at.opt.secure){ return no("Soul missing public key at '" + key + "'.") }
-
- at.on('secure', function(msg){ this.off();
- if(!at.opt.secure){ return eve.to.next(msg) }
- no("Data cannot be changed.");
- }).on.on('secure', msg);
- return;
- }
- var link_is = Gun.val.link.is, state_ify = Gun.state.ify;
-
-
-
- function security(msg){
- var at = this.as, sea = at.sea, to = this.to;
- if(at.opt.faith && (msg._||noop).faith){
- this.to.next(msg);
- return;
- }
- if(msg.get){
-
- var soul = msg.get['#'];
- if(soul){
- if(typeof soul !== 'string'){ return to.next(msg) }
- if('alias' === soul){
- return to.next(msg);
- } else
- if('~@' === soul.slice(0,2)){
- return to.next(msg);
- } else {
- return to.next(msg);
- }
- }
- }
- if(msg.put){
-
-
- var check = {}, each = {}, u;
- each.node = function(node, soul){
- if(Gun.obj.empty(node, '_')){ return check['node'+soul] = 0 }
- Gun.obj.map(node, each.way, {soul: soul, node: node});
- };
- each.way = function(val, key){
- var soul = this.soul, node = this.node, tmp;
- if('_' === key){ return }
- if('~@' === soul){
- each.alias(val, key, node, soul); return;
- }
- if('~@' === soul.slice(0,2)){
- each.pubs(val, key, node, soul); return;
- }
- if('~' === soul.slice(0,1) && 2 === (tmp = soul.slice(1)).split('.').length){
- each.pub(val, key, node, soul, tmp, (msg._||noop).user); return;
- }
- each.any(val, key, node, soul, (msg._||noop).user); return;
- return each.end({err: "No other data allowed!"});
- };
- each.alias = function(val, key, node, soul){
- if(!val){ return each.end({err: "Data must exist!"}) }
- if('~@'+key === Gun.val.link.is(val)){ return check['alias'+key] = 0 }
- each.end({err: "Mismatching alias."});
- };
- each.pubs = function(val, key, node, soul){
- if(!val){ return each.end({err: "Alias must exist!"}) }
- if(key === Gun.val.link.is(val)){ return check['pubs'+soul+key] = 0 }
- each.end({err: "Alias must match!"});
- };
- each.pub = function(val, key, node, soul, pub, user){ var tmp;
- if('pub' === key){
- if(val === pub){ return (check['pub'+soul+key] = 0) }
- return each.end({err: "Account must match!"});
- }
- check['user'+soul+key] = 1;
- if(Gun.is(msg.$) && user && user.is && pub === user.is.pub){
- SEA.sign(SEA.opt.prep(tmp = SEA.opt.parse(val), key, node, soul), (user._).sea, function(data){ var rel;
- if(u === data){ return each.end({err: SEA.err || 'Pub signature fail.'}) }
- if(rel = Gun.val.link.is(val)){
- (at.sea.own[rel] = at.sea.own[rel] || {})[pub] = true;
- }
- node[key] = JSON.stringify({':': SEA.opt.unpack(data.m), '~': data.s});
- check['user'+soul+key] = 0;
- each.end({ok: 1});
- }, {check: SEA.opt.pack(tmp, key, node, soul), raw: 1});
- return;
- }
- SEA.verify(SEA.opt.pack(val,key,node,soul), pub, function(data){ var rel, tmp;
- data = SEA.opt.unpack(data, key, node);
- if(u === data){
- return each.end({err: "Unverified data."});
- }
- if((rel = Gun.val.link.is(data)) && pub === SEA.opt.pub(rel)){
- (at.sea.own[rel] = at.sea.own[rel] || {})[pub] = true;
- }
- check['user'+soul+key] = 0;
- each.end({ok: 1});
- });
- };
- each.any = function(val, key, node, soul, user){ var tmp, pub;
- if(!(pub = SEA.opt.pub(soul))){
- if(at.opt.secure){
- each.end({err: "Soul is missing public key at '" + key + "'."});
- return;
- }
-
- check['any'+soul+key] = 1;
- at.on('secure', function(msg){ this.off();
- check['any'+soul+key] = 0;
- if(at.opt.secure){ msg = null }
- each.end(msg || {err: "Data cannot be modified."});
- }).on.on('secure', msg);
-
- return;
- }
- if(Gun.is(msg.$) && user && user.is && pub === user.is.pub){
-
- check['any'+soul+key] = 1;
- SEA.sign(SEA.opt.prep(tmp = SEA.opt.parse(val), key, node, soul), (user._).sea, function(data){
- if(u === data){ return each.end({err: 'My signature fail.'}) }
- node[key] = JSON.stringify({':': SEA.opt.unpack(data.m), '~': data.s});
- check['any'+soul+key] = 0;
- each.end({ok: 1});
- }, {check: SEA.opt.pack(tmp, key, node, soul), raw: 1});
- return;
- }
- check['any'+soul+key] = 1;
- SEA.verify(SEA.opt.pack(val,key,node,soul), pub, function(data){ var rel;
- data = SEA.opt.unpack(data, key, node);
- if(u === data){ return each.end({err: "Mismatched owner on '" + key + "'."}) }
- if((rel = Gun.val.link.is(data)) && pub === SEA.opt.pub(rel)){
- (at.sea.own[rel] = at.sea.own[rel] || {})[pub] = true;
- }
- check['any'+soul+key] = 0;
- each.end({ok: 1});
- });
- }
- each.end = function(ctx){
- if(each.err){ return }
- if((each.err = ctx.err) || ctx.no){
- console.log('NO!', each.err, msg.put);
- return;
- }
- if(!each.end.ed){ return }
- if(Gun.obj.map(check, function(no){
- if(no){ return true }
- })){ return }
- (msg._||{}).user = at.user || security;
- to.next(msg);
- };
- Gun.obj.map(msg.put, each.node);
- each.end({end: each.end.ed = true});
- return;
- }
- to.next(msg);
- }
- var pubcut = /[^\w_-]/;
- SEA.opt.pub = function(s){
- if(!s){ return }
- s = s.split('~');
- if(!s || !(s = s[1])){ return }
- s = s.split(pubcut).slice(0,2);
- if(!s || 2 != s.length){ return }
- if('@' === (s[0]||'')[0]){ return }
- s = s.slice(0,2).join('.');
- return s;
- }
- SEA.opt.prep = function(d,k, n,s){
- return {'#':s,'.':k,':':SEA.opt.parse(d),'>':Gun.state.is(n, k)};
- }
- SEA.opt.pack = function(d,k, n,s){
- if(SEA.opt.check(d)){ return d }
- var meta = (Gun.obj.ify((d && d[':'])||d)||''), sig = meta['~'];
- return sig? {m: {'#':s||d['#'],'.':k||d['.'],':':meta[':'],'>':d['>']||Gun.state.is(n, k)}, s: sig} : d;
- }
- var O = SEA.opt;
- SEA.opt.unpack = function(d, k, n){ var tmp;
- if(u === d){ return }
- if(d && (u !== (tmp = d[':']))){ return tmp }
- k = k || O.fall_key; if(!n && O.fall_val){ n = {}; n[k] = O.fall_val }
- if(!k || !n){ return }
- if(d === n[k]){ return d }
- if(!SEA.opt.check(n[k])){ return d }
- var soul = Gun.node.soul(n) || O.fall_soul, s = Gun.state.is(n, k) || O.fall_state;
- if(d && 4 === d.length && soul === d[0] && k === d[1] && fl(s) === fl(d[3])){
- return d[2];
- }
- if(s < SEA.opt.shuffle_attack){
- return d;
- }
- }
- SEA.opt.shuffle_attack = 1546329600000;
- var noop = function(){}, u;
- var fl = Math.floor;
- var rel_is = Gun.val.rel.is;
- var obj_ify = Gun.obj.ify;
-
-
|