mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
235 lines
5.7 KiB
HTML
235 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<style>
|
|
html, body {
|
|
background: rgb(245, 245, 245);
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
div {
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
#top {
|
|
background: #283e4a;
|
|
height: 52px;
|
|
width: 100%;
|
|
}
|
|
.box {
|
|
border-radius: 3px;
|
|
box-shadow: 0px 0px 3px #777;
|
|
background: white;
|
|
max-width: 36em;
|
|
margin: 0 auto;
|
|
min-height: 10em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
.color {
|
|
background: #2977b5;
|
|
height: 7em;
|
|
width: 100%;
|
|
}
|
|
.pad {
|
|
margin: 1em;
|
|
}
|
|
.none { display: none; }
|
|
input {
|
|
font-size: 1em;
|
|
margin: 0.1em;
|
|
}
|
|
</style>
|
|
<div id="top">
|
|
<center>
|
|
<input id="search" placeholder="search by pub or DID">
|
|
</center>
|
|
</div>
|
|
|
|
<div class="box">
|
|
<div class="color"></div>
|
|
<div class="pad">
|
|
<form id="sign">
|
|
<h1>Login</h1>
|
|
<input id="alias" placeholder="username">
|
|
<input id="pass" type="password" placeholder="passphrase">
|
|
<input id="in" type="submit" value="sign in">
|
|
<input id="up" type="button" value="sign up">
|
|
</form>
|
|
|
|
|
|
<form id="profile" class="none">
|
|
<h1>Profile</h1>
|
|
<p>Data is privately encrypted by default. "+" to grant access, "x" to revoke access.</p>
|
|
<input id="name" placeholder="name"> <button>+</button><br/>
|
|
<input id="born" placeholder="born"> <button>+</button><br/>
|
|
<input id="edu" placeholder="education"> <button>+</button><br/>
|
|
<input id="skills" placeholder="skills"> <button>+</button><br/>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="box"><div class="pad">
|
|
Public Key: <input id="pub">
|
|
</div></div>
|
|
|
|
<script src="../jquery.js"></script>
|
|
<script src="../../../gun/gun.js"></script>
|
|
<script src="../../../gun/sea.js"></script>
|
|
|
|
<script>
|
|
|
|
// extend SEA functions to base64 encode encrypted data
|
|
// workaround for https://github.com/amark/gun/issues/783
|
|
|
|
(() => {
|
|
const _encrypt = SEA.encrypt;
|
|
SEA.encrypt = function(...args) {
|
|
return _encrypt.apply(this, args).then(enc => btoa(JSON.stringify(enc)));
|
|
}
|
|
|
|
const _decrypt = SEA.decrypt;
|
|
SEA.decrypt = function(data, ...args) {
|
|
try { data = JSON.parse(atob(data)); }
|
|
finally { return _decrypt.apply(this, [data, ...args]); }
|
|
}
|
|
})();
|
|
|
|
// override User functions to fix several issues
|
|
// see https://github.com/amark/gun/issues/808
|
|
|
|
SEA.Gun.User.prototype.grant = function grant(to, cb) {
|
|
const gun = this; const user = gun.back(-1).user();
|
|
const pair = user._.sea; let path = '';
|
|
|
|
gun.back(at => { if (at.has) { path += at.get; } });
|
|
|
|
(async () => {
|
|
let enc, sec;
|
|
|
|
if (sec = await user.get('trust').get(pair.pub).get(path).then()) {
|
|
sec = await SEA.decrypt(sec, pair);
|
|
|
|
} else {
|
|
sec = SEA.random(24).toString();
|
|
enc = await SEA.encrypt(sec, pair);
|
|
|
|
user.get('trust').get(pair.pub).get(path).put(enc);
|
|
}
|
|
|
|
let pub = to.get('pub') .then();
|
|
let epub = to.get('epub').then();
|
|
|
|
pub = await pub; epub = await epub;
|
|
|
|
const dh = await SEA.secret (epub, pair);
|
|
enc = await SEA.encrypt(sec, dh);
|
|
|
|
// if pub is not already in trust, first put an empty node
|
|
// workaround for https://github.com/amark/gun/issues/844
|
|
|
|
if (!await user.get('trust').get(pub).then()) {
|
|
await user.get('trust').get(pub).get(path).put({}).then();
|
|
}
|
|
|
|
user.get('trust').get(pub).get(path).put(enc, cb);
|
|
})();
|
|
|
|
return gun;
|
|
}
|
|
|
|
SEA.Gun.User.prototype.secret = function(data, cb) {
|
|
const gun = this; const user = gun.back(-1).user();
|
|
const pair = user._.sea; let path = '';
|
|
|
|
gun.back(at => { if (at.has) { path += at.get; } });
|
|
|
|
(async () => {
|
|
let enc, sec;
|
|
|
|
if (sec = await user.get('trust').get(pair.pub).get(path).then()) {
|
|
sec = await SEA.decrypt(sec, pair);
|
|
|
|
} else {
|
|
sec = SEA.random(24).toString();
|
|
enc = await SEA.encrypt(sec, pair);
|
|
|
|
user.get('trust').get(pair.pub).get(path).put(enc);
|
|
}
|
|
|
|
enc = await SEA.encrypt(data, sec);
|
|
gun.put(enc, cb);
|
|
})();
|
|
|
|
return gun;
|
|
}
|
|
|
|
var gun = Gun('http://localhost:8765/gun');
|
|
var user = gun.user();
|
|
var LI = {};
|
|
|
|
user.recall({sessionStorage: true});
|
|
|
|
$('#up').on('click', function(e){
|
|
user.create($('#alias').val(), $('#pass').val());
|
|
});
|
|
|
|
$('#sign').on('submit', function(e){
|
|
e.preventDefault();
|
|
user.auth($('#alias').val(), $('#pass').val());
|
|
});
|
|
|
|
gun.on('auth', function(){
|
|
$('#sign').hide();
|
|
$('#profile').show();
|
|
var pub = user._.sea.pub;
|
|
$('#pub').val(pub);
|
|
return;
|
|
$("#search").val(pub).trigger('blur');
|
|
});
|
|
|
|
$('#profile input').on('keyup', function(e){
|
|
if(!user.is){ return }
|
|
var id = LI.busy = $(this).attr('id');
|
|
user.get('profile').get(id).secret($(this).val());
|
|
}).on('blur', function(){ LI.busy = false })
|
|
|
|
$('#profile button').on('click', async function(e){
|
|
e.preventDefault();
|
|
if(!user.is){ return }
|
|
var b = $(this);
|
|
var id = b.prev().attr('id');
|
|
var pub = prompt("What is the Public Key or DID you want to give read access to?");
|
|
var to = gun.user(pub);
|
|
var who = await to.get('alias').then();
|
|
if(!confirm("You want to give access to " + who + "?")){ return }
|
|
user.get('profile').get(id).grant(to);
|
|
});
|
|
|
|
$('#search').on('blur', function(e){
|
|
var s = LI.search = $(this).val();
|
|
var find = gun.user(s);
|
|
find.get('profile').on(function(data, key, at, ev){
|
|
if(s !== LI.search){
|
|
ev.off();
|
|
return;
|
|
}
|
|
|
|
Gun.node.is(data, async (enc, id) => {
|
|
if (id === LI.busy) { return; }
|
|
|
|
const pair = user._.sea;
|
|
let key, val;
|
|
|
|
if (key =
|
|
await find.get('trust').get(pair.pub).get(id + 'profile').then()) {
|
|
const mix = await Gun.SEA.secret(await find.get('epub').then(), pair);
|
|
|
|
key = await Gun.SEA.decrypt(key, mix);
|
|
val = await Gun.SEA.decrypt(enc, key);
|
|
|
|
// decode encrypted data to show 'SEA{...}'
|
|
} else { val = JSON.parse(atob(enc)); }
|
|
|
|
$('#' + id).val(val);
|
|
});
|
|
});
|
|
});
|
|
</script> |