-
-
Save diatche/1ea348aa7b77f6edf5c92ba3f8470a67 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html><body> | |
<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> | |
<button id='revoke'>x</button> | |
</div> | |
</div> | |
<div class="box"><div class="pad"> | |
Public Key: <input id="pub"> | |
</div></div> | |
<script src="https://cdn.jsdelivr.net/npm/gun/examples/jquery.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/gun/lib/webrtc.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/gun/lib/open.js"></script> | |
<!-- <script src="../examples/jquery.js"></script> | |
<script src="../gun.js"></script> | |
<script src="../sea.js"></script> | |
<script src="../lib/open.js"></script> --> | |
<script> | |
//var gun = Gun(); | |
var gun = Gun({ | |
peers: ['http://localhost:8765/gun'], | |
localStorage: true, | |
multicast: true, | |
axe: true, | |
}); | |
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); | |
$("#search").val(pub).trigger('blur'); | |
console.log('auth: ' + pub); | |
}); | |
const updateTrustedValues = async (values) => { | |
let pair = user._.sea; | |
let trust = (await user.get('profile-trust3').then()) || {}; | |
for (let pub of Object.keys(trust)) { | |
if (pub === '_') continue; | |
let tuser = gun.user(pub); | |
let epub = await tuser.get('epub'); | |
if (!epub) continue; | |
let secret = await Gun.SEA.secret(epub, pair); | |
let encRef = user.get('profile-trust3').get(pub); | |
let encs = {}; | |
let currentEncs = await user.get('profile-trust3').get(pub).get('__keys').then(); | |
for (let key of Object.keys(values)) { | |
if (!currentEncs[key]) { | |
// Access to this key was not granted | |
continue; | |
} | |
let val = values[key]; | |
let enc = await Gun.SEA.encrypt(val, secret); | |
encs[key] = enc; | |
} | |
await encRef.put(encs); | |
let sharedData = await user.get('profile-trust3').get(pub).then(); | |
console.log('shared data: ' + JSON.stringify(sharedData, null, 2)); | |
} | |
}; | |
$('#profile input').on('keyup', function(e){ | |
if(!user.is){ return } | |
var id = LI.busy = $(this).attr('id'); | |
console.log("Huh?", id, user); | |
(async () => { | |
let pair = user._.sea; | |
let val = $(this).val(); | |
let enc = await Gun.SEA.encrypt(val, pair); | |
let data = await Gun.SEA.sign(enc, pair); | |
user.get('profile').get(id).put(data); | |
await updateTrustedValues({ [id]: 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?"); | |
if (!pub) { | |
return; | |
} | |
var to = gun.user(pub); | |
var who = await to.get('alias').then(); | |
if (!who) { | |
alert('user not found: ' + pub); | |
return; | |
} | |
if(!confirm("You want to give access to " + who + "?")){ return } | |
let epub = await to.get('epub').then(); | |
await user.get('profile-trust3').get(pub).get('__keys').put({ [id]: true }); | |
console.log(`Trusted user ${who} with epub: ${epub}`); | |
let sharedData = await user.get('profile-trust3').get(pub).then(); | |
console.log('shared data: ' + JSON.stringify(sharedData, null, 2)); | |
}); | |
const deepEmpty = async (ref) => { | |
let data = await ref.then(); | |
if (!data) return; | |
let keys = Object.keys(data); | |
let reset = {}; | |
for (let key of keys) { | |
if (key === '_') continue; | |
if (typeof data[key] === 'object') { | |
await deepEmpty(ref.get(key)); | |
continue; | |
} | |
reset[key] = ''; | |
} | |
ref.put(reset); | |
}; | |
$('#revoke').on('click', async function(e){ | |
e.preventDefault(); | |
if(!user.is){ return } | |
if(!confirm("You want to revoke all access?")){ return } | |
await deepEmpty(user.get('profile-trust3')); | |
console.log('unshared all data'); | |
}); | |
$('#search').on('blur', function(e){ | |
var s = LI.search = $(this).val(); | |
var find = gun.user(s); | |
(async () => { | |
var user = await find.then(); | |
if (!user) { | |
alert('user not found: ' + s); | |
} | |
})(); | |
if (find._.sea) { | |
// own values | |
find.get('profile').on(function(data, key, at, ev){ | |
if(s !== LI.search){ | |
ev.off(); | |
return; | |
} | |
Gun.node.is(data, async function(v, k){ | |
if(k === LI.busy){ return } | |
let val = v; | |
if (val && val.startsWith && val.startsWith('SEA')) { | |
let pair = user._.sea; | |
let msg = await Gun.SEA.verify(v, pair.pub); | |
val = await Gun.SEA.decrypt(msg, pair); | |
} | |
$('#'+k).val(val || v); | |
}); | |
}); | |
} else { | |
// other user's values | |
let pair = user._.sea; | |
find.get('profile-trust3').get(pair.pub).on(function(data, key, at, ev){ | |
if(s !== LI.search){ | |
ev.off(); | |
return; | |
} | |
Gun.node.is(data, async function(v, k){ | |
if(k === LI.busy){ return } | |
let val = v; | |
if (val && val.startsWith && val.startsWith('SEA')) { | |
let pair = user._.sea; | |
let epub = await find.get('epub'); | |
let secret = await Gun.SEA.secret(epub, pair); | |
val = await Gun.SEA.decrypt(val, secret); | |
} | |
$('#'+k).val(val || v); | |
// Try override other users data ^_^ | |
// find.get('profile-trust3').get(pair.pub).get(k).put('---'); | |
}); | |
}); | |
} | |
}); | |
</script> | |
</body></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment