Improved user login and stability of funtions

Old prompt based user login and server connect are replaced with login page
Improved stability and simplification of functions
Moved all superNode functions to app.js
Supernode mode will now work in all pages (home,profile,msg) instead of just home
This commit is contained in:
sairajzero 2019-07-24 03:01:29 +05:30
parent cd31d9c267
commit 174b9fddf6
10 changed files with 7581 additions and 7564 deletions

View File

@ -6,7 +6,8 @@ window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.ms
if (!window.indexedDB) { if (!window.indexedDB) {
window.alert("Your browser doesn't support a stable version of IndexedDB.") window.alert("Your browser doesn't support a stable version of IndexedDB.")
} }
var supernodeKBucket;
var superNodeList;
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var encrypt = { var encrypt = {
@ -14,7 +15,7 @@ var encrypt = {
p: BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16), p: BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16),
exponent1: function () { exponent1: function () {
return encrypt.p.add(BigInteger.ONE).divide(BigInteger("4")) return this.p.add(BigInteger.ONE).divide(BigInteger("4"))
}, },
calculateY: function (x) { calculateY: function (x) {
@ -159,6 +160,34 @@ var encrypt = {
var floID = key.getBitcoinAddress(); var floID = key.getBitcoinAddress();
return floID; return floID;
}, },
validateAddr: function (value) {
try{
var addr = new Bitcoin.Address(value);
if (addr == value)
return true;
else
return false;
}catch(error){
return false;
}
},
verifyWIF: function (wif,addr){
try {
var key = new Bitcoin.ECKey(wif);
if(key.priv == null){
return false;
}
key.setCompressed(true);
var bitcoinAddress = key.getBitcoinAddress();
if (addr == bitcoinAddress)
return true;
else
return false;
}
catch (error) {
console.log(error);
}
},
sign: function (msg, privateKeyHex) { sign: function (msg, privateKeyHex) {
var key = new Bitcoin.ECKey(privateKeyHex); var key = new Bitcoin.ECKey(privateKeyHex);
key.setCompressed(true); key.setCompressed(true);
@ -255,11 +284,9 @@ function getTime(time){
function logout(){ function logout(){
sessionStorage.clear(); sessionStorage.clear();
location.reload(); window.location.href = "index.html";
} }
var supernodeKBucket;
var superNodeList;
/*Kademlia DHT K-bucket implementation as a binary tree.*/ /*Kademlia DHT K-bucket implementation as a binary tree.*/
if (typeof reactor == "undefined" || !reactor) { if (typeof reactor == "undefined" || !reactor) {
@ -317,25 +344,6 @@ reactor.addEventListener('bucket_full', function (someObject) {
console.log('Bucket full ' + someObject); console.log('Bucket full ' + someObject);
}); });
/*
//Sample Usage
//Creating and defining the event
reactor.registerEvent('big bang');
reactor.addEventListener('big bang', function(someObject){
console.log('This is big bang listener yo!'+ someObject.a);
});
//Firing the event
reactor.dispatchEvent('big bang');
reactor.dispatchEvent('big bang',{a:1});
reactor.dispatchEvent('big bang',{a:55});
*/
//Checking if existing NodeID can be used
//This first block of if will initialize the configuration of KBucket
//Add Events, Messaging between different K-Buckets, and attach relevant distributed data
/** /**
* @param {Uint8Array} array1 * @param {Uint8Array} array1
@ -984,6 +992,35 @@ kBucketObj = {
} }
} }
/* Common IDB functions */
function storeTweet(data,tid){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
data.tweetID = `${data.time}_${data.floID}`;
data.tid = tid;
obs.add(data);
var obsL = db.transaction("lastTweet", "readwrite").objectStore("lastTweet");
obsL.put(tid,data.floID);
db.close();
};
}
function storeMsg(data){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("messages", "readwrite").objectStore("messages");
data.msgID = `${data.time}_${data.floID}`;
obs.add(data);
db.close();
};
}
/* SuperNode functions */
function sendDataToSuperNode(floID,data){ function sendDataToSuperNode(floID,data){
kBucketObj.determineClosestSupernode(floID).then(result=>{ kBucketObj.determineClosestSupernode(floID).then(result=>{
var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws"); var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws");
@ -996,4 +1033,159 @@ function sendDataToSuperNode(floID,data){
}).catch(e => { }).catch(e => {
console.log(e.message); console.log(e.message);
}); });
} }
function superNodeMode(data){
if(data.reqNewTweets){
kBucketObj.determineClosestSupernode(data.floID).then(result => {
if(result[0].floID == selfID)
SuperNode_sendTweetsFromIDB(data.floID,data.tid,data.requestor);
}).catch(error => {
console.log(error);
});
}else if(data.newSuperNodeTweet){
kBucketObj.determineClosestSupernode(data.floID).then(result => {
if(result[0].floID == selfID)
SuperNode_storeSuperNodeTweet(data.data,data.tid);
}).catch(error => {
console.log(error);
});
}else if(data.viaSuperNodeMsg){
kBucketObj.determineClosestSupernode(data.to).then(result => {
if(result[0].floID == selfID)
SuperNode_storeViaSuperNodeMsg(data.from,data.to,data.data);
}).catch(error => {
console.log(error);
});
}else if(data.viaMsgreq){
kBucketObj.determineClosestSupernode(data.floID).then(result => {
if(result[0].floID == selfID)
SuperNode_sendviaMsgFromIDB(data.floID);
}).catch(error => {
console.log(error);
});
}
}
function SuperNode_sendTweetsFromIDB(floID,tid,requestor){
return new Promise((resolve,reject) => {
var requestorWS = new WebSocket("ws://"+profiles[requestor].onionAddr+"/ws");
requestorWS.onopen = (event) => {
console.log(`sending ${floID} tweets to ${requestor} Server!`);
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
idb.onupgradeneeded = (event) => {
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
}
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
var curReq = obs.openCursor();
curReq.onsuccess = (event) => {
var cursor = event.target.result;
if(cursor) {
if(cursor.value.floID == floID && cursor.value.tid > tid){
data = JSON.stringify({fromSuperNode:true, floID:cursor.value.floID,tid:cursor.value.tid,data:cursor.value.data})
requestorWS.send(data);
}
cursor.continue();
}else{
resolve("Displayed Tweets from IDB!");
}
}
curReq.onerror = (event) => { reject("Error in Reading tweets from IDB!") }
db.close();
};
};
requestorWS.onerror = (event) => { console.log(`${requestor} Server is offline!`) };
requestorWS.onclose = (event) => { console.log(`Disconnected from ${requestor} Server!`) };
});
}
function SuperNode_storeSuperNodeTweet(data,tid){
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
idb.onupgradeneeded = (event) => {
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
}
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
var parsedData = JSON.parse(data);
var tweetID = ''+parsedData.floID+'_'+parsedData.time;
obs.add({tweetID:tweetID,floID:parsedData.floID,tid:tid,data:data});
db.close();
};
}
function SuperNode_storeViaSuperNodeMsg(from,to,data){
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
idb.onupgradeneeded = (event) => {
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement :true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
}
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
obs.add({from:from,to:to,data:data});
db.close();
};
}
function SuperNode_sendviaMsgFromIDB(floID){
var receiverWS = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws");
receiverWS.onopen = (event) => {
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
idb.onupgradeneeded = (event) => {
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
};
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
obs.openCursor().onsuccess = (event) => {
var cursor = event.target.result;
if(cursor) {
if(cursor.value.to == floID){
receiverWS.send(cursor.value.data);
cursor.delete();
}
cursor.continue();
}else{
console.log('Sent All messages to '+floID)
}
}
db.close();
};
};
receiverWS.onerror = (event) => { console.log('Connection Error to '+floID) };
receiverWS.onclose = (event) => { console.log('Disconnected from '+floID) };
}

View File

@ -8,12 +8,12 @@
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<!-- Font Awesome File --> <!-- Font Awesome File -->
<script type="text/javascript" src="registerID.js"></script> <script type="text/javascript" src="init.js"></script>
<script type="text/javascript" src="app.js"></script> <script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="home.js"></script> <script type="text/javascript" src="home.js"></script>
</head> </head>
<body onload = "userDataStartUp();"> <body onload = "viewHome();">
<div class="navbar navbar-default navbar-static-top"> <div class="navbar navbar-default navbar-static-top">
<div class="container"> <div class="container">

View File

@ -1,317 +1,60 @@
var profiles = [] var profiles, following;
var selfID;
var selfWebsocket,followingWebSockets = []; var selfWebsocket,followingWebSockets = [];
var privKey; var privKey, modSuperNode, selfID;
var following;
function userDataStartUp(){ function viewHome(){
console.log("StartUp"); if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined || sessionStorage.superNodeList === undefined ){
alert("Login credentials failed! Returning to login page!");
/*document.getElementById("sendMsgInput").addEventListener("keyup",function(event){ window.location.href = "index.html";
if(event.keyCode === 13){ return;
event.preventDefault(); }
sendMsg(); profiles = JSON.parse(sessionStorage.profiles);
} console.log(profiles);
});*/ privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey));
selfID = sessionStorage.selfID;
getDatafromAPI().then(function (result) { superNodeList = JSON.parse(sessionStorage.superNodeList);
console.log(result); if(superNodeList.includes(selfID))
getProfilesfromIDB().then(function (result){ modSuperNode = true;
profiles = arrayToObject(result); kBucketObj.launchKBucket().then(function(result){
console.log(profiles); console.log(result);
sessionStorage.profiles = JSON.stringify(profiles); initselfWebSocket();
getSuperNodeListfromIDB().then(function(result){ listProfiles();
console.log(result) pingSuperNodeforNewMsgs();
superNodeList = result; getFollowinglistFromIDB().then(result => {
sessionStorage.superNodeList = JSON.stringify(superNodeList); following = result;
kBucketObj.launchKBucket().then(function(result){ if(!following.includes(selfID))
console.log(result) following.push(selfID);
getuserID().then(function(result){ console.log(following);
console.log(result); displayTweetsFromIDB().then(result => {
selfID = result; connectToAllFollowing();
if(superNodeList.includes(selfID)) }).catch(error => {
modSuperNode = true; console.log(error);
sessionStorage.privKey = JSON.stringify(encrypt.createShamirsSecretShares(privKey,10,10)); })
sessionStorage.selfID = selfID; }).catch(error => {
alert(`${selfID}\nWelcome ${profiles[selfID].name}`) console.log(error);
initselfWebSocket(); })
listProfiles(); }).catch(function(error){
pingSuperNodeforNewMsgs(); console.log(error.message);
getFollowinglistFromIDB().then(function(result){ });
following = result;
if(!following.includes(selfID))
following.push(selfID);
console.log(following);
displayTweetsFromIDB().then(function(result){
connectToAllFollowing();
}).catch(function(error){
console.log(error.message);
})
}).catch(function(error){
console.log(error.message);
})
}).catch(function (error) {
console.log(error.message);
});
}).catch(function(error){
console.log(error.message);
});
}).catch(function (error) {
console.log(error.message);
});
}).catch(function (error) {
console.log(error.message);
});
}).catch(function (error) {
console.log(error.message);
});
}
function storedata(data){
return new Promise(
function(resolve, reject) {
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction('profiles', "readwrite").objectStore('profiles');
objectRequest = obs.put(data);
objectRequest.onerror = function(event) {
reject(Error('Error occured: Unable to store data'));
};
objectRequest.onsuccess = function(event) {
resolve('Data saved OK');
db.close();
};
};
}
);
}
function getDatafromAPI(){
return new Promise(
function(resolve, reject) {
var addr = adminID;
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
reject("Error in opening IndexedDB!");
};
idb.onupgradeneeded = function(event) {
var db = event.target.result;
var objectStore0 = event.target.result.createObjectStore("superNodes");
var objectStore1 = db.createObjectStore("profiles",{ keyPath: 'floID' });
objectStore1.createIndex('onionAddr', 'onionAddr', { unique: false });
objectStore1.createIndex('name', 'name', { unique: false });
objectStore1.createIndex('pubKey', 'pubKey', { unique: false });
var objectStore2 = db.createObjectStore("lastTx");
var objectStore3 = db.createObjectStore("tweets",{ keyPath: 'tweetID' });
objectStore3.createIndex('tid', 'tid', { unique: false });
objectStore3.createIndex('floID', 'floID', { unique: false });
objectStore3.createIndex('time', 'time', { unique: false });
objectStore3.createIndex('data', 'data', { unique: false });
var objectStore4 = db.createObjectStore("lastTweet");
var objectStore5 = db.createObjectStore("followers");
var objectStore6 = db.createObjectStore("following");
var objectStore7 = event.target.result.createObjectStore("messages",{ keyPath: 'msgID' });
objectStore7.createIndex('time', 'time', { unique: false });
objectStore7.createIndex('text', 'text', { unique: false });
objectStore7.createIndex('floID', 'floID', { unique: false });
objectStore7.createIndex('type', 'type', { unique: false });
};
idb.onsuccess = function(event) {
var db = event.target.result;
//window["wait"] = addrList.length;
var lastTx = db.transaction('lastTx', "readwrite").objectStore('lastTx');
//addrList.forEach(function(addr){
console.log(addr);
new Promise(function(res,rej){
var lastTxReq = lastTx.get(addr);
lastTxReq.onsuccess = function(event){
var lasttx = event.target.result;
if(lasttx === undefined){
lasttx = 0;
}
res(lasttx);
}
}).then(function(lasttx){
var response = ajax("GET",`api/addrs/${addr}/txs`);
var nRequired = JSON.parse(response).totalItems - lasttx;
console.log(nRequired);
while(true && nRequired){
var response = ajax("GET",`api/addrs/${addr}/txs?from=0&to=${nRequired}`);
response = JSON.parse(response);
if (nRequired + lasttx != response.totalItems ){
nRequired = response.totalItems - lasttx;
continue;
}
response.items.reverse().forEach(function(tx){
try {
if (tx.vin[0].addr == addr){
var data = JSON.parse(tx.floData).FLO_Tweet_SuperNode;
if(data !== undefined){
storeSuperNodeData(data).then(function (response) {
}).catch(function (error) {
console.log(error.message);
});
}
}else{
var data = JSON.parse(tx.floData).FLO_Tweet;
if(data !== undefined){
if(encrypt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr)
throw("PublicKey doesnot match with floID")
data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name, pubKey:data.pubKey};
storedata(data).then(function (response) {
}).catch(function (error) {
console.log(error.message);
});
}
}
} catch (e) {
//console.log(e)
}
});
var obs = db.transaction('lastTx', "readwrite").objectStore('lastTx');
obs.put(response.totalItems,addr);
break;
}
db.close();
resolve('retrived data from API');
});
};
}
);
}
function storeSuperNodeData(data){
return new Promise(
function(resolve, reject) {
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
reject("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction('superNodes', "readwrite").objectStore('superNodes');
if(data.addNodes)
for(var i=0; i<data.addNodes.length; i++)
obs.add(true,data.addNodes[i])
if(data.removeNodes)
for(var i=0; i<data.removeNodes.length; i++)
obs.delete(data.removeNodes[i])
db.close();
resolve('Updated superNodes list in IDB');
};
}
);
}
function getSuperNodeListfromIDB(){
return new Promise(
function(resolve,reject){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
reject("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("superNodes", "readwrite").objectStore("superNodes");
var getReq = obs.getAllKeys();
getReq.onsuccess = function(event){
resolve(event.target.result);
}
getReq.onerror = function(event){
reject('Unable to read superNode list!')
}
db.close();
};
}
);
}
function getuserID(){
return new Promise(
function(resolve,reject){
privKey = (sessionStorage.privKey !== undefined ? encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey)):prompt("Enter FLO Private Key : "));
var key = new Bitcoin.ECKey(privKey);
while(key.priv == null){
privKey = prompt("Invalid FLO Private Key! Retry : ")
key = Bitcoin.ECKey(privKey);
}
key.setCompressed(true);
var userID = key.getBitcoinAddress();
if (profiles[userID] === undefined)
var reg = confirm(`${userID} is not registers to FLO Tweet!\nRegister FLO ID to this onion?`);
else if (profiles[userID].onionAddr == window.location.host)
resolve(userID)
else
var reg = confirm(`${userID} is registered to another onion!\nChange to this onion?`);
if(reg){
var name = prompt("Enter your name :");
var pubKey = key.getPubKeyHex();
if(registerID(userID,window.location.host,privKey,pubKey,name)){
profiles[userID] = {onionAddr : window.location.host, name : name, pubKey : pubKey};
resolve(userID);
}
}
reject(`Unable to bind ${userID} to this onionAddress!\nTry again later!`);
}
);
}
function getProfilesfromIDB(){
return new Promise(
function(resolve,reject){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
reject("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("profiles", "readwrite").objectStore("profiles");
var getReq = obs.getAll();
getReq.onsuccess = function(event){
resolve(event.target.result);
}
getReq.onerror = function(event){
reject('Unable to read profiles!')
}
db.close();
};
}
);
} }
function initselfWebSocket(){ function initselfWebSocket(){
selfWebsocket = new WebSocket("ws://"+location.host+"/ws"); selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
selfWebsocket.onopen = function(evt){ selfWebsocket.onopen = (event) => {
console.log("Connecting"); console.log("Connecting");
var pass = (sessionStorage.serverPass !== undefined ? encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass)): prompt("Enter server password :")); var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
selfWebsocket.send("$"+pass); selfWebsocket.send("$"+serverPass);
sessionStorage.serverPass = JSON.stringify(encrypt.createShamirsSecretShares(pass,5,5));
}; };
selfWebsocket.onclose = function(evt){ selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") };
console.log("DISCONNECTED"); selfWebsocket.onmessage = (event) => {
}; console.log(event.data);
selfWebsocket.onmessage = function(evt){ if(event.data[0] == '$')
console.log(evt.data); return;
if(evt.data == "$Access Denied!"){ try{
var pass = prompt("Access Denied! reEnter server password :"); data = JSON.parse(event.data);
selfWebsocket.send("$"+pass);
sessionStorage.serverPass = JSON.stringify(encrypt.createShamirsSecretShares(pass,5,5));
}else if(evt.data == "$Access Granted!")
alert("Access Granted!")
else{
try{
data = JSON.parse(evt.data);
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("followers", "readwrite").objectStore("followers"); var obs = db.transaction("followers", "readwrite").objectStore("followers");
obs.add(data.sign,data.floID); obs.add(data.sign,data.floID);
@ -320,7 +63,7 @@ function initselfWebSocket(){
selfWebsocket.send(`F${data.floID}`); selfWebsocket.send(`F${data.floID}`);
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ }else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("followers", "readwrite").objectStore("followers"); var obs = db.transaction("followers", "readwrite").objectStore("followers");
obs.delete(data.floID); obs.delete(data.floID);
@ -339,44 +82,13 @@ function initselfWebSocket(){
createTweetElement(data.floID,data.time,data.tweet); createTweetElement(data.floID,data.time,data.tweet);
} }
}else if(modSuperNode){ }else if(modSuperNode){
if(data.reqNewTweets){ superNodeMode(data);
kBucketObj.determineClosestSupernode(data.floID).then(result=>{
if(result[0].floID == selfID)
SuperNode_sendTweetsFromIDB(data.floID,data.tid,data.requestor);
}).catch(e => {
console.log(e.message);
});
}else if(data.newSuperNodeTweet){
kBucketObj.determineClosestSupernode(data.floID).then(result=>{
if(result[0].floID == selfID)
SuperNode_storeSuperNodeTweet(data.data,data.tid);
}).catch(e => {
console.log(e.message);
});
}else if(data.viaSuperNodeMsg){
kBucketObj.determineClosestSupernode(data.to).then(result=>{
if(result[0].floID == selfID)
SuperNode_storeViaSuperNodeMsg(data.from,data.to,data.data);
}).catch(e => {
console.log(e.message);
});
}else if(data.viaMsgreq){
kBucketObj.determineClosestSupernode(data.floID).then(result=>{
if(result[0].floID == selfID)
SuperNode_sendviaMsgFromIDB(data.floID);
}).catch(e => {
console.log(e.message);
});
}
} }
}catch(error){ }catch(error){
console.log(error.message); console.log(error.message);
} }
}
};
selfWebsocket.onerror = function(evt){
console.log(evt);
}; };
selfWebsocket.onerror = (event) => { console.log(event) };
} }
function listProfiles(){ function listProfiles(){
@ -394,7 +106,6 @@ function listProfiles(){
</div></a>` </div></a>`
profileList.appendChild(element); profileList.appendChild(element);
} }
//document.getElementById("profileInfo").style.display = "none";
} }
function postTweet(){ function postTweet(){
@ -406,98 +117,40 @@ function postTweet(){
var data = JSON.stringify({floID:selfID,time:time,tweet:tweet,sign:sign}); var data = JSON.stringify({floID:selfID,time:time,tweet:tweet,sign:sign});
console.log(data); console.log(data);
selfWebsocket.send(data); selfWebsocket.send(data);
getLastTweetCount(selfID).then(function(result){ getLastTweetCount(selfID).then(result => {
sendTweetToSuperNode(data,result+1); var SNdata = JSON.stringify({newSuperNodeTweet:true,floID:selfID,tid:result+1,data:data});
}).catch(function(error){ sendDataToSuperNode(selfID,SNdata);
console.log(error.message); }).catch(error => {
console.log(error);
}); });
} }
function storeTweet(data,tid){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
data.tweetID = `${data.time}_${data.floID}`;
data.tid = tid;
obs.add(data);
var obsL = db.transaction("lastTweet", "readwrite").objectStore("lastTweet");
obsL.put(tid,data.floID);
db.close();
};
}
function storeMsg(data){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("messages", "readwrite").objectStore("messages");
data.msgID = `${data.time}_${data.floID}`;
obs.add(data);
db.close();
};
}
function sendTweetToSuperNode(data,tid){
kBucketObj.determineClosestSupernode(selfID).then(result=>{
var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws");
superNodeWS.onopen = function(ev){
console.log(`Connected to self SuperNode!`);
data = JSON.stringify({newSuperNodeTweet:true,floID:selfID,tid:tid,data:data})
console.log(data)
superNodeWS.send(data);
};
superNodeWS.onerror = function(ev) {console.log(`self SuperNode is offline!`);};
superNodeWS.onclose = function(ev) {console.log(`Disconnected from self SuperNode!`);};
}).catch(e => {
console.log(e.message);
});
}
function getFollowinglistFromIDB(){ function getFollowinglistFromIDB(){
return new Promise( return new Promise((resolve,reject) => {
function(resolve,reject){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) { idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
reject("Error in opening IndexedDB!"); idb.onsuccess = (event) => {
};
idb.onsuccess = function(event) {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("following", "readwrite").objectStore("following"); var obs = db.transaction("following", "readwrite").objectStore("following");
var getReq = obs.getAllKeys(); var getReq = obs.getAllKeys();
getReq.onsuccess = function(event){ getReq.onsuccess = (event) => { resolve(event.target.result) }
resolve(event.target.result); getReq.onerror = (event) => { reject('Unable to read following list!') }
}
getReq.onerror = function(event){
reject('Unable to read following list!')
}
db.close(); db.close();
}; };
} });
);
} }
function displayTweetsFromIDB(){ function displayTweetsFromIDB(){
return new Promise( return new Promise((resolve,reject) => {
function(resolve,reject){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) { idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
reject("Error in opening IndexedDB!"); idb.onsuccess = (event) => {
};
idb.onsuccess = function(event) {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("tweets", "readwrite").objectStore("tweets"); var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
var curReq = obs.openCursor(); var curReq = obs.openCursor();
curReq.onsuccess = function(event) { curReq.onsuccess = (event) => {
var cursor = event.target.result; var cursor = event.target.result;
if(cursor) { if(cursor) {
//console.log(cursor.value)
if(cursor.value.floID == selfID || following.includes(cursor.value.floID)) if(cursor.value.floID == selfID || following.includes(cursor.value.floID))
createTweetElement(cursor.value.floID,cursor.value.time,cursor.value.data); createTweetElement(cursor.value.floID,cursor.value.time,cursor.value.data);
cursor.continue(); cursor.continue();
@ -505,13 +158,10 @@ function displayTweetsFromIDB(){
resolve("Displayed Tweets from IDB!"); resolve("Displayed Tweets from IDB!");
} }
} }
curReq.onerror = function(event){ curReq.onerror = (event) => { reject("Error in Reading tweets from IDB!") }
reject("Error in Reading tweets from IDB!");
}
db.close(); db.close();
}; };
} });
);
} }
function createTweetElement(floID,time,tweet){ function createTweetElement(floID,time,tweet){
@ -539,27 +189,24 @@ function connectToAllFollowing(){
console.log(floid) console.log(floid)
followingWebSockets[floid] = new WebSocket("ws://"+profiles[floid].onionAddr+"/ws"); followingWebSockets[floid] = new WebSocket("ws://"+profiles[floid].onionAddr+"/ws");
followingWebSockets[floid].onopen = function(ev){ followingWebSockets[floid].onopen = (event) => {
console.log(`Connected to ${floid} Server!`); console.log(`Connected to ${floid} Server!`);
getLastTweetCount(floid).then(function(result){ getLastTweetCount(floid).then(result => {
followingWebSockets[floid].send(`>${result}`); followingWebSockets[floid].send(`>${result}`);
}).catch(function(error){ }).catch(error => {
console.log(error.message); console.log(error);
}); });
}; };
followingWebSockets[floid].onerror = function(ev) { followingWebSockets[floid].onerror = (event) => {
console.log(`${floid} Server is offline!`); console.log(`${floid} Server is offline!`);
//Ping SuperNode for any new tweets //Ping SuperNode for any new tweets
pingSuperNodeforNewTweets(floid); pingSuperNodeforNewTweets(floid);
}; };
followingWebSockets[floid].onclose = function(ev) { followingWebSockets[floid].onclose = (event) => { console.log(`Disconnected from ${floid} Server!`); };
console.log(`Disconnected from ${floid} Server!`); followingWebSockets[floid].onmessage = (event) => {
}; console.log(event.data);
followingWebSockets[floid].onmessage = function(evt){
console.log(evt.data);
try{ try{
var data = JSON.parse(evt.data); var data = JSON.parse(event.data);
var id = data.id; var id = data.id;
data = data.data; data = data.data;
if( floid!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floid].pubKey)) if( floid!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floid].pubKey))
@ -574,14 +221,13 @@ function connectToAllFollowing(){
} }
function getLastTweetCount(floid){ function getLastTweetCount(floid){
return new Promise( return new Promise((resolve,reject) => {
function(resolve,reject){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet'); var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet');
var lastTweetReq = lastTweet.get(floid); var lastTweetReq = lastTweet.get(floid);
lastTweetReq.onsuccess = function(event){ lastTweetReq.onsuccess = (event) => {
var result = event.target.result; var result = event.target.result;
if(result === undefined) if(result === undefined)
result = 0; result = 0;
@ -589,8 +235,7 @@ function getLastTweetCount(floid){
} }
db.close(); db.close();
}; };
} });
);
} }
function pingSuperNodeforNewMsgs(){ function pingSuperNodeforNewMsgs(){
@ -599,150 +244,10 @@ function pingSuperNodeforNewMsgs(){
} }
function pingSuperNodeforNewTweets(floID){ function pingSuperNodeforNewTweets(floID){
getLastTweetCount(floID).then(function(result){ getLastTweetCount(floID).then(result => {
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID}) var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
sendDataToSuperNode(floID,data); sendDataToSuperNode(floID,data);
}).catch(function(error){ }).catch(error => {
console.log(error.message); console.log(error);
}); });
} }
function SuperNode_storeSuperNodeTweet(data,tid){
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onupgradeneeded = function(event){
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
}
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
var parsedData = JSON.parse(data);
var tweetID = ''+parsedData.floID+'_'+parsedData.time;
obs.add({tweetID:tweetID,floID:parsedData.floID,tid:tid,data:data});
db.close();
};
}
function SuperNode_storeViaSuperNodeMsg(from,to,data){
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onupgradeneeded = function(event){
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement :true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
}
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
obs.add({from:from,to:to,data:data});
db.close();
};
}
function SuperNode_sendTweetsFromIDB(floID,tid,requestor){
return new Promise(
function(resolve,reject){
var requestorWS = new WebSocket("ws://"+profiles[requestor].onionAddr+"/ws");
requestorWS.onopen = function(ev){
console.log(`sending ${floID} tweets to ${requestor} Server!`);
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = function(event) {
reject("Error in opening IndexedDB!");
};
idb.onupgradeneeded = function(event){
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
}
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("superNodeTweet", "readwrite").objectStore("superNodeTweet");
var curReq = obs.openCursor();
curReq.onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
if(cursor.value.floID == floID && cursor.value.tid > tid){
data = JSON.stringify({fromSuperNode:true, floID:cursor.value.floID,tid:cursor.value.tid,data:cursor.value.data})
requestorWS.send(data);
}
cursor.continue();
}else{
resolve("Displayed Tweets from IDB!");
}
}
curReq.onerror = function(event){
reject("Error in Reading tweets from IDB!");
}
db.close();
};
};
requestorWS.onerror = function(ev) {
console.log(`${requestor} Server is offline!`);
};
requestorWS.onclose = function(ev) {
console.log(`Disconnected from ${requestor} Server!`);
};
}
);
}
function SuperNode_sendviaMsgFromIDB(floID){
var receiverWS = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws");
receiverWS.onopen = function(ev){
var idb = indexedDB.open("FLO_Tweet",2);
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onupgradeneeded = function(event) {
var objectStore1 = event.target.result.createObjectStore("superNodeTweet",{ keyPath: 'tweetID' });
objectStore1.createIndex('floID', 'floID', { unique: false });
objectStore1.createIndex('tid', 'tid', { unique: false });
objectStore1.createIndex('data', 'data', { unique: false });
var objectStore2 = event.target.result.createObjectStore("viaSuperNodeMsg",{ keyPath: 'id',autoIncrement:true });
objectStore2.createIndex('from', 'from', { unique: false });
objectStore2.createIndex('to', 'to', { unique: false });
objectStore2.createIndex('data', 'data', { unique: false });
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("viaSuperNodeMsg", "readwrite").objectStore("viaSuperNodeMsg");
obs.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
if(cursor.value.to == floID){
receiverWS.send(cursor.value.data);
cursor.delete();
}
cursor.continue();
}else{
console.log('Sent All messages to '+floID)
}
}
db.close();
};
};
receiverWS.onerror = function(ev) { console.log('Connection Error to '+floID) };
receiverWS.onclose = function(ev) { console.log('Disconnected from '+floID) };
}

View File

@ -1,5 +1,146 @@
<html> <html>
<script type="text/javascript"> <head>
window.location.href = "home.html"; <title>Login</title>
</script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
@charset "utf-8";
/* CSS Document */
h1{
margin: 0 auto;
padding-left: 15%;
text-transform:uppercase;
font-size:30px;
color:white;
}
h2{
margin: 0 auto;
padding-left: 15%;
font-size:18px;
color:#fff;
}
body {
font-family: Helvetica;
margin:0 auto;
min-height:100%;
background: lightblue;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
.nav {
margin: 0 auto;
margin-top: 100px;
margin-left: 35%;
width: 300px;
height: auto;
background: #fff;
border-radius: 5px;
text-align: center;
padding-top: 10px;
padding-bottom: 10px;
box-shadow: 0 0 10px rgba(0,0,0, .5);
}
.input {
border: 1px solid #a6a6a6;
width: 230px;
height: 40px;
border-radius: 3px;
margin-top: 5px;
padding-left: 9px;
color: #6c6c6c;
background: #fcfcfc;
outline: none;
}
.input:hover:enabled{
box-shadow: 0 0 10px #337AB7;
border: 1px #337AB7 solid ;
}
.input:focus, .button:focus, .button:hover:focus{
box-shadow: 0 0 10px #337AB7;
border: 1px #337AB7 solid ;
}
.button {
color:#fff;
font-size:20px;
border: 1px solid #a6a6a6;
width: 243px;
height: 43px;
border-radius: 5px;
margin-top: 5px;
margin-right: 6px;
outline: none;
}
.button:disabled,.input:disabled{
cursor:not-allowed;
}
label {
position: relative;
top: 5px;
margin-right: 115px;
}
label span {
margin-left: 5px;
font-size:14px;
}
</style>
<style>
#alert-container{
width: 100%;
text-align: center;
position: fixed;
top:0;
z-index: 2;
}
.alert {
padding: 10px;
color: white;
max-width: 700px;
margin: 0 auto;
}
.closebtn {
margin-left: 15px;
color: white;
font-weight: bold;
float: right;
cursor: pointer;
transition: 0.3s;
}
.closebtn:hover {
color: black;
}
</style>
<script type="text/javascript" src="init.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="login.js"></script>
</head>
<body onload="refreshAPIdata();">
<div id="alert-container"></div>
<div class="nav">
<form id='serverConnect'>
<input type="password" id="serverPass" class="input" placeholder="ServerPass" />
<input type="button" value="Connect" class="button btn-primary" onclick="connect()"/></br>
</form>
<form id='userSignIn'>
<input type="text" id="username" class="input" placeholder="Username" disabled/>
<input type="password" id="privKey" class="input" placeholder="PrivKey" disabled/>
<input type="button" value="Sign In" class="button btn-primary" onclick="signIn()" disabled/>
</form>
</div>
</body>
</html> </html>

13418
app/web/registerID.js → app/web/init.js Executable file → Normal file

File diff suppressed because it is too large Load Diff

379
app/web/login.js Normal file
View File

@ -0,0 +1,379 @@
if( sessionStorage.profiles && sessionStorage.privKey && sessionStorage.selfID && sessionStorage.serverPass && sessionStorage.superNodeList ){
window.location.replace("home.html");
return;
}
const adminID = "FMabh7gTSyKPAb2Wi9sK5CBhV8nVFk783i";
if(blockchain == "FLO")
var api_url = `https://flosight.duckdns.org/`;
else if(blockchain == "FLO_TEST")
var api_url = `https://testnet-flosight.duckdns.org/`;
const sendAmt = 0.001 ;
const fee = 0.0005;
var username,privKey,floID;
var profiles;
function refreshAPIdata(){
return new Promise((resolve,reject) => {
console.log("refreshAPIdata");
getDatafromAPI().then(result => {
console.log(result);
getProfilesfromIDB().then(result => {
profiles = arrayToObject(result);
console.log(profiles);
sessionStorage.profiles = JSON.stringify(profiles);
getSuperNodeListfromIDB().then(result => {
console.log(result)
superNodeList = result;
sessionStorage.superNodeList = JSON.stringify(superNodeList);
resolve('Refresh API data Successful!')
}).catch(error => {
reject(error);
});
}).catch(error => {
reject(error);
});
}).catch(error => {
reject(error);
});
});
}
function customAlert(msg,type){
color = {info:"#2196F3",danger:"#f44336",warning:"#ff9800",success:"#4CAF50"};
var alertBox = document.createElement('div');
alertBox.setAttribute('class','alert');
alertBox.style.backgroundColor = color[type];
alertBox.innerHTML = `<span class="closebtn" onclick="this.parentElement.style.display='none';">&#10006;</span>
${msg}`;
document.getElementById("alert-container").appendChild(alertBox);
}
function disableForm(formId, disableFlag) {
var form = document.getElementById(formId);
for(var i=0; i<form.length; i++)
form[i].disabled = disableFlag;
}
function connect(){
document.getElementById("alert-container").innerHTML = '';
var serverPass = document.getElementById('serverPass');
initselfWebSocket(serverPass).then(result => {
customAlert(result,success);
disableForm('serverConnect',true);
disableForm('userSignIn',false);
}).catch(error => {
customAlert(error,danger);
});
}
function signIn(){
document.getElementById("alert-container").innerHTML = '';
username = document.getElementById('username').value;
privKey = document.getElementById('privKey').value;
var key = new Bitcoin.ECKey(privKey);
if(key.priv == null){
customAlert("Invalid FLO Private Key!",'danger');
return false;
}
key.setCompressed(true);
floID = key.getBitcoinAddress();
try{
console.log(floID)
if (profiles[floID] === undefined)
throw `${floID} is not registers to FLO Tweet!<br/>Register FLO ID to this onion?`;
if (profiles[floID].onionAddr != window.location.host)
throw `${floID} is registered to another onion!<br/>Change to this onion?`;
if (profiles[floID].name != username)
throw `${floID} is registered to another username!<br/>Change username?`;
login();
}catch(msg){
console.log(msg)
customAlert(`${msg}<span class="closebtn" onclick="this.parentElement.parentElement.style.display='none'; signUp();">&#10004;</span>`,'warning');
}
}
async function login(){
sessionStorage.privKey = JSON.stringify(encrypt.createShamirsSecretShares(privKey,10,10));
sessionStorage.selfID = floID;
customAlert(`Welcome ${username}`,'info');
await sleep(3000);
window.location.replace("home.html");
}
function signUp(){
registerID(floID,window.location.host,privKey,privKey.getPubKeyHex(),username).then(result =>{
customAlert(`Registration Successful!<br/> txid : ${result}`,'success');
refreshAPIdata().then(result => {
console.log(result);
login();
}).catch(error => {
console.log(error);
});
}).catch(error => {
customAlert(error,'danger');
});
}
function ajax(method, uri){
var request = new XMLHttpRequest();
var url = `${api_url}/${uri}`
console.log(url)
var result;
request.open(method,url , false);
request.onload = function () {
if (request.readyState == 4 && request.status == 200)
result = this.response;
else {
console.log('error');
result = false;
}
};
request.send();
console.log(result);
return result;
}
function getDatafromAPI(){
return new Promise((resolve,reject) => {
var addr = adminID;
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
idb.onupgradeneeded = (event) => {
var db = event.target.result;
var objectStore0 = event.target.result.createObjectStore("superNodes");
var objectStore1 = db.createObjectStore("profiles",{ keyPath: 'floID' });
objectStore1.createIndex('onionAddr', 'onionAddr', { unique: false });
objectStore1.createIndex('name', 'name', { unique: false });
objectStore1.createIndex('pubKey', 'pubKey', { unique: false });
var objectStore2 = db.createObjectStore("lastTx");
var objectStore3 = db.createObjectStore("tweets",{ keyPath: 'tweetID' });
objectStore3.createIndex('tid', 'tid', { unique: false });
objectStore3.createIndex('floID', 'floID', { unique: false });
objectStore3.createIndex('time', 'time', { unique: false });
objectStore3.createIndex('data', 'data', { unique: false });
var objectStore4 = db.createObjectStore("lastTweet");
var objectStore5 = db.createObjectStore("followers");
var objectStore6 = db.createObjectStore("following");
var objectStore7 = event.target.result.createObjectStore("messages",{ keyPath: 'msgID' });
objectStore7.createIndex('time', 'time', { unique: false });
objectStore7.createIndex('text', 'text', { unique: false });
objectStore7.createIndex('floID', 'floID', { unique: false });
objectStore7.createIndex('type', 'type', { unique: false });
};
idb.onsuccess = (event) => {
var db = event.target.result;
var lastTx = db.transaction('lastTx', "readwrite").objectStore('lastTx');
console.log(addr);
new Promise((res,rej) => {
var lastTxReq = lastTx.get(addr);
lastTxReq.onsuccess = (event) => {
var lasttx = event.target.result;
if(lasttx === undefined){
lasttx = 0;
}
res(lasttx);
}
}).then(lasttx => {
var response = ajax("GET",`api/addrs/${addr}/txs`);
var nRequired = JSON.parse(response).totalItems - lasttx;
console.log(nRequired);
while(true && nRequired){
var response = ajax("GET",`api/addrs/${addr}/txs?from=0&to=${nRequired}`);
response = JSON.parse(response);
if (nRequired + lasttx != response.totalItems ){
nRequired = response.totalItems - lasttx;
continue;
}
response.items.reverse().forEach(tx => {
try {
if (tx.vin[0].addr == addr){
var data = JSON.parse(tx.floData).FLO_Tweet_SuperNode;
if(data !== undefined){
storeSuperNodeData(data).then(function (response) {
}).catch(error => {
console.log(error);
});
}
}else{
var data = JSON.parse(tx.floData).FLO_Tweet;
if(data !== undefined){
if(encrypt.getFLOIDfromPubkeyHex(data.pubKey)!=tx.vin[0].addr)
throw("PublicKey doesnot match with floID")
data = {floID : tx.vin[0].addr, onionAddr : data.onionAddr, name : data.name, pubKey:data.pubKey};
storeProfile(data).then(function (response) {
}).catch(error => {
console.log(error);
});
}
}
} catch (error) {
//console.log(error)
}
});
var obs = db.transaction('lastTx', "readwrite").objectStore('lastTx');
obs.put(response.totalItems,addr);
break;
}
db.close();
resolve('retrived data from API');
});
};
});
}
function storeProfile(data){
return new Promise((resolve,reject) => {
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = (event) => { console.log("Error in opening IndexedDB!") };
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction('profiles', "readwrite").objectStore('profiles');
objectRequest = obs.put(data);
objectRequest.onerror = (event) => { reject(Error('Error occured: Unable to store data'))};
objectRequest.onsuccess = (event) => { resolve('Data saved OK') };
db.close();
};
});
}
function storeSuperNodeData(data){
return new Promise((resolve,reject) => {
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = (event) => { reject("Error in opening IndexedDB!"); };
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction('superNodes', "readwrite").objectStore('superNodes');
if(data.addNodes)
for(var i=0; i<data.addNodes.length; i++)
obs.add(true,data.addNodes[i])
if(data.removeNodes)
for(var i=0; i<data.removeNodes.length; i++)
obs.delete(data.removeNodes[i])
db.close();
resolve('Updated superNodes list in IDB');
};
});
}
function getProfilesfromIDB(){
return new Promise((resolve,reject) => {
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("profiles", "readwrite").objectStore("profiles");
var getReq = obs.getAll();
getReq.onsuccess = (event) => { resolve(event.target.result) }
getReq.onerror = (event) => { reject('Unable to read profiles!') }
db.close();
};
});
}
function getSuperNodeListfromIDB(){
return new Promise((resolve,reject) => {
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
idb.onsuccess = (event) => {
var db = event.target.result;
var obs = db.transaction("superNodes", "readwrite").objectStore("superNodes");
var getReq = obs.getAllKeys();
getReq.onsuccess = (event) => { resolve(event.target.result) }
getReq.onerror = (event) => { reject('Unable to read superNode list!') }
db.close();
};
});
}
function initselfWebSocket(serverPass){
return new Promise((resolve,reject) => {
selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
selfWebsocket.onopen = (event) => {
console.log("Connecting");
selfWebsocket.send("$"+serverPass);
};
selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") };
selfWebsocket.onmessage = (event) => {
console.log(event.data);
if(event.data == "$Access Denied!")
reject("Access Denied!");
else if(event.data == "$Access Granted!")
resolve("Access Granted!");
};
selfWebsocket.onerror = (event) => { console.log(event) };
});
}
//Script for AJAX, and register functions
function registerID(sender,onionAddr,wif,pubkey,username) {
return new Promise((resolve,reject) => {
var trx = bitjs.transaction();
var utxoAmt = 0.0;
var x = sendAmt+fee;
var response = ajax("GET",`api/addr/${sender}/utxo`);
var utxos = JSON.parse(response);
for(var x = utxos.length-1; x >= 0; x--){
if(utxoAmt < sendAmt+fee){
trx.addinput(utxos[x].txid, utxos[x].vout, utxos[x].scriptPubKey);
utxoAmt += utxos[x].amount;
}else
break;
}
console.log(utxoAmt+":"+(sendAmt+fee));
if(utxoAmt < sendAmt+fee)
reject("Insufficient balance!");
trx.addoutput(adminID, sendAmt);
console.log(adminID+":"+ sendAmt);
var change = utxoAmt-sendAmt-fee;
if(change>0)
trx.addoutput(sender, change);
console.log(sender+":"+ change);
var key = new Bitcoin.ECKey(wif);
var sendFloData = JSON.stringify({FLO_Tweet:{onionAddr:onionAddr, name: username, pubKey: pubkey}});;
trx.addflodata(sendFloData);
console.log(sendFloData);
var signedTxHash = trx.sign(wif, 1);
console.log(signedTxHash);
var txid = broadcastTx(signedTxHash);
if (txid)
resolve(txid);
else
reject('Registration Unsuccessful!')
});
}
function broadcastTx(signedTxHash) {
var http = new XMLHttpRequest();
var url = `${api_url}/api/tx/send`;
if (signedTxHash.length < 1) {
return false;
}
var params = `{"rawtx":"${signedTxHash}"}`;
var result;
http.open('POST', url, false);
//Send the proper header information along with the request
http.setRequestHeader('Content-type', 'application/json');
http.onreadystatechange = function () { //Call a function when the state changes.
if (http.readyState == 4 && http.status == 200) {
console.log(http.response);
var txid = JSON.parse(http.response).txid.result;
console.log("Transaction successful! txid : " + txid);
result = txid;
} else {
console.log(http.responseText);
result = false;
}
}
http.send(params);
return result;
}

View File

@ -9,7 +9,7 @@
<!-- Font Awesome File --> <!-- Font Awesome File -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script type="text/javascript" src="registerID.js"></script> <script type="text/javascript" src="init.js"></script>
<script type="text/javascript" src="app.js"></script> <script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="msg.js"></script> <script type="text/javascript" src="msg.js"></script>

View File

@ -1,11 +1,11 @@
var profiles; var profiles;
var receiverID,selfID,privKey; var receiverID,selfID,privKey,modSuperNode;
var selfwebsocket,receiverWebSocket,recStat; var selfwebsocket,receiverWebSocket,recStat;
function initMsgs(){ function initMsgs(){
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined){ if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined || sessionStorage.superNodeList === undefined ){
alert("Login credentials failed! Returning to home page!"); alert("Login credentials failed! Returning to login page!");
window.location.href = "home.html"; window.location.href = "index.html";
return; return;
} }
profiles = JSON.parse(sessionStorage.profiles); profiles = JSON.parse(sessionStorage.profiles);
@ -13,21 +13,23 @@ function initMsgs(){
privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey)); privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey));
selfID = sessionStorage.selfID; selfID = sessionStorage.selfID;
superNodeList = JSON.parse(sessionStorage.superNodeList); superNodeList = JSON.parse(sessionStorage.superNodeList);
kBucketObj.launchKBucket().then(function(result){ if(superNodeList.includes(selfID))
modSuperNode = true;
kBucketObj.launchKBucket().then(result => {
console.log(result) console.log(result)
initselfWebSocket(); initselfWebSocket();
readMsgfromIDB().then(function(result){ readMsgfromIDB().then(result => {
listProfiles(); listProfiles();
document.getElementById("sendMsgInput").addEventListener("keyup",function(event){ document.getElementById("sendMsgInput").addEventListener("keyup",(event) => {
if(event.keyCode === 13){ if(event.keyCode === 13){
event.preventDefault(); event.preventDefault();
sendMsg(); sendMsg();
} }
}); });
}).catch(function(error){ }).catch(error => {
console.log(error); console.log(error);
}); });
}).catch(function(error){ }).catch(error => {
console.log(error); console.log(error);
}); });
} }
@ -42,32 +44,30 @@ function listProfiles(){
var element = document.createElement("div"); var element = document.createElement("div");
element.setAttribute("class", "media"); element.setAttribute("class", "media");
element.innerHTML = `<a href="javascript:changeReceiver('${p}');"><div class="media-body"> element.innerHTML = `<a href="javascript:changeReceiver('${p}');"><div class="media-body">
<h5 class="media-heading">${profiles[p].name}</h5> <h5 class="media-heading">${profiles[p].name}</h5>
<small>@${p}</small> <small>@${p}</small>
</div></a>` </div></a>`
profileList.appendChild(element); profileList.appendChild(element);
} }
} }
function initselfWebSocket(){ function initselfWebSocket(){
selfWebsocket = new WebSocket("ws://"+location.host+"/ws"); selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
selfWebsocket.onopen = function(evt){ selfWebsocket.onopen = (event) => {
console.log("Connecting"); console.log("Connecting");
var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass)); var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
selfWebsocket.send("$"+serverPass); selfWebsocket.send("$"+serverPass);
}; };
selfWebsocket.onclose = function(evt){ selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") };
console.log("DISCONNECTED"); selfWebsocket.onmessage = (event) => {
}; console.log(event.data);
selfWebsocket.onmessage = function(evt){ if(event.data[0] == '$')
console.log(evt.data);
if(evt.data[0] == '$')
return; return;
try{ try{
data = JSON.parse(evt.data); data = JSON.parse(event.data);
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("followers", "readwrite").objectStore("followers"); var obs = db.transaction("followers", "readwrite").objectStore("followers");
obs.add(data.sign,data.floID); obs.add(data.sign,data.floID);
@ -76,7 +76,7 @@ function initselfWebSocket(){
selfWebsocket.send(`F${data.floID}-${data.sign}`); selfWebsocket.send(`F${data.floID}-${data.sign}`);
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ }else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("followers", "readwrite").objectStore("followers"); var obs = db.transaction("followers", "readwrite").objectStore("followers");
obs.delete(data.floID); obs.delete(data.floID);
@ -89,19 +89,18 @@ function initselfWebSocket(){
createMsgElement(data.from,data.time,msg,'R') createMsgElement(data.from,data.time,msg,'R')
storeMsg({time:data.time,floID:data.from,text:msg,type:'R'}); storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
} }
}else if(modSuperNode){
superNodeMode(data);
} }
}catch(error){ }catch(error){
console.log(error.message) console.log(error.message)
} }
}; };
selfWebsocket.onerror = function(evt){ selfWebsocket.onerror = (event) => { console.log(event) };
console.log(evt);
};
} }
function readMsgfromIDB(){ function readMsgfromIDB(){
return new Promise( return new Promise((resolve,reject) => {
function(resolve,reject){
var disp = document.getElementById("msgsContainer"); var disp = document.getElementById("msgsContainer");
for(floID in profiles){ for(floID in profiles){
var element = document.createElement('div'); var element = document.createElement('div');
@ -110,13 +109,11 @@ function readMsgfromIDB(){
disp.appendChild(element); disp.appendChild(element);
} }
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) { idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
reject("Error in opening IndexedDB!"); idb.onsuccess = (event) => {
};
idb.onsuccess = function(event) {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("messages", "readwrite").objectStore("messages"); var obs = db.transaction("messages", "readwrite").objectStore("messages");
obs.openCursor().onsuccess = function(event) { obs.openCursor().onsuccess = (event) => {
var cursor = event.target.result; var cursor = event.target.result;
if(cursor) { if(cursor) {
createMsgElement(cursor.value.floID,cursor.value.time,cursor.value.text,cursor.value.type); createMsgElement(cursor.value.floID,cursor.value.time,cursor.value.text,cursor.value.type);
@ -128,8 +125,7 @@ function readMsgfromIDB(){
}; };
db.close(); db.close();
}; };
} });
);
} }
function changeReceiver(floID){ function changeReceiver(floID){
@ -148,9 +144,9 @@ function changeReceiver(floID){
document.getElementById(receiverID).style.display = 'block'; document.getElementById(receiverID).style.display = 'block';
try{ try{
receiverWebSocket = new WebSocket("ws://"+profiles[receiverID].onionAddr+"/ws"); receiverWebSocket = new WebSocket("ws://"+profiles[receiverID].onionAddr+"/ws");
receiverWebSocket.onopen = function(ev){ recStat = true; }; receiverWebSocket.onopen = (event) => { recStat = true; };
receiverWebSocket.onerror = function(ev) { recStat = false;}; receiverWebSocket.onerror = (event) => { recStat = false;};
receiverWebSocket.onclose = function(ev) { recStat = false; }; receiverWebSocket.onclose = (event) => { recStat = false; };
}catch(e){ }catch(e){
console.log(e); console.log(e);
} }
@ -161,23 +157,22 @@ function sendMsg(){
alert("Select a contact and send message"); alert("Select a contact and send message");
return; return;
} }
var inp = document.getElementById('sendMsgInput') var inp = document.getElementById('sendMsgInput');
var msg = inp.value var msg = inp.value;
inp.value = "" inp.value = "";
console.log(msg) console.log(msg);
var time = Date.now() var time = Date.now();
var sign = encrypt.sign(msg,privKey) var sign = encrypt.sign(msg,privKey);
var msgEncrypt = encrypt.encryptMessage(msg,profiles[receiverID].pubKey) var msgEncrypt = encrypt.encryptMessage(msg,profiles[receiverID].pubKey);
var data = JSON.stringify({message:true,from:selfID,to:receiverID,time:time,secret:msgEncrypt.secret,sign:sign,pubVal:msgEncrypt.senderPublicKeyString}); var data = JSON.stringify({message:true,from:selfID,to:receiverID,time:time,secret:msgEncrypt.secret,sign:sign,pubVal:msgEncrypt.senderPublicKeyString});
if(recStat) if(recStat)
receiverWebSocket.send(data); receiverWebSocket.send(data);
else{ else{
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:receiverID,data:data}) var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:receiverID,data:data});
sendDataToSuperNode(receiverID,SNdata) sendDataToSuperNode(receiverID,SNdata);
} }
console.log(`sentMsg : ${data}`); console.log(`sentMsg : ${data}`);
createMsgElement(receiverID,time,msg,'S') createMsgElement(receiverID,time,msg,'S');
storeMsg({time:time,floID:receiverID,text:msg,type:'S'}); storeMsg({time:time,floID:receiverID,text:msg,type:'S'});
} }
@ -194,17 +189,3 @@ function createMsgElement(floID,time,msg,type){
</div>`; </div>`;
msgField.appendChild(element); msgField.appendChild(element);
} }
function storeMsg(data){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("messages", "readwrite").objectStore("messages");
data.msgID = `${data.time}_${data.floID}`;
obs.add(data);
db.close();
};
}

View File

@ -8,7 +8,7 @@
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<!-- Font Awesome File --> <!-- Font Awesome File -->
<script type="text/javascript" src="registerID.js"></script> <script type="text/javascript" src="init.js"></script>
<script type="text/javascript" src="app.js"></script> <script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="profile.js"></script> <script type="text/javascript" src="profile.js"></script>

View File

@ -1,12 +1,12 @@
var profileWebsocket, selfWebsocket,profileServerStatus; var profileWebsocket, selfWebsocket,profileServerStatus;
var profiles; var profiles;
var profileID, privKey, selfID; var profileID, privKey, selfID, modSuperNode;
function viewProfile(){ function viewProfile(){
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined){ if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined || sessionStorage.superNodeList === undefined ){
alert("Login credentials failed! Returning to home page!"); alert("Login credentials failed! Returning to login page!");
window.location.href = "home.html"; window.location.href = "index.html";
return; return;
} }
profiles = JSON.parse(sessionStorage.profiles); profiles = JSON.parse(sessionStorage.profiles);
@ -16,11 +16,13 @@ function viewProfile(){
var url = new URL(window.location.href); var url = new URL(window.location.href);
profileID = url.searchParams.get("floID"); profileID = url.searchParams.get("floID");
superNodeList = JSON.parse(sessionStorage.superNodeList); superNodeList = JSON.parse(sessionStorage.superNodeList);
kBucketObj.launchKBucket().then(function(result){ if(superNodeList.includes(selfID))
modSuperNode = true;
kBucketObj.launchKBucket().then(result => {
console.log(result) console.log(result)
listProfiles(); listProfiles();
displayProfile(profileID); displayProfile(profileID);
}).catch(function(error){ }).catch(error => {
console.log(error.message); console.log(error.message);
}); });
} }
@ -30,7 +32,7 @@ function displayProfile(profileID){
var errorMsg; var errorMsg;
if(!profileID) if(!profileID)
errorMsg = "Select a Profile to display"; errorMsg = "Select a Profile to display";
else if(!validateAddr(profileID)) else if(!encrypt.validateAddr(profileID))
errorMsg = "Invalid FLO ID"; errorMsg = "Invalid FLO ID";
else if(!(profileID in profiles)) else if(!(profileID in profiles))
errorMsg = "FLO ID not registered to FLO Tweet"; errorMsg = "FLO ID not registered to FLO Tweet";
@ -44,32 +46,29 @@ function displayProfile(profileID){
document.getElementById("profileName").innerHTML=profiles[profileID].name; document.getElementById("profileName").innerHTML=profiles[profileID].name;
document.getElementById("profileFloID").innerHTML='@'+profileID; document.getElementById("profileFloID").innerHTML='@'+profileID;
initselfWebSocket(); initselfWebSocket();
displayTweetFromIDB(profileID).then(function(result){ displayTweetFromIDB(profileID).then(result => {
connectToX(profileID).then(function(result){ connectToProfileServer(profileID).then(result => {
console.log(result); console.log(result);
profileServerStatus = true; profileServerStatus = true;
getTweetsFromX(profileID); pingProfileServerforNewTweets(profileID);
}).catch(function(error){ }).catch(error => {
console.log(error); console.log(error);
pingSuperNodeforNewTweets(profileID); pingSuperNodeforNewTweets(profileID);
profileServerStatus = false; profileServerStatus = false;
}); });
}).catch(function(error){ }).catch(error => {
console.log(error.message); console.log(error.message);
}); });
} }
function displayTweetFromIDB(floID){ function displayTweetFromIDB(floID){
return new Promise( return new Promise((resolve,reject) => {
function(resolve,reject){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) { idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
reject("Error in opening IndexedDB!"); idb.onsuccess = (event) => {
};
idb.onsuccess = function(event) {
var db = event.target.result; var db = event.target.result;
var obj = db.transaction("following", "readwrite").objectStore("following"); var obj = db.transaction("following", "readwrite").objectStore("following");
obj.get(floID).onsuccess = function (event) { obj.get(floID).onsuccess = (event) => {
var followBtn = document.getElementById("follow-button"); var followBtn = document.getElementById("follow-button");
if(event.target.result === undefined){ if(event.target.result === undefined){
followBtn.innerHTML = "+ Follow"; followBtn.innerHTML = "+ Follow";
@ -81,7 +80,7 @@ function displayTweetFromIDB(floID){
followBtn.disabled = false; followBtn.disabled = false;
} }
var obs = db.transaction("tweets", "readwrite").objectStore("tweets"); var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
obs.openCursor().onsuccess = function(event) { obs.openCursor().onsuccess = (event) => {
var cursor = event.target.result; var cursor = event.target.result;
if(cursor) { if(cursor) {
//console.log(cursor.value) //console.log(cursor.value)
@ -94,8 +93,7 @@ function displayTweetFromIDB(floID){
} }
db.close(); db.close();
}; };
} });
);
} }
function listProfiles(){ function listProfiles(){
@ -111,7 +109,6 @@ function listProfiles(){
</div></a>` </div></a>`
profileList.appendChild(element); profileList.appendChild(element);
} }
//document.getElementById("profileInfo").style.display = "none";
} }
function createTweetElement(floID,time,tweet){ function createTweetElement(floID,time,tweet){
@ -133,23 +130,16 @@ function createTweetElement(floID,time,tweet){
tweetDisplay.insertBefore(element, tweetDisplay.firstChild); tweetDisplay.insertBefore(element, tweetDisplay.firstChild);
} }
function connectToX(floID){ function connectToProfileServer(floID){
return new Promise( return new Promise((resolve,reject) => {
function(resolve,reject){
profileWebsocket = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws"); profileWebsocket = new WebSocket("ws://"+profiles[floID].onionAddr+"/ws");
profileWebsocket.onopen = function(ev){ profileWebsocket.onopen = (event) => { resolve("Connected to Profile Server!") };
resolve("Connected to Profile Server!"); profileWebsocket.onerror = (event) => { reject("Profile Server is offline!") };
}; profileWebsocket.onclose = (event) => { console.log("Disconnected from Profile Server!") };
profileWebsocket.onerror = function(ev) { profileWebsocket.onmessage = (event) => {
reject("Profile Server is offline!"); console.log(event.data);
};
profileWebsocket.onclose = function(ev) {
console.log("Disconnected from Profile Server!")
};
profileWebsocket.onmessage = function(evt){
console.log(evt.data);
try{ try{
var data = JSON.parse(evt.data); var data = JSON.parse(event.data);
var id = data.id; var id = data.id;
data = data.data; data = data.data;
if( floID!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floID].pubKey)) if( floID!=data.floID || !encrypt.verify(data.tweet,data.sign,profiles[floID].pubKey))
@ -160,73 +150,38 @@ function connectToX(floID){
console.log(error.message); console.log(error.message);
} }
} }
} });
);
}
function storeTweet(data,id){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("tweets", "readwrite").objectStore("tweets");
data.tweetID = `${data.time}_${data.floID}`;
obs.add(data);
var obsL = db.transaction("lastTweet", "readwrite").objectStore("lastTweet");
obsL.put(id,data.floID);
db.close();
};
}
function storeMsg(data){
var idb = indexedDB.open("FLO_Tweet");
idb.onerror = function(event) {
console.log("Error in opening IndexedDB!");
};
idb.onsuccess = function(event) {
var db = event.target.result;
var obs = db.transaction("messages", "readwrite").objectStore("messages");
data.msgID = `${data.time}_${data.floID}`;
obs.add(data);
db.close();
};
} }
function pingSuperNodeforNewTweets(floID){ function pingSuperNodeforNewTweets(floID){
getLastTweetCount(floID).then(function(result){ getLastTweetCount(floID).then(result => {
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID}) var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
sendDataToSuperNode(floID,data); sendDataToSuperNode(floID,data);
}).catch(function(error){ }).catch(error => {
console.log(error.message); console.log(error.message);
}); });
} }
function getTweetsFromX(floID){ function pingProfileServerforNewTweets(floID){
return new Promise( getLastTweetCount(floID).then(result => {
function (resolve,reject){ console.log(profileWebsocket);
getLastTweetCount(floID).then(function(result){ profileWebsocket.send(`>${result}`);
console.log(profileWebsocket); console.log("sent");
profileWebsocket.send(`>${result}`); resolve('Sent New tweet request to user server!');
console.log("sent"); }).catch(error => {
resolve('Sent New tweet request to user server!'); console.log(error.message);
}).catch(function(error){ });
console.log(error.message);
});
}
);
} }
function getLastTweetCount(floid){ function getLastTweetCount(floid){
return new Promise( return new Promise((resolve,reject) => {
function(resolve,reject){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onerror = (event) => { reject("Error in opening IndexedDB!") };
idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet'); var lastTweet = db.transaction('lastTweet', "readwrite").objectStore('lastTweet');
var lastTweetReq = lastTweet.get(floid); var lastTweetReq = lastTweet.get(floid);
lastTweetReq.onsuccess = function(event){ lastTweetReq.onsuccess = (event) => {
var result = event.target.result; var result = event.target.result;
if(result === undefined) if(result === undefined)
result = 0; result = 0;
@ -234,29 +189,26 @@ function getLastTweetCount(floid){
} }
db.close(); db.close();
}; };
} });
);
} }
function initselfWebSocket(){ function initselfWebSocket(){
selfWebsocket = new WebSocket("ws://"+location.host+"/ws"); selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
selfWebsocket.onopen = function(evt){ selfWebsocket.onopen = (event) => {
console.log("Connecting"); console.log("Connecting");
var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass)); var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
selfWebsocket.send("$"+serverPass); selfWebsocket.send("$"+serverPass);
}; };
selfWebsocket.onclose = function(evt){ selfWebsocket.onclose = (event) => { console.log("DISCONNECTED") };
console.log("DISCONNECTED"); selfWebsocket.onmessage = (event) => {
}; console.log(event.data);
selfWebsocket.onmessage = function(evt){ if(event.data[0] == '$')
console.log(evt.data);
if(evt.data[0] == '$')
return; return;
try{ try{
data = JSON.parse(evt.data); data = JSON.parse(event.data);
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("followers", "readwrite").objectStore("followers"); var obs = db.transaction("followers", "readwrite").objectStore("followers");
obs.add(data.sign,data.floID); obs.add(data.sign,data.floID);
@ -265,7 +217,7 @@ function initselfWebSocket(){
selfWebsocket.send(`F${data.floID}-${data.sign}`); selfWebsocket.send(`F${data.floID}-${data.sign}`);
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){ }else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("followers", "readwrite").objectStore("followers"); var obs = db.transaction("followers", "readwrite").objectStore("followers");
obs.delete(data.floID); obs.delete(data.floID);
@ -283,14 +235,14 @@ function initselfWebSocket(){
storeTweet({floID:data.floID,time:data.time,data:data.tweet},tid); storeTweet({floID:data.floID,time:data.time,data:data.tweet},tid);
createTweetElement(data.floID,data.time,data.tweet); createTweetElement(data.floID,data.time,data.tweet);
} }
}else if(modSuperNode){
superNodeMode(data);
} }
}catch(error){ }catch(error){
console.log(error.message) console.log(error.message)
} }
}; };
selfWebsocket.onerror = function(evt){ selfWebsocket.onerror = (event) => { console.log(event) };
console.log(evt);
};
} }
function follow(){ function follow(){
@ -301,12 +253,12 @@ function follow(){
if(profileServerStatus) if(profileServerStatus)
profileWebsocket.send(data); profileWebsocket.send(data);
else{ else{
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data}) var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data});
sendDataToSuperNode(profileID,SNdata) sendDataToSuperNode(profileID,SNdata);
} }
selfWebsocket.send(`f${profileID}-${sign}`) selfWebsocket.send(`f${profileID}-${sign}`)
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("following", "readwrite").objectStore("following"); var obs = db.transaction("following", "readwrite").objectStore("following");
obs.add(sign,profileID); obs.add(sign,profileID);
@ -321,12 +273,12 @@ function follow(){
if(profileServerStatus) if(profileServerStatus)
profileWebsocket.send(data); profileWebsocket.send(data);
else{ else{
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data}) var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:profileID,data:data});
sendDataToSuperNode(profileID,SNdata) sendDataToSuperNode(profileID,SNdata);
} }
selfWebsocket.send(`u${profileID}`) selfWebsocket.send(`u${profileID}`)
var idb = indexedDB.open("FLO_Tweet"); var idb = indexedDB.open("FLO_Tweet");
idb.onsuccess = function(event) { idb.onsuccess = (event) => {
var db = event.target.result; var db = event.target.result;
var obs = db.transaction("following", "readwrite").objectStore("following"); var obs = db.transaction("following", "readwrite").objectStore("following");
obs.delete(profileID); obs.delete(profileID);
@ -336,4 +288,3 @@ function follow(){
followBtn.innerHTML = "+ Follow"; followBtn.innerHTML = "+ Follow";
} }
} }