Skip to content

Instantly share code, notes, and snippets.

@Lightnet
Last active September 26, 2019 06:00
Show Gist options
  • Save Lightnet/0776f3d51cc9a8c6869d4ef36ccbb345 to your computer and use it in GitHub Desktop.
Save Lightnet/0776f3d51cc9a8c6869d4ef36ccbb345 to your computer and use it in GitHub Desktop.
gunjstrustsharekey.js
//===============================================
// CLEAR GUN DATABASE
localStorage.clear();
//(function() {
//===============================================
// INIT GUN DATABASE
let gunurl = window.location.origin+'/gun';
//console.log(gunurl);
var gun = Gun(gunurl);
gun.on('hi', peer => {//peer connect
console.log('connect peer to',peer);
//console.log('peer connect!');
});
gun.on('bye', (peer)=>{// peer disconnect
console.log('disconnected from', peer);
//console.log('disconnected from peer!');
});
gun.get('mark').put({
name: "Mark",
email: "mark@gunDB.io",
});
let doc = document.getElementById('guntext');
gun.get('mark').on(function(data, key){
//console.log("update:", data);
doc.innerText = data.name;
});
//gun.get('~@test').map(function(data,key){//user
//console.log("data",data);
//});
const PERMISSIONS = [
{ name: "clipboard-read" },
{ name: "clipboard-write" }
];
/** Watch for pastes */
navigator.clipboard.addEventListener('clipboardchange', e => {
navigator.clipboard.getText().then( text => {
log('Updated clipboard contents: '+text)
})
});
//===============================================
// TESTING LOGIN / DO NOT USED PRODUCTION!
var users=[];
users.push({index:0,value:"beta",passphrase:"test"});
users.push({index:1,value:"alpha",passphrase:"test"});
users.push({index:1,value:"delta",passphrase:"test"});
users.push({index:2,value:"bbb",passphrase:"test"});
users.push({index:3,value:"test",passphrase:"test"});
$("#users").change(function(){
//console.log("selected");
let idx=$(this).val();
//console.log(idx);
if(users[idx]!=null){
$('#alias').val(users[idx].value);
$('#passphrase').val(users[idx].passphrase);
}
});
function addusers(index, data) {
//console.log("index",index);console.log("value",data);
$('#users').append($('<option/>', {
value: index,
text : data.value
}));
}
$.each(users,addusers);
//===============================================
// TEST GUN / USER
$("#btngun").click(async function(){
console.dir(Gun);
console.log(gun);
let user = gun.user();
let sec = await SEA.work("foo", "bar");
let mix = await SEA.encrypt("bar", sec);
mix = JSON.stringify(mix)
console.log(mix);
//gun.get('any'+user.is.pub+'graph').get('foo').put(mix);
gun.get(user.is.pub).get('foo').put(mix);
console.log(user.is.pub);
//gun.get('any'+user.is.pub+'graph').get('foo').once(ack=>{
//console.log(ack);
//});
gun.get(user.is.pub).get('foo').once((data,key)=>{
console.log(data);
});
//gun.get('~@test').once(ack=>{
//console.log(ack);
//});
});
$("#btnuser").click(function(){
let user = gun.user();
console.log(user);
});
function setClipboard(value) {
var tempInput = document.createElement("input");
tempInput.style = "position: absolute; left: -1000px; top: -1000px";
tempInput.value = value;
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
navigator.clipboard.writeText(value)
.then(() => {
// Success!
console.log("COPY IT?")
})
.catch(err => {
console.log('Something went wrong', err);
});
}
$("#aliaskeycopy").click(function(){
let user = gun.user();
if(!user.is)return;
//console.log(user.is.pub);
setClipboard(user.is.pub);
});
//===============================================
// LOGIN
$("#btnlogin").click(function(){
let user = gun.user();
user.auth($('#alias').val(), $('#passphrase').val(),(ack)=>{//user login username and password
if(ack.err){
console.log(ack.err);
modalmessage(ack.err);
}else{
//console.log(ack);
//modalmessage(ack);
$("#login").hide();
$("#profile").show();
selectactive("btnprofile");
//$("#messages").show();
//$("#publicchat").show();
//$("#privatechat").show();
$('#username').text($('#alias').val());
$('#aliaskeycopy').text("Alias:"+$('#alias').val()+" (Key Copy)");
user.get('profile').get('alias').decryptonce(ack=>{//get user profile alias key for value
//console.log(ack);
$('#inputalias').val(ack);
});
$('#aliaspublickey').val(ack.sea.pub);
updateContacts();
$("#navmenu").show();
}
});
});
$("#btnforgot").click(function(){
$('#login').hide();
$('#forgot').show();
});
//===============================================
// REGISTER
$("#btnregister").click(function(){
let user = gun.user();
user.create($('#alias').val(), $('#passphrase').val(),(ack)=>{//create user and password
if(ack.err){
console.log(ack.err);//if user exist or error
}else{
console.log(ack);//pass if created
modalmessage("Created " + $('#alias').val() + "!");
}
});
});
//===============================================
// FORGOT
$("#btnforgothint").click(async function(){
//let user = gun.user();
let alias = $('#falias').val();
alias = await gun.get('~@'+alias).then();//reused variable
if(!alias){//check user exist if not return false.
modalmessage('Not Found Alias!');
return;
}
let publickey;
for(let obj in alias){//object
//console.log(obj);
publickey = obj;//property name for public key
}
publickey = SEA.opt.pub(publickey);//check and convert to key or null?
//console.log(publickey);
let q1 = ($('#fquestion1').val() || '').trim(); //get id fquestion1 input
let q2 = ($('#fquestion2').val() || '').trim(); //get id fquestion2 input
if((!q1)||(!q2)){
//console.log('Q Empty!');
modalmessage('"Question (1 || 2) Empty!"');
return;
}
let to = gun.user(publickey);//get user alias graph
let hint = await to.get('hint').then();//get encrypt hint key graph
let dec = await Gun.SEA.work(q1,q2);//get fquestion1 and fquestion2 string to mix key
hint = await Gun.SEA.decrypt(hint,dec);//get hint and key decrypt message
//console.log(hint);
if(hint !=null){//check if hint is string or null
$('#fhint').val(hint);
}else{
modalmessage("Fail Decrypt!");
}
});
$("#btnbacklogin").click(function(){
$('#login').show();
$('#forgot').hide();
});
//===============================================
// PROFILE
$('#copypublickey').click(function(){//select input text and copy command to clipboard
$('#aliaspublickey').select();
document.execCommand('copy');
navigator.clipboard.writeText($('#aliaspublickey').val())
.then(() => {
// Success!
console.log("COPY IT?")
})
.catch(err => {
console.log('Something went wrong', err);
});
});
$("#inputalias").keyup(function() {
let aliasval = $("#inputalias").val();
//console.log(aliasval);
let user = gun.user();
user.get('profile').get('alias').encryptput($("#inputalias").val());
});
$("#getalias").click(function(){
let user = gun.user();
//user.get('profile').get('alias').decryptonce(ack=>{
//console.log(ack);
//});
user.get('profile').get('alias').once(ack=>{
console.log(ack);
});
});
$("#grantkey").click(async function(){
let user = gun.user();
let key = $('#accesskey').val();
if(key.length == 0){console.log("EMPTY!");return;}
let to = gun.user(key);
let who = await to.get('alias').then();
//console.log(who);
if(who != null){
console.log("PASS");
modalmessage("Grant access:" + who);
user.get('profile').get('alias').grantkey(to);//grant key
}else{
console.log("FAIL");
modalmessage("Grant access fail!");
}
});
$("#revokekey").click(async function(){
let user = gun.user();
let key = $('#accesskey').val();
if(key.length == 0){console.log("EMPTY!");return;}
let to = gun.user(key);
let who = await to.get('alias').then();
//console.log(who);
if(who != null){
console.log("PASS");
user.get('profile').get('alias').revokekey(to);//revoke key
modalmessage("Revoke access:" + who);
}else{
console.log("FAIL");
modalmessage("Revoke access fail!");
}
});
$("#trustkey").click(async function(){
let user = gun.user();
let key = $('#accesskey').val();
if(key.length == 0){console.log("EMPTY!");return;}
let to = gun.user(key);
let who = await to.get('alias').then();
//console.log(who);
if(who != null){
console.log("PASS");
user.get('profile').get('alias').trustkey(to);
}else{
console.log("FAIL");
}
});
$("#distrustkey").click(async function(){
let user = gun.user();
let key = $('#accesskey').val();
if(key.length == 0){console.log("EMPTY!");return;}
let to = gun.user(key);
let who = await to.get('alias').then();
//console.log(who);
if(who != null){
console.log("PASS");
user.get('profile').get('alias').distrustkey(to);
}else{
console.log("FAIL");
}
});
$("#trustlist").click(async function(){
let user = gun.user();
user.get('profile').get('alias').trustlist();
});
$("#putvalue").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
let keyvalue = $('#dataalias').val();// input text
keyvalue="helloworld";
console.log(keyvalue);
if(key.length == 0){console.log("EMPTY!");return;}
let to = gun.user(key);
let who = await to.get('alias').then();
//console.log(who);
if(who != null){
console.log("PASS");
to.get('profile').get('alias').encryptput(keyvalue);// encrypt value | data
}else{
console.log("FAIL");
}
});
//https://github.com/amark/gun/blob/master/lib/mix.js
$("#btnwriteput").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
let keyvalue = $('#sharewrite').val();// input text
if(!keyvalue){
console.log("empty!");
return;
}
let user = gun.user();
var seckey = await SEA.work("test", "test");
var msg = "test"
msg = keyvalue;
var enc = await SEA.encrypt(msg, seckey);
user.get('sharedata').get(user._.sea.pub).get('access').get('key').encryptput("RANDOMASDF");
});
$("#btnwriteget").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
let keyvalue = $('#dataalias').val();// input text
let user = gun.user();
var seckey = await SEA.work("test", "test");
let to = gun.user(key);
let who = await to.get('alias').then();
if((who != null)&&(keyvalue.length > 0)){
to.get('sharedata').get(key).get('profile').get('alias').once(async (ack)=>{
console.log(ack);
let data = await SEA.decrypt(ack, seckey);
console.log(data);
$("#sharewrite").val(data);
});
console.log("WHO",who);
}else{
user.get('sharedata').get(user._.sea.pub).get('access').get('key').decryptonce((ack)=>{
//console.log(ack);
//let data = await SEA.decrypt(ack, seckey);
//console.log(data);
$("#sharewrite").val(ack);
console.log(ack);
});
console.log("OWNER");
}
});
$("#btnsharetrustlist").click(async function(){
let user = gun.user();
user.get('sharedata').get(user._.sea.pub).get('access').get('key').trustlist();
});
$("#btnmap").click(async function(){
//console.log(Gun.text.random());
//let genid = Gun.text.random();
//gun.get('data').get(genid).put({name:"foo",foo:"bar"});
//gun.get(genid).put({name:"foo",foo:"bar"});
//function callback(data){
//console.log(data);
//}
//gun.get({'#': {'>': '*'}, '%': 50000}).map().once(callback)
//gun.get('data').get({'.': {'>': genid}}).map().once(callback)
//gun.get('data').get({'.': {'>': "FztS1VqZoZQUkjosL6oyDf3G"}}).map().once(callback)
//console.log(gun);
//gun.map().once(callback);
//Gun().put({foo: 'bar'});
//Gun().get('foo').once(ack=>{
//console.log(ack)
//});
});
$("#btnwriteputmix").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
let keyvalue = $('#sharewrite').val();// input text
//gun/lib/mix.js
//Gun.state.node = function(node, vertex, opt){
let user = gun.user();
let to = gun.user(key);
console.log("WRITE SHARE:")
let who = await to.get('alias').then();
console.log("who:",who)
if(who != null){
console.log("SET WRITE OWN");
//add user at ref owner sharekey for write to write own to ref update graph.
user.get('sharedata').get(key).get('access').get('key').put(keyvalue, function(ack){
console.log(ack);
});
}
});
$("#btnwritegetmix").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
//let keyvalue = $('#dataalias').val();// input text
//gun/lib/mix.js
//Gun.state.node = function(node, vertex, opt){
let user = gun.user();
let to = gun.user(key);
console.log("WRITE SHARE:")
let who = await to.get('alias').then();
console.log("who:",who)
if(who != null){
user.get('sharedata').get(key).get('access').get('key').once(function(ack){
console.log(ack);
});
}
});
$("#btngetlatestgraph").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
//let keyvalue = $('#dataalias').val();// input text
//gun/lib/mix.js
//Gun.state.node = function(node, vertex, opt){
let user = gun.user();
let to = gun.user(key);
console.log("WRITE SHARE:");
let who = await to.get('alias').then();
console.log("who:",who)
if((who != null)){
console.log("SET WRITE OWN");
//add user at ref owner sharekey for write to write own to ref update graph.
//user.get('sharedata').get(key).get('access').get('key').put("ASDF");
let rootpub = key;
let cat = {};
cat.idx = 0;
cat.count = 0;
cat.timegraph = 0;
cat.idgraph = 'key'; //graph key id
cat.datagraph;
//get graph path
let rootpath = to.get('sharedata').get(rootpub).get('access').get(cat.idgraph).graphpath();
//console.log("rootpath",rootpath);
let rootindex = await to.get('trust').get(rootpath).get('index').then();
cat.rootindex = rootindex - 1;
//cat.rootindex = rootindex;
//console.log("rootindex",rootindex);
//time different
//user.get('sharedata').get(rootpub).get('access').get(cat.idgraph).once(ack=>{
//console.log("FROM CURRENT USER ROOT!");
//console.log(ack);
//console.log("=======!");
//});
cat.ownpub=function(to){
console.log("list pubs");
to.get('trust').get(rootpath).once().map().once((d,k)=>{
cat.idx++;
//console.log(Gun.node.soul(key))
console.log(d);
//if(k != "index"){
cat.pub(k);
//}
})
}
cat.pub=async function(publickey){
console.log("pub: ", publickey);
let ref = gun.user(publickey);
let who = await ref.get('alias').then();
if(!who)return;
console.log("pub who:",who);
let keygraph = await ref.get('sharedata').get(rootpub).get('access').get('key').then();
console.log(keygraph);
//path for sharewrite
ref.get('sharedata').get(rootpub).get('access').on(function(data, key, at, ev){
ev.off();
console.log("data");
console.log(data);
//let bfound = false;
if( data['_']['>'][cat.idgraph] >= cat.timegraph){
cat.timegraph = data['_']['>'][cat.idgraph];
cat.datagraph = data[cat.idgraph];
console.log(cat.datagraph);
//bfound = true;
}
cat.check();
});
}
cat.check=function(){
cat.count++;
console.log("checking...");
console.log(`index: ${cat.idx}`);
console.log(`count: ${cat.count}`);
//if(cat.idx == cat.count){//check for loop.
//console.log("cat.datagraph");
//console.log(cat.datagraph);
//}
if(cat.rootindex == cat.count){
console.log("cat.datagraph");
console.log(cat.datagraph);
}
}
cat.ownpub(to);//call at to get latest graph id for value
}
});
$("#searchpublickeypaste").click(async function(){
$('#inputsearchpublickey').focus();
document.execCommand("paste");
navigator.permissions.query({name: "clipboard-write"}).then(result => {
console.log(result);
if (result.state == "granted" || result.state == "prompt") {
/* write to the clipboard now */
console.log("READ?");
navigator.clipboard.readText()
.then(text => {
//my code to handle paste
console.log(text);
$('#inputsearchpublickey').val(text);
})
.catch(err => {
console.error('Failed to read clipboard contents: ', err);
});
}
});
});
$("#btngrantaccess").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
//let keyvalue = $('#dataalias').val();// input text
//gun/lib/mix.js
//Gun.state.node = function(node, vertex, opt){
let user = gun.user();
let to = gun.user(key);
let who = await to.get('alias').then();
//console.log(who);
if(who != null){
console.log("PASS: GRANT ACCESS");
user.get('sharedata').get(user._.sea.pub).get('access').get('key').grantkey(to);
}else{
console.log("FAIL");
}
});
$("#btntrustaccess").click(async function(){
let key = $('#inputsearchpublickey').val(); //public key
//let keyvalue = $('#dataalias').val();// input text
//gun/lib/mix.js
//Gun.state.node = function(node, vertex, opt){
let user = gun.user();
let to = gun.user(key);
let who = await to.get('alias').then();
//console.log(who);
if(who != null){
console.log("PASS: WRITE ACCESS");
user.get('sharedata').get(user._.sea.pub).get('access').get('key').trustkey(to);
}else{
console.log("FAIL");
}
});
$("#accesskey").keyup(async function() {
let key = $('#accesskey').val();
if(key.length == 0){console.log("EMPTY!");return;}
let to = gun.user(key);
let who = await to.get('alias').then();
if(who != null){
$('#lookalias').text(who);
}
});
//===============================================
// SEARCH
$("#inputsearchpublickey").keyup(async function() {
let publickey = $("#inputsearchpublickey").val();
let to = gun.user(publickey);
if(publickey.length==0){console.log("NONE");return;}
let who = await to.get('alias').then();
if(!who){
who = "null";
}
$('#searchalias').text(' Alias: '+who);
to.get('profile').get('alias').decryptonce(ack=>{
console.log(ack)
$('#dataalias').val(ack);
},{sharetype:"user",sharekeytype:"path"})
});
//===============================================
// BUTTON NAV MENU
function hidediv(){
$("#profile").hide();
$("#changepassphrase").hide();
$("#passphrasehint").hide();
$("#messages").hide();
$("#publicchat").hide();
$("#privatechat").hide();
}
$('#btnprofile').click(function(){
hidediv();
$("#profile").show();
selectactive("btnprofile");
});
$('#btnchangepassphrase').click(function(){
hidediv();
$("#changepassphrase").show();
selectactive("btnchangepassphrase");
});
$('#btnpassphrase').click(function(){
hidediv();
$("#passphrasehint").show();
selectactive("btnpassphrase");
});
$('#btnmessage').click(function(){
hidediv();
$("#messages").show();
selectactive("btnmessage");
});
$('#btnpublicchat').click(function(){
hidediv();
InitChat();
$("#publicchat").show();
selectactive("btnpublicchat");
});
$('#btnprivatechat').click(function(){
hidediv();
$("#privatechat").show();
//initPrivateChat();
updateprivatechatlist();
selectactive("btnprivatechat");
});
var tabs=[]
tabs.push({id:"btnprofile"});
tabs.push({id:"btnchangepassphrase"});
tabs.push({id:"btnpassphrase"});
tabs.push({id:"btnmessage"});
tabs.push({id:"btnpublicchat"});
tabs.push({id:"btnprivatechat"});
function selectactive(tab){
for(let idx in tabs){
console.log(tab);
//$('#'+tabs[idx].id).removeClass("active");
if($('#'+tabs[idx].id).hasClass('active')){
$('#'+tabs[idx].id).removeClass("active");
break;
}
}
$('#'+tab).addClass("active");
}
//===============================================
// CHANGE PASSPHRASE
$('#btnchangepassphraseapply').click(function(){
let user = gun.user();
//console.log($('#oldpassphrase').val());console.log($('#newpassphrase').val());console.log("btnchangepassphraseapply");
user.auth(user.is.alias, $('#oldpassphrase').val(), (ack) => {//user auth call
//console.log(ack);
let status = ack.err || "Saved!";//check if there error else saved message.
console.log(status);
modalmessage(status);
}, {change: $('#newpassphrase').val()});//set config to change password
});
//===============================================
// PASSPHRASE HINT
$('#btnapplypassphrasehint').click(async function(){
//console.log($('#question1').val());console.log($('#question2').val());console.log($('#hint').val());console.log("btnapplypassphrase");
let user = gun.user();
let q1 = $('#question1').val(); //get input id question 1
let q2 = $('#question2').val(); //get input id question 2
let hint = $('#hint').val(); //get input id hint
let sec = await Gun.SEA.secret(user.is.epub, user._.sea);//mix key to decrypt
let enc_q1 = await Gun.SEA.encrypt(q1, sec);//encrypt q1
user.get('forgot').get('q1').put(enc_q1);//set hash q1 to user data store
let enc_q2 = await Gun.SEA.encrypt(q2, sec);//encrypt q1
user.get('forgot').get('q2').put(enc_q2); //set hash q2 to user data store
sec = await Gun.SEA.work(q1,q2);//encrypt key
//console.log(sec);
let enc = await Gun.SEA.encrypt(hint, sec);//encrypt hint
//console.log(enc);
user.get('hint').put(enc,ack=>{//set hash hint
//console.log(ack);
if(ack.err){
//console.log("Error!");
modalmessage(ack.err);
return;
}
if(ack.ok){
//console.log('Hint Apply!');
modalmessage('Hint Apply!');
}
});
});
$('#btngetpassphrasehint').click(async function(){
let user = gun.user();
let question1,question2,hint;
let sec = await Gun.SEA.secret(user.is.epub, user._.sea);//mix key to decrypt
question1 = await user.get('forgot').get('q1').then();
question1 = await Gun.SEA.decrypt(question1, sec);//decrypt question1
question2 = await user.get('forgot').get('q2').then();
question2 = await Gun.SEA.decrypt(question2, sec);//decrypt question2
$('#question1').val(question1);//set input text
$('#question2').val(question2);//set input text
sec = await Gun.SEA.work(question1,question2);//encrypt key
//console.log(sec);
hint = await user.get('hint').then();//get encrypt hint
hint = await Gun.SEA.decrypt(hint, sec);//decrypt hint
//console.log(hint);
$('#hint').val(hint);
});
//===============================================
// MESSAGES
$('#btnadduser').click(async function(){
let publickey = ($('#mpublickey').val() || '').trim();
if(!publickey){console.log("Public Key EMPTY!");return;}
let user = gun.user();
let to = gun.user(publickey);//get alias
let who = await to.then() || {};//get alias data
if(!who.alias){console.log("No Alias!");return;}
user.get("contacts").get(publickey).put({alias:who.alias});
updateContacts();
});
$('#btnremoveuser').click(async function(){
let publickey = ($('#mpublickey').val() || '').trim();
if(!publickey){console.log("Public Key EMPTY!");return;}
let user = gun.user();
let to = gun.user(publickey);//get alias
let who = await to.then() || {};//get alias data
if(!who.alias){console.log("No Alias!");return;}
user.get("contacts").get(publickey).put(null);
updateContacts();
});
function updateContacts(){
$('#usercontacts').empty();
$('#usercontacts').append($('<option selected disabled>-- Select User --</option>'));
let user = gun.user();
user.get("contacts").once().map().once(function(data,key){
//console.log("data",data);
//console.log("key",key);
if($("#" + key).length){
}else{
if(data !=null){
addusercontact(key, data);
}
}
});
console.log("update contacts");
}
function addusercontact(index, data) {
//console.log("index",index);console.log("value",data);
//console.log($("#" + index).length)
let bfound=false;
$("#usercontacts option").each(function(idx) {//loop option
if($(this).val() == index){//if key value exist
bfound=true;
return;
}
//$(this).siblings('[value="'+ val +'"]').remove();
});
if(!bfound){//if not found add option for user contacts
if($("#" + index).length){
console.log("NONE?")
}else{
$('#usercontacts').append($('<option/>', {
//id: index,
value: index,
text : data.alias
}));
}
}
}
$("#usercontacts").change(function(){
//console.log("selected");
let idx=$(this).val();
//console.log(idx);
$('#mpublickey').val(idx);
viewprivatemessages();
});
var messages=[];
var UIdec;
function CleanMessages(){
$('#messagelist').empty();
}
async function sendprivatemessage(){
let msg = ($('#inputmessagechat').val() || '').trim();
let publickey = ($('#mpublickey').val() || '').trim();
if(!msg){console.log("Message EMPTY!");return;}
if(!publickey){console.log("Public Key EMPTY!");return;}
let user = gun.user();
let to = gun.user(publickey);//get alias
let who = await to.then() || {};//get alias data
if(!who.alias){console.log("No Alias!");return;}
let sec = await Gun.SEA.secret(who.epub, user._.sea); // Diffie-Hellman
let enc = await Gun.SEA.encrypt(msg, sec); //encrypt message
user.get('messages').get(publickey).set(enc);
console.log("finish...");
}
async function viewprivatemessages(){
let user = gun.user();
if(!user.is){ return }//check if user exist
//messages = [];
CleanMessages();
let pub = ($('#mpublickey').val() || '').trim();
if(!pub) return;//check if not id empty
let to = gun.user(pub);//get alias
let who = await to.then() || {};//get alias data
if(!who.alias){
console.log("No Alias!");
$('#mwho').text("who?");
return;
}
$('#mwho').text(who.alias);
UIdec = await Gun.SEA.secret(who.epub, user._.sea); // Diffie-Hellman
user.get('messages').get(pub).map().once((data,id)=>{
UI(data,id,user.is.alias)
});
to.get('messages').get(user._.sea.pub).map().once((data,id)=>{
UI(data,id,who.alias)
});
}
async function UI(say, id, alias){
say = await Gun.SEA.decrypt(say, UIdec);
//messages.push({id:id,alias:alias,message:say});
if($("#" + id).length){
//console.log("found!?");
}else{
$('#messagelist').append($('<div/>', {
id: id,
text : alias + ": " + say
}));
}
let element = document.getElementById("messagelist");
element.scrollTop = element.scrollHeight;
}
$("#mpublickey").keyup(async function(e) {
viewprivatemessages();
})
$("#inputmessagechat").keyup(async function(e) {
//console.log(e);
//console.log($('#inputmessagechat').val());
if(e.key == "Enter"){
//console.log("Enter");
sendprivatemessage();
}
});
function MessagesResize(){
let height = $(window).height(); - $('#messages').offset().top;
//$('#messages').height(height);
$('#messages').css('height', height - 50);
//console.log(height);
//console.log($('#messages').offset().top);
height = $('#messages').height();
//console.log(height);
$('#messagelist').css('height', height - 44);
}
$(window).resize(function() {
MessagesResize();
});
MessagesResize();
//===============================================
// PUBLIC CHAT
var gunchat;
function timestamp(){
let currentDate = new Date();
//console.log(currentDate);
let year = currentDate.getFullYear();
let month = ("0" + (currentDate.getMonth() + 1 ) ).slice(-2);
let date = ("0" +currentDate.getDate()).slice(-2);
let hour = ("0" +currentDate.getHours()).slice(-2);
let minute = ("0" +currentDate.getMinutes()).slice(-2);
let second = ("0" +currentDate.getSeconds()).slice(-2);
let millisecond = currentDate.getMilliseconds();
return year + "/" + (month) + "/" + date + ":" + hour+ ":" + minute+ ":" + second+ ":" + millisecond;
}
function scrollPublicMessage(){
let element = document.getElementById("publicchatlist");
element.scrollTop = element.scrollHeight;
}
$("#inputpublicchat").keyup(async function(e) {
if(e.key == "Enter"){
//console.log("Enter");
let user = gun.user();
if(!user.is){ return }//check if user exist
let msg = ($('#inputpublicchat').val() || '').trim();
if(!msg) return;//check if not id empty
let encmsg = await SEA.work("public","chat");//encrypttion key default?
//console.log(encmsg);
let enc = await SEA.encrypt(msg,encmsg);
//console.log(enc);
let who = await user.get('alias').then();
//console.log(who);
//console.log(typeof enc)
enc = window.btoa(enc);
gun.get('chat').get(timestamp()).put({
alias:who,
message:enc
});
console.log("send message...");
}
});
//https://gun.eco/docs/RAD
async function InitChat(){
console.log("Init Chat...")
$('#publicchatlist').empty();
let encmsg = await SEA.work("public","chat"); //encrypttion key default?
async function qcallback(data,key){
console.log('incoming messages...')
//console.log("key",key);
console.log("data",data);
if(data == null)return;
if(data.message != null){
let message = window.atob(data.message);
//console.log(message);
let dec = await SEA.decrypt(message,encmsg);
//console.log(dec)
if(dec!=null){
$('#publicchatlist').append($('<div/>', {
id: key,
text : data.alias + ": " + dec
}));
scrollPublicMessage();
}
}
}
let currentDate = new Date();
let year = currentDate.getFullYear();
let month = ("0" + (currentDate.getMonth() + 1 ) ).slice(-2);
let date = ("0" +currentDate.getDate()).slice(-2);
let timestring = year + "/" + month + "/" + date + ":";
console.log(timestring);
if(gunchat !=null){
gunchat.off()
}
gunchat = gun.get('chat');
//gunchat.get({'.': {'*': '2019/08/'}}).map().once(qcallback);
//gunchat.get({'.': {'*': timestring}}).map().once(qcallback);
gunchat.get({'.': {'*': timestring},'%': 50000}).map().once(qcallback);
}
function PublicChatResize(){
let height = $(window).height(); - $('#publicchat').offset().top;
$('#publicchat').css('height', height - 50);
height = $('#publicchat').height();
$('#publicchatlist').css('height', height - 44);
}
$(window).resize(function() {
PublicChatResize();
});
PublicChatResize();
//===============================================
// PRIVATE CHAT
var privatechatkey="";
var gunprivatechat;
var privatesharekey="";
function CleanPrivateChatMessages(){
$('#privatechatlist').empty();
}
function scrollPrivateMessage(){
let element = document.getElementById("privatechatlist");
element.scrollTop = element.scrollHeight;
}
function PrivateChatResize(){
let height = $(window).height(); - $('#privatechat').offset().top;
$('#privatechat').css('height', height - 50);
height = $('#privatechat').height();
$('#privatechatlist').css('height', height - 44);
}
$(window).resize(function() {
PrivateChatResize();
});
PrivateChatResize();
$("#inputprivatechat").keyup(async function(e) {
if(e.key == "Enter"){
//console.log("Enter");
let user = gun.user();
if(!user.is){ return }//check if user exist
let msg = ($('#inputprivatechat').val() || '').trim();
if(!msg) return;//check if not id empty
let who = await user.get('alias').then();
if(gunprivatechat !=null){
let enc = await SEA.encrypt(msg, privatesharekey);
enc = window.btoa(enc);//gun graph need to be string not SEA{} that will reject that is not soul of user
gunprivatechat.get('message').get(timestamp()).put({
alias:who,
message:enc
});
}
console.log("send private chat...");
}
});
async function initPrivateChat(){
//updateprivatechatlist();
CleanPrivateChatMessages();
let privatekey = ($('#privatechatkey').val() || "").trim();
if(!privatekey)return;
console.log("init chat...");
//Need to fail checks!
console.log(privatekey);
privatechatkey = privatekey;
let user = gun.user();
let pair = user._.sea;
//GET ENC SHARE KEY
let pub = await gun.get(privatechatkey).get('info').get('pub').then();
let title = await gun.get(privatechatkey).get('info').get('name').then();
if(pub == user.is.pub){
$('#ppublickey').show();
$('#btnprivatechatgrant').show();
$('#btnprivatechatrevoke').show();
}else{
$('#ppublickey').hide();
$('#btnprivatechatgrant').hide();
$('#btnprivatechatrevoke').hide();
}
$('#btnprivatechatcreate').hide();
$('#privatechatroom').hide();
$('#privatechatkey').hide();
$('#btnprivatechatjoin').hide();
$('#btnprivatechatleave').show();
$('#btnprivatechatadd').hide();
$('#btnprivatechatremove').hide();
$('#btnprivatechatname').text(title);
let to = gun.user(pub);
let epub =await to.get('epub').then();
let encsharekey = await to.get('privatechatroom').get(privatechatkey).get('pub').get(pair.pub).then();
console.log(encsharekey);
//let dh = await SEA.secret(pair.epub, pair);
let dh = await SEA.secret(epub, pair);
let dec = await SEA.decrypt(encsharekey, dh);
console.log(dec);
if(dec==null){
console.log("NULL SHARE KEY!");
return;
}
privatesharekey = dec;
if(gunprivatechat !=null){
gunprivatechat.off();
}
gunprivatechat = gun.get(privatekey);
let currentDate = new Date();
let year = currentDate.getFullYear();
let month = ("0" + (currentDate.getMonth() + 1 ) ).slice(-2);
let date = ("0" +currentDate.getDate()).slice(-2);
let timestring = year + "/" + month + "/" + date + ":";
async function qcallback(data,key){
console.log('incoming messages...')
//console.log("key",key);
//console.log("data",data);
if(data == null)return;
if(data.message != null){
let message = window.atob(data.message);
let decmsg = await SEA.decrypt(message,privatesharekey);
if(decmsg!=null){
$('#privatechatlist').append($('<div/>', {
id: key,
text : data.alias + ": " + decmsg
}));
scrollPrivateMessage();
}
}
}
gunprivatechat.get('message').get({'.': {'*': timestring},'%': 50000}).map().once(qcallback);
}
function leavePrivateChatRoom(){
$('#btnprivatechatjoin').show(); //Show Enter Room
$('#btnprivatechatleave').hide(); //Hide Leave Room
$('#ppublickey').hide(); //public key
$('#btnprivatechatgrant').hide(); //Grant
$('#btnprivatechatrevoke').hide(); //Revoke
$('#btnprivatechatcreate').show(); // Create Room
$('#privatechatroom').show(); // Rooms
$('#privatechatkey').show(); // Show Input Private Key
$('#btnprivatechatadd').show(); //show button add private room
$('#btnprivatechatremove').show(); // show button remove private room
$('#btnprivatechatname').text(" key? ");
if(gunprivatechat !=null){
gunprivatechat.off();
gunprivatechat=null;
}
privatesharekey="";
}
async function addPrivateChat(index, data){
let user = gun.user();
console.log("add chat room list");
console.log(index);
console.log(data);
let name = await user.get('privatechatroom').get(index).get('info').get('name').then();
$('#privatechatroom').append($('<option/>', {
//id: index,
value: index,
text : name
}));
}
function updateprivatechatlist(){
$('#privatechatroom').empty();
$('#privatechatroom').append($('<option selected disabled> -- Select Private Chat -- </option>'));
let user = gun.user();
user.get('privatechatroom').once().map().once(function(data,key){
if(data !=null){
addPrivateChat(key,data);
}
});
}
$('#btnprivatechatcreate').click(async function(){
console.log("btnprivatechatcreate");
let user = gun.user();// get user graph
let pair = user._.sea;//user pair
let genprivatechatid = Gun.text.random();//random string
let gensharekey = Gun.text.random();//random string
let pname = "private chat "+genprivatechatid;//id name
let pdescription= "private chat";//id description
let enc = await SEA.encrypt(gensharekey, pair);//encode key
user.get('privatechatroom')
.get(genprivatechatid).get('pri').put(enc);
let dh = await SEA.secret(pair.epub, pair);
enc = await SEA.encrypt(gensharekey, dh);
user.get('privatechatroom')
.get(genprivatechatid).get('pub').get(pair.pub).put(enc);
user.get('privatechatroom')
.get(genprivatechatid)
.get('info')
.put({
pub:pair.pub,
name:pname,
description:pdescription,
date:timestamp()
});
gun.get(genprivatechatid)
.get('info')
.put({
pub:pair.pub,
name:pname,
description:pdescription,
date:timestamp()
});
});
$('#btnprivatechatjoin').click(function(){
console.log("btnprivatechatjoin");
initPrivateChat();
});
$('#btnprivatechatleave').click(function(){
console.log("btnprivatechatleave");
leavePrivateChatRoom();
});
$('#btnprivatechatadd').click(async function(){
console.log("btnprivatechatadd");
let user = gun.user();
if(!user.is)return;
let privatekey = ($('#privatechatkey').val() || "").trim() ;
if(!privatekey)return;
let gkey = await gun.get(privatekey).then();
//console.log(gkey);
if(gkey == undefined){
console.log("NOT FOUND!");
return;
}
let guninfo = gun.get(privatekey).get('info');
let pub = await guninfo.get('pub').then();
let title = await guninfo.get('name').then();
let description = await guninfo.get('description').then();
let date = await guninfo.get('date').then();
//console.log(pub);console.log(title);console.log(date);
user.get('privatechatroom').get(privatekey).get('info').put({
pub:pub,
name: title,
description:description,
date:date
});
});
$('#btnprivatechatremove').click(async function(){
console.log("btnprivatechatremove");
let user = gun.user();
if(!user.is)return;
let privatekey = ($('#privatechatkey').val() || "").trim();
if(!privatekey)return;
let gkey = await gun.get(privatekey).then();
if(gkey == undefined){
console.log("NOT FOUND!");
return;
}
user.get('privatechatroom').get(privatekey).put(null);
});
$('#btnprivatechatgrant').click(async function(){
console.log("btnprivatechatgrant");
let ppublickey = ($('#ppublickey').val() || "").trim();
if(!ppublickey)return;
let pkey = (privatesharekey || "").trim();
//check user pub key owner
let pownid = await gun.get(privatechatkey).get('info').get('pub').then();
//console.log(pownid);console.log(ppublickey);
if(pownid == ppublickey){
console.log("owner");
return;
}
let user = gun.user();
let pair = user._.sea;
let to = gun.user(ppublickey);
let who = await to.get('alias').then();
if(!who)return;
if(!pkey)return;
let pub = await to.get('pub').then();
let epub = await to.get('epub').then();
let dh = await SEA.secret(epub, pair);
let enc = await SEA.encrypt(pkey, dh);
user.get('privatechatroom')
.get(privatechatkey)
.get('pub')
.get(pub).put(enc);
console.log(pkey);
console.log("finish grant!");
});
$('#btnprivatechatrevoke').click(async function(){
console.log("btnprivatechatrevoke");
let ppublickey = ($('#ppublickey').val() || "").trim();
if(!ppublickey)return;
let pkey = (privatesharekey || "").trim();
//check user pub key owner
let pownid = await gun.get(privatechatkey).get('info').get('pub').then();
if(pownid == ppublickey){
console.log("owner");
return;
}
let user = gun.user();
let pair = user._.sea;
let to = gun.user(ppublickey);
let who = await to.get('alias').then();
if(!who)return;
if(!pkey)return;
//need to generate new share key
//user.get('privatechatroom')
//.get(privatechatkey)
//.get('pub').map().once(function(data,key){});
let pub = await to.get('pub').then();
user.get('privatechatroom')
.get(privatechatkey)
.get('pub')
.get(pub).put(null);
console.log(pkey);
console.log("finish revoke!");
});
$('#privatechatroom').change(function(){
//console.log("privatechatroom");
let idx=$(this).val();
//console.log(idx);
$('#privatechatkey').val(idx);
});
//===============================================
// DIALOG MESSAGE
function modalmessage(_text){
$("#dialogmessage").text(_text);
$("#Modal").show();
}
$('#btndialogokay').click(function(){
//console.log("dialog hide");
$("#Modal").hide();
});
$('#btnshowmodal').click(function(){
//console.log("dialog hide");
$("#Modal").show();
});
//===============================================
// SETUP
hidediv();
$("#navmenu").hide();
$("#forgot").hide();
$('#ppublickey').hide();
$('#btnprivatechatgrant').hide();
$('#btnprivatechatrevoke').hide();
$('#btnprivatechatleave').hide();
//}());
/*
Self contain Sandbox Gun Module chain for auth sea.js:
Created by: Lightnet
License: MIT
Version: 3.0
Last Update:2019.09.19
Credit: amark ( https://github.com/amark/gun)
Status(Work in progress!):
* Working on trust public key will conflict with share key functions!
* Work in progress to test dis/trust public key.
* encryptput not working to...get(...).encryptput() NO! Mismatched owner on 'ct'.
Information: This is addon chain to sea.js for user to test functions of acess write and read
in encryption. It is base on sea.js user functions that is current not improve yet.
Gun functions:
* trustkey(to, cb, opt) - writable: allow, public key (wip)
* distrustkey(to, cb, opt) - writable: denied, public key (wip)
* grantkey(to, cb, opt) - readable: allow, share key (working for user root)
* revokekey(to, cb, opt) - readable: denied, share key (working for user root / wip trust key)
* encryptput(data, cb, opt) - encrypt: value (working for user root / wip trust key)
* decryptonce( cb, opt) - decrypt: value (working for user root / wip trust key)
dis/trustkey:
The owner user key graph to dis/allow for other users write access of the value or data.
The writable key user public key is store in put(data | value)
Example:
gun.get('namespace').get('foo').put({SEA{ct:"",iv:"",s:""},~@publickey1,~@publickey2}); //does not work
Example put:(wip might not work)
* sea: "SEA{ct: "...",iv: "...",s: "..."}}"
* ~@publickey1:{'#': ~@publickey1}
* ~@publickey2:{'#': ~@publickey2}
* _:{...}
To create public key map list that is to need encrypt data and then alias list.
Note:
* This part of sea.js function security call/filter check for sea key and alias public keys.
* This base on understanding of security node checks.
grantkey/revokekey:
To able to dis/allow user share key access to read data. The share key are store in user trust map key and path.
Gun Notes:
* sea.js and gun.js are buggy with auth checks.
* There is a bug in gun.user('publickey') will return as gun not user object.
*/
(function() {
var Gun = (typeof window !== "undefined")? window.Gun : require('gun/gun');
Gun.on('opt', function(context) {
context.opt.sharekeydebug = true;
context.opt.sharekeyvalue = 'value';
context.opt.sharekeytrust = 'trust';
context.opt.sharekeybbase = true; //btoa, atob //base64 ecode and decode
this.to.next(context);
});
function trustlist(cb, opt){
console.log("`.trustlist` PROTOTYPE API DO NOT USE, TESTING!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
(async function(){
//make sure that user root
if(sharetype == "user"){
//let data = await gun.then();
//console.log(data);
//let index = 0;
user.get('trust').get(path).once().map().once(async (data,key)=>{
//index++;
//console.log("trust");
//console.log("data",data);
//console.log("key",key);
let to = gun.user(key);
let who = await to.get('alias').then();
console.log("who: ", who);
//Gun.node.is(data, async function(v, k){
//console.log(v)
//console.log(k)
//});
//user.get('trust').get(path).get('index').put(index);
//console.log(index);
});
}
//if(sharetype == "gun"){}
}());
return gun;
}
function trustindex(cb, opt){
console.log("`.trustlist` PROTOTYPE API DO NOT USE, TESTING!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
(async function(){
//make sure that user root
if(sharetype == "user"){
let index = await user.get('trust').get(path).get('index').then();
return index;
}else{
return null;
}
}());
}
function trustkey(to, cb, opt){
console.log("`.trustkey` PROTOTYPE API MAY BE CHANGED OR RENAMED USE!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
//let debug = opt.debug || gun._.root.opt.sharekeydebug;
//let valueid = opt.valueid || gun._.root.opt.sharekeyvalue;
//let trustid = opt.trustid || gun._.root.opt.sharekeytrust;
//let bbase = opt.bbase || gun._.root.opt.sharekeybbase;
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
let each = {};
(async function(){
if(sharetype == "user"){
//console.log(gun);
//sea.js
//line 792
//root.get(tmp = '~'+act.pair.pub).put(act.data); // awesome, now we can actually save the user with their public key as their ID.
//root.get('~@'+alias).put(Gun.obj.put({}, tmp, Gun.val.link.ify(tmp))); // next up, we want to associate the alias with the public key. So we add it to the alias list.
//let tmp = '~'+pair.pub;
//tmp = Gun.val.link.ify(tmp);
//tmp = Gun.obj.put({}, tmp, Gun.val.link.ify(tmp));
//console.log(tmp);
let who = await to.get('alias').then();
if(who!=null){
let pub = await to.get('pub').then();
user.get('trust').get(path).get(pub).put({write:true},ack=>{
console.log("trust");
console.log(ack);
});
//note this might break code if there take long if more then 100 alias users
//update sync error not working.
//if other user has not added key value will not work
let index = 0;
user.get('trust').get(path).once().map().once((data,key)=>{
index++;
user.get('trust').get(path).get('index').put(index);
console.log(index);
});
console.log("done!");
}
}
//if(sharetype == "gun"){}
}());
return gun;
}
function distrustkey(to, cb, opt){
console.log("`.distrustkey` PROTOTYPE API MAY BE CHANGED OR RENAMED USE!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
let debug = opt.debug || gun._.root.opt.sharekeydebug;
let valueid = opt.valueid || gun._.root.opt.sharekeyvalue;
let trustid = opt.trustid || gun._.root.opt.sharekeytrust;
let bbase = opt.bbase || gun._.root.opt.sharekeybbase;
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
let each = {};
(async function(){
if(sharetype == "user"){
let who = await to.get('alias').then();
if(who!=null){
console.log("FOUND!",who);
let pub = await to.get('pub').then();
user.get('trust').get(path).get(pub).put({write:false},ack=>{
console.log("trust");
console.log(ack);
});
}
}
if(sharetype == "gun"){
}
}());
return gun;
}
function grantkey(to, cb, opt){
console.log("`.grantkey` PROTOTYPE API MAY BE CHANGED OR RENAMED USE!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
//let debug = opt.debug || gun._.root.opt.sharekeydebug;
//let valueid = opt.valueid || gun._.root.opt.sharekeyvalue;
//let trustid = opt.trustid || gun._.root.opt.sharekeytrust;
//let bbase = opt.bbase || gun._.root.opt.sharekeybbase;
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
(async function(){
if(sharetype == "user"){
let enc, sec = await user.get('grant').get(pair.pub).get(path).then();
sec = await SEA.decrypt(sec, pair);
if(!sec){
sec = SEA.random(16).toString();
//sec = Gun.text.random(16);
enc = await SEA.encrypt(sec, pair);
user.get('grant').get(pair.pub).get(path).put(enc);
}
let pub = await to.get('pub').then();
let epub = await to.get('epub').then();
pub = await pub; epub = await epub;
let dh = await SEA.secret(epub, pair);
enc = await SEA.encrypt(sec, dh);
user.get('grant').get(pub).get(path).put(enc, cb);
}
}());
return gun;
}
function revokekey(to, cb, opt){
console.log("`.revokekey` PROTOTYPE API MAY BE CHANGED OR RENAMED USE!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
//let debug = opt.debug || gun._.root.opt.sharekeydebug;
//let valueid = opt.valueid || gun._.root.opt.sharekeyvalue;
//let trustid = opt.trustid || gun._.root.opt.sharekeytrust;
//let bbase = opt.bbase || gun._.root.opt.sharekeybbase;
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
(async function(){
if(sharetype == "user"){
let alias = await to.get("alias").then();
if(!alias){
cb({err:'Error alias not found!'});
return gun;
}
let enc, sec;
sec = await user.get('grant').get(pair.pub).get(path).then();
sec = await SEA.decrypt(sec, pair);
let key = await gun.once().then();
//GET VALUE
let value = await SEA.decrypt(key, sec);
// CREATE SHARE KEY
sec = SEA.random(16).toString();
//sec = Gun.text.random(16);
enc = await SEA.encrypt(sec, pair);
//ENCRYPT KEY
user.get('grant').get(pair.pub).get(path).put(enc);
let pub = await to.get('pub').then();
console.log("pub",pub);
console.log("path: ",path)
user.get('grant').once().map().once(async (data,mkey)=>{//grant users
//console.log(data)
//let p = await user.get('grant').get(mkey).then();
//console.log(p)
let uname;
uname = await gun.back(-1).user(mkey).get('alias').then();
//console.log("mkey",mkey);
uname = await gun.back(-1).user(mkey).get('alias').then();
if(pair.pub != mkey){//check self user to be resalt
if(pub == mkey){ //check user to be revoke
//do nothing??? (revoke user)
console.log(uname, "REVOKE USER!");
}else{
console.log(uname, "PASS");
//let op = await user.get('trust').get(mkey).then();
//for (var p in op) {
//console.log(p);
//}
let ckey = await user.get('grant').get(mkey).get(path).then();
if(ckey != "null"){//Check if there user are revoke key if they are null should be ignore.
//console.log(uname, "CREATE NEW SALT SHARE KEY ");
let mto = gun.back(-1).user(mkey);
let mpub = await mto.get('pub').then();
let mepub = await mto.get('epub').then();
let dh = await SEA.secret(mepub, pair);
let menc = await SEA.encrypt(sec, dh);
//NEW SALT KEY
//console.log( uname,"NEW SHARE KEY: ",menc);
user.get('grant').get(mpub).get(path).put(menc);
}
}
}
});
//ENCRYPT VALUE
let v = await SEA.encrypt(value, sec);
gun.put(v, cb);
// Remove Salt Key
//let pub = await to.get('pub').then();
user.get('grant').get(pub).get(path).put("null", cb);//remove key
}
}());
return gun;
}
function encryptput(data, cb, opt){
console.log("`.encryptput` PROTOTYPE API MAY BE CHANGED OR RENAMED USE!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
//let debug = opt.debug || gun._.root.opt.sharekeydebug;
//let valueid = opt.valueid || gun._.root.opt.sharekeyvalue;
//let trustid = opt.trustid || gun._.root.opt.sharekeytrust;
//let bbase = opt.bbase || gun._.root.opt.sharekeybbase;
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
(async function(){
let enc, sec;
console.log(gun);
if(sharetype == "user"){
sec = await user.get('grant').get(pair.pub).get(path).then();
sec = await SEA.decrypt(sec, pair);
//console.log(sec);
if(!sec){
console.log("CREATE SHARE KEY!");
sec = SEA.random(16).toString();
//sec = Gun.text.random(16);
enc = await SEA.encrypt(sec, pair);
user.get('grant').get(pair.pub).get(path).put(enc);
}
enc = await SEA.encrypt(data, sec);
let enc2 = await gun.then();
// value enc and public keys from current gun graph
//need to be convert into array not string 'SEA{...}' > {...}
let tmpp=enc;//json object
//tmpp=
//for(o in enc2){
//if("~" == o.slice(0,1)){
//console.log("FOUND PUB KEY");
//let tmppub = o;
//console.log(tmppub);
//tmpp = Gun.obj.put(tmpp, tmppub, Gun.val.link.ify(tmppub))
//console.log(tmpp);
//}
//}
gun.put(tmpp, cb);
//console.log("enc",enc);
//gun.put(enc, cb);
}
//if user is not root graph
if(sharetype == "gun"){
let countmax = 10;//limit back to root loop
let root;
for(let i=0;i<countmax;i++){//look for user soul root from let to = gun.user('key');
let tmp = gun.back(i);//loop to find user root
if(tmp._.soul){
console.log("FOUND SOUL!");
root = tmp;
break;
}
}
if(root !=null){
let to = root;//user root graph
let enc1 = await to.get('grant').get(pair.pub).get(path).then();
let epub = await to.get('epub').then();
let mix = await SEA.secret(epub, pair);
let key = await SEA.decrypt(enc1, mix);//SECRET
//console.log(key);
//GET VALUE AND SHARE KEYS
let enc2 = await gun.then();
console.log(enc2);
//ENCRYPT VALUE
let enc3 = await SEA.encrypt(data, key);
console.log(enc3);
let enc0 = enc3;
console.log(enc0);
//enc0 = tmpp;
//gun.back().get('any'+user._.sea.pub+'alias').put(enc0);
//gun.back().get('alias').put(enc0);
gun.put(enc0, cb);
//gun.put(enc, cb);
}
}
}());
return gun;
}
function graphpath( cb, opt){
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
//(async function(){
//}());
//return gun;
return path;
}
function decryptonce( cb, opt){
console.log("`.decryptonce` PROTOTYPE API MAY BE CHANGED OR RENAMED USE!");
cb = cb || function(ctx) { return ctx };
opt = opt || {};
let gun = this, user = gun.back(-1).user(), pair = user._.sea, path = '';
//console.log(user);
gun.back(function(at){ if(at.is){ return } path += (at.get||'') });
//let debug = opt.debug || gun._.root.opt.sharekeydebug;
//let valueid = opt.valueid || gun._.root.opt.sharekeyvalue;
//let trustid = opt.trustid || gun._.root.opt.sharekeytrust;
//let bbase = opt.bbase || gun._.root.opt.sharekeybbase;
let sharetype;
if (gun._.$ instanceof Gun.User){//check gun node is user object
sharetype = "user";
}else{
sharetype = "gun";
}
(async function(){
//console.log(sharetype);
if(sharetype == "user"){
let sec = await user.get('grant').get(pair.pub).get(path).then();
sec = await SEA.decrypt(sec, pair);
let key = await gun.then();
//console.log(key);
if(key === undefined){
//console.log("FOUND NULL");
cb(undefined);
return gun;
}
//if(key.sea === undefined){
//cb(undefined);
//return gun;
//}
//key = key.sea;//TESTING....
let value = await SEA.decrypt(key, sec);
cb(value);
}
//console.log(gun);
if(sharetype == "gun"){
//console.log(gun);
let countmax = 10;
let root;
//need to work this fixed later
for(let i=0;i<countmax;i++){//look for user soul root from let to = gun.user('key');
let tmp = gun.back(i);//loop to find user root
if(tmp._.soul){
console.log("FOUND SOUL!");
root = tmp;
break;
}
}
if('~' === root._.soul.slice(0,1)){//public key
//let soul;// = root._.soul.slice(0,1);
//console.log(SEA.opt.pub(root._.soul));
//soul=SEA.opt.pub(root._.soul);
//let to = gun.user(soul);
let to = root;//user root graph
let enc1 = await to.get('grant').get(pair.pub).get(path).then();
let epub = await to.get('epub').then();
let mix = await SEA.secret(epub, pair);
let key = await SEA.decrypt(enc1, mix);
//console.log(key);
let enc2 = await gun.then();
if(enc2 === undefined){
//console.log("FOUND NULL");
cb(undefined);
return gun;
}
//if(enc2.sea === undefined){
//cb(undefined);
//return gun;
//}
//console.log(enc2);
//enc2 = enc2.sea;//TESTING....
console.log(enc2);
//enc2 = "SEA"+ JSON.stringify(enc2);
let value = await SEA.decrypt(enc2, key);
//console.log(value);
cb(value);
}
}
}());
return gun;
}
//SETUP FUNCTION for GUN
Gun.chain.trustkey = trustkey;
Gun.chain.distrustkey = distrustkey;
Gun.chain.grantkey = grantkey;
Gun.chain.revokekey = revokekey;
Gun.chain.encryptput = encryptput;
Gun.chain.decryptonce = decryptonce;
//TESTING...
Gun.chain.trustlist = trustlist;
Gun.chain.trustindex = trustindex;
Gun.chain.graphpath = graphpath;
}());
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta name="description" content="">
<!--<link id="favicon" rel="icon" href="" type="image/x-icon">-->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- import the webpage's stylesheet -->
<link rel="stylesheet" href="/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/lib/mix.js"></script>
<!-- RAD/LEX -->
<script src="https://cdn.jsdelivr.net/npm/gun/lib/radix.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/lib/radisk.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/lib/store.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gun/lib/rindexed.js"></script>
<!--<script src="https://cdn.jsdelivr.net/npm/gun/lib/then.js"></script>-->
<script src="/gunjstrustsharekeyv3.js"></script>
<script src="/sea.js"></script>
<!--
<script src="https://cdn.jsdelivr.net/npm/gun/sea.js"></script>
<script src="/gunadapter.js"></script>
-->
</head>
<body>
<label>Nodejs http with Gun.js</label>
<label id="guntext">...</label>
<button id="btngun">Gun</button>
<button id="btnuser">User</button>
<button id="aliaskeycopy"> Alias: Unknown </button>
<!--<button id="btnshowmodal">Modal</button>-->
<div id="navmenu">
<button id="btnprofile"> Profile </button>
<button id="btnchangepassphrase"> Change Passphrase </button>
<button id="btnpassphrase"> Passphrase Hint </button>
<button id="btnmessage"> Messages </button>
<button id="btnpublicchat"> Public Chat </button>
<button id="btnprivatechat"> Private Chat </button>
</div>
<div id="login">
<select id="users">
<option selected="true" disabled>-- Select User! --</option>
</select>
Alias:<input id="alias" value="test" />
Passphrase:<input id="passphrase" value="test" />
<button id="btnlogin">Login</button>
<button id="btnforgot">Forgot</button>
<button id="btnregister">Register</button>
</div>
<div id="forgot">
Alias:<input id="falias" placeholder="username" />
<br>Question 1:<input id="fquestion1" value="" placeholder="question #1"/>
<br>Question 2:<input id="fquestion2" value="" placeholder="question #2"/>
<br>Hint:<input id="fhint" value="" placeholder="passphrase hint"/>
<br><button id="btnforgothint">Get Hint</button>
<button id="btnbacklogin">Cancel</button>
</div>
<div id="profile">
Public Key: <input id="aliaspublickey" readonly size="90"><button id="copypublickey">Copy</button>
<br>Profile:<label id="username"></label>
<br>
<br>Access Public Key: <input id="accesskey" placeholder="public key" size="90"/> <label id="lookalias">None</label>
<br>Alias: <input id="inputalias" placeholder="value"/>
<button id="getalias"> Get Value </button>
<button id="grantkey"> Grant (share key) </button>
<button id="revokekey"> Revoke (share key) </button>
<button id="trustkey"> Trust (pub key) </button>
<button id="distrustkey"> Distrust (pub key) </button>
<button id="trustlist"> trust list (pub key) </button>
<br>
<br> Search Public Key:
<br> <input id="inputsearchpublickey" placeholder="public key"/><button id="searchpublickeypaste">Paste</button><label id="searchalias"> Alias: ?</label>
<br> Alias: <input id="dataalias" placeholder="value"/><!--<button id="putvalue"> Put? </button>-->
<br>
<br> write sharedata: <input id="sharewrite" placeholder="value"/>
<br><button id="btnwriteput"> Write put </button>
<button id="btnwriteget"> Write get? </button>
<button id="btngrantaccess"> Grant access </button>
<br><button id="btntrustaccess"> Trust access </button>
<button id="btnwriteputmix"> Write Put mix </button>
<button id="btnwritegetmix"> Write Get mix </button>
<button id="btngetlatestgraph"> Write Get latest graph </button>
<button id="btnsharetrustlist"> sharewrite trust list</button>
<button id="btnmap"> map </button>
</div>
<div id="changepassphrase">
Old passphrase:<input id="oldpassphrase" value="" placeholder="old passphrase"/>
<br>New passphrase:<input id="newpassphrase" value="" placeholder="new passphrase"/>
<br><button id="btnchangepassphraseapply"> Apply </button>
</div>
<div id="passphrasehint">
Question 1:<input id="question1" value="" placeholder="Question #1"/>
<br>Question 2:<input id="question2" value="" placeholder="Question #2"/>
<br>Hint:<input id="hint" value="" placeholder="passphrase hint"/>
<br><button id="btnapplypassphrasehint"> Apply Hint </button>
<button id="btngetpassphrasehint"> Get Hint </button>
</div>
<div id="messages" style="height:100%;width:100%;">
<div id="messagesdiv" style="height:22px;width:100%;">
<select id="usercontacts">
<option selected disabled>-- Select User --</option>
</select>
<label>Public Key:</label><input id="mpublickey" value="" placeholder="public key"/>
<button id="btnadduser">+</button>
<button id="btnremoveuser">-</button>
<label id="mwho">who?</label>
</div>
<div id="messagelist" style="background-color: darkgray;">
</div>
<div id="messageinputarea"style="height:22px;width:100%">
<input id="inputmessagechat" value="" placeholder="type here and press enter">
</div>
</div>
<div id="publicchat">
Public Chat
<div id="publicchatlist" style="background-color: darkgray;overflow-y: scroll;">
Not Init.
</div>
<div id="publicchatarea"style="height:22px;width:100%">
<input id="inputpublicchat" value="" placeholder="type here and press enter">
</div>
</div>
<div id="privatechat">
Private Chat
<button id="btnprivatechatcreate">create</button>
<select id="privatechatroom">
<option selected disabled>-- Select Private Chat --</option>
</select>
<input id="privatechatkey" placeholder="private chat room key"/>
<button id="btnprivatechatjoin">Enter</button>
<button id="btnprivatechatleave">Leave</button>
<button id="btnprivatechatadd">+</button>
<button id="btnprivatechatremove">-</button>
<label id="btnprivatechatname">key?</label>
<input id="ppublickey" placeholder="public key"/>
<button id="btnprivatechatgrant">grant</button>
<button id="btnprivatechatrevoke">revoke</button>
<div id="privatechatlist" style="background-color: darkgray;overflow-y: scroll;">
Not Init.
</div>
<div id="privatechatarea"style="height:22px;width:100%">
<input id="inputprivatechat" value="" placeholder="type here and press enter">
</div>
</div>
<div id="Modal" class="modal">
<div id="dialog" class="modal-content">
<p>Message:<label id="dialogmessage">None</label></p>
<button id="btndialogokay">Okay</button>
</div>
</div>
<script src="/clientprototype.js" defer></script>
<footer>
</footer>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment