diff --git a/index.html b/index.html
index 9a5325e..aeac7e9 100644
--- a/index.html
+++ b/index.html
@@ -61,35 +61,21 @@
//load messages from IDB and render them
console.log(`Loading Data! Please Wait...`)
- messenger.initUserDB().then(result => {
- console.log(result)
- //Check for availble bg image
- setBgImage()
- messenger.loadDataFromIDB().then(data => {
- console.log(data)
- floGlobals.appendix = data.appendix;
- floGlobals.groups = data.groups;
- floGlobals.chats = data.chats
- floGlobals['marked'] = data.marked
- renderChatList()
- renderMailList(data.mails, false)
- renderMarked(data.marked)
- messenger.setUIcallbacks(renderDirectUI, renderGroupUI)
- messenger.requestDirectInbox()
- .then(r => console.log("DirectConn:", r))
- .catch(e => console.error("Request error:", e))
- messenger.requestGroupInbox()
- .then(r => console.log(r))
- console.log(`Load Successful!`)
- if(isPinSet){
- loadPage()
- }
- }).catch(error => {
- //console.error(`Failed to load data`)
- notify(error, "error")
- })
- })
-
+ //Check for availble bg image
+ setBgImage();
+ //Set UI render functions
+ messenger.renderUI.chats = renderChatList;
+ messenger.renderUI.directChat = renderDirectUI;
+ messenger.renderUI.groupChat = renderGroupUI;
+ messenger.renderUI.mails = m => renderMailList(m, false);
+ messenger.renderUI.marked = renderMarked;
+ //init messenger
+ messenger.init().then(result => {
+ console.log(result);
+ if(isPinSet){
+ loadPage()
+ }
+ }).catch(error => notify(error, "error"));
}).catch(error => notify(error, "error"))
}
@@ -1143,7 +1129,7 @@
getRef('add_as_contact_option').classList.remove('hide-completely')
}
- const markUnread = floGlobals.marked[clickedContact.floID]?.includes('unread')
+ const markUnread = messenger.marked[clickedContact.floID]?.includes('unread')
if (markUnread) {
getRef('mark_read_option').classList.remove('hide-completely')
getRef('mark_unread_option').classList.add('hide-completely')
@@ -1162,7 +1148,7 @@
getRef("contact_initial").innerHTML = `
`
- if (floGlobals.groups[clickedContact['floID']].admin === myFloID)
+ if (messenger.groups[clickedContact['floID']].admin === myFloID)
getRef('contact_name').disabled = false
else
getRef('contact_name').disabled = true
@@ -1180,7 +1166,7 @@
case 'contacts_popup':
const contacts = []
for (contact in floGlobals.contacts) {
- if (!floGlobals.groups[activeChat.floID].members.includes(contact) && contact in floGlobals.pubKeys) {
+ if (!messenger.groups[activeChat.floID].members.includes(contact) && contact in floGlobals.pubKeys) {
contacts.push(contact)
}
}
@@ -1382,8 +1368,8 @@
let name
if (floGlobals.contacts[floID])
name = floGlobals.contacts[floID]
- else if (floGlobals.groups[floID])
- name = floGlobals.groups[floID].name
+ else if (messenger.groups[floID])
+ name = messenger.groups[floID].name
else if (floID === myFloID)
name = 'You'
else
@@ -1678,7 +1664,7 @@
initial.innerHTML = `
`
- cardContainer.querySelector('.name').textContent = floGlobals.groups[floID].name
+ cardContainer.querySelector('.name').textContent = messenger.groups[floID].name
}
else {
cardContainer.querySelector('.name').textContent = name !== 'Unknown' ? name : floID
@@ -1713,7 +1699,7 @@
}
}
if (type === 'group' && lastMessage.time === 0) {
- lastMessage.time = floGlobals.groups[floID].created
+ lastMessage.time = messenger.groups[floID].created
}
let lastText = document.createElement('p')
if ((type === 'chat' && lastMessage.category === 'sent') || (type === 'group' && lastMessage.sender === myFloID)) {
@@ -1856,7 +1842,7 @@
else if (admin) {
if (newMembers.length) {
const cards = document.createDocumentFragment()
- const { admin } = floGlobals.groups[groupID]
+ const { admin } = messenger.groups[groupID]
newMembers.forEach(member => {
let eventCard = document.createElement('p')
eventCard.classList.add('group-event-card')
@@ -1872,7 +1858,7 @@
}
else if (rmMembers.length) {
const cards = document.createDocumentFragment()
- const { admin } = floGlobals.groups[groupID]
+ const { admin } = messenger.groups[groupID]
rmMembers.forEach(member => {
let eventCard = document.createElement('p')
eventCard.classList.add('group-event-card')
@@ -2134,7 +2120,7 @@
clickedContact['chatCard'] = contact
clickedContact['floID'] = contact.getAttribute("flo-id")
clickedContact['name'] = contact.getAttribute("name")
- clickedContact['isGroup'] = floGlobals.groups.hasOwnProperty(clickedContact['floID'])
+ clickedContact['isGroup'] = messenger.groups.hasOwnProperty(clickedContact['floID'])
showPopup('contact_details_popup')
}, 500)
getRef('chat_page').addEventListener('touchmove', handleTouchMove)
@@ -2171,7 +2157,7 @@
clickedContact['chatCard'] = contact
clickedContact['floID'] = contact.getAttribute("flo-id")
clickedContact['name'] = contact.getAttribute("name")
- clickedContact['isGroup'] = floGlobals.groups.hasOwnProperty(clickedContact['floID'])
+ clickedContact['isGroup'] = messenger.groups.hasOwnProperty(clickedContact['floID'])
if (clickedContact['floID'] === myFloID) return
@@ -2744,15 +2730,15 @@
getRef('contacts_container').append(frag)
}
- async function renderChatList() {
+ async function renderChatList(chatOrder) {
const frag = document.createDocumentFragment()
getRef('chat_container').innerHTML = ''
- for (floID of messenger.getChatOrder().mixed) {
- const markUnread = floGlobals.marked[floID]?.includes('unread')
+ for (floID of chatOrder) {
+ const markUnread = messenger.marked[floID]?.includes('unread')
let type
- if (floGlobals.chats[floID])
+ if (messenger.chats[floID])
type = 'chat'
- else if (floGlobals.groups[floID])
+ else if (messenger.groups[floID])
type = 'group'
frag.append(render.contactCard(floID, { type, markUnread }))
}
@@ -2927,7 +2913,7 @@
backgroundColor = contact.getAttribute('background-color')
activeChat['floID'] = floID
- activeChat['isGroup'] = floGlobals.groups[floID] ? true : false
+ activeChat['isGroup'] = messenger.groups[floID] ? true : false
getRef("chat_dp").setAttribute('style', `color: ${textColor}; background-color: ${backgroundColor};`)
getRef("receiver_name").textContent = getContactName(floID);
if (activeChat.isGroup) {
@@ -3235,12 +3221,12 @@
getRef("chat_dp").innerHTML = `
`
- getRef("last_interaction_time").textContent = `Created ${getFormatedTime(floGlobals.groups[floID].created)}`;
+ getRef("last_interaction_time").textContent = `Created ${getFormatedTime(messenger.groups[floID].created)}`;
getRef("chat_type").textContent = `Group FLO ID`;
getRef('group_members_list').innerHTML = ''
- floGlobals.groups[floID].members.forEach(member => {
- let isAdmin = floGlobals.groups[floID].admin === member ? true : false
+ messenger.groups[floID].members.forEach(member => {
+ let isAdmin = messenger.groups[floID].admin === member ? true : false
frag.append(render.contactCard(member, { type: 'contact', contactOnly: true, isAdmin }))
})
getRef('group_members_list').append(frag)
@@ -3250,9 +3236,9 @@
getRef('delete_chat_button').classList.add('hide-completely')
- getRef("group_description").value = floGlobals.groups[floID].description === '' ? 'Add group description' : floGlobals.groups[floID].description;
+ getRef("group_description").value = messenger.groups[floID].description === '' ? 'Add group description' : messenger.groups[floID].description;
- if (floGlobals.groups[activeChat['floID']].admin === myFloID) {
+ if (messenger.groups[activeChat['floID']].admin === myFloID) {
getRef("chat_name").disabled = false
getRef('group_description').disabled = false
getRef('edit_group_button').classList.remove('hide-completely')
diff --git a/scripts/messenger.js b/scripts/messenger.js
index 7546c37..fc8c837 100644
--- a/scripts/messenger.js
+++ b/scripts/messenger.js
@@ -1,6 +1,62 @@
(function() {
const messenger = window.messenger = {};
+ const expiredKeys = {};
+
+ const UI = {
+ group: (d, e) => console.log(d, e),
+ direct: (d, e) => console.log(d, e),
+ chats: (c) => console.log(c),
+ mails: (m) => console.log(m),
+ marked: (r) => console.log(r)
+ };
+ messenger.renderUI = {};
+ Object.defineProperties(messenger.renderUI, {
+ chats: {
+ set: ui_fn => UI.chats = ui_fn
+ },
+ directChat: {
+ set: ui_fn => UI.direct = ui_fn
+ },
+ groupChat: {
+ set: ui_fn => UI.group = ui_fn
+ },
+ mails: {
+ set: ui_fn => UI.mails = ui_fn
+ },
+ marked: {
+ set: ui_fn => UI.marked = ui_fn
+ },
+ });
+
+ const _loaded = {};
+ Object.defineProperties(messenger, {
+ chats: {
+ get: _loaded.chats
+ },
+ groups: {
+ get: _loaded.groups
+ },
+ blocked: {
+ get: _loaded.blocked
+ },
+ marked: {
+ get: _loaded.marked
+ }
+ });
+
+ var directConnID, groupConnID = {};
+ messenger.conn = {};
+ Object.defineProperties(messenger.conn, {
+ direct: {
+ get: directConnID
+ },
+ group: {
+ get: Object.assign({}, groupConnID),
+ value: g_id => groupConnID[g_id]
+ }
+ });
+
function sendRaw(message, recipient, type, encrypt = null, comment = undefined) {
return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(recipient))
@@ -21,11 +77,11 @@
})
}
- function encrypt(value, key = floGlobals.appendix.AESKey) {
+ function encrypt(value, key = _loaded.appendix.AESKey) {
return Crypto.AES.encrypt(value, key)
}
- function decrypt(value, key = floGlobals.appendix.AESKey) {
+ function decrypt(value, key = _loaded.appendix.AESKey) {
return Crypto.AES.decrypt(value, key)
}
@@ -51,8 +107,7 @@
if (!result || !result.includes(mark))
return resolve("Mark doesnot exist")
else {
- result.splice(result.indexOf(mark),
- 1); //remove the mark from the list of marks
+ result.splice(result.indexOf(mark), 1); //remove the mark from the list of marks
compactIDB.writeData("marked", result, key)
.then(result => resolve("Mark removed"))
.catch(error => reject(error))
@@ -61,13 +116,12 @@
})
}
- const UIcallback = {
- group: (d, e) => console.log(d, e),
- direct: (d, e) => console.log(d, e)
- }
-
- function groupConn(groupID) {
- console.debug(UIcallback);
+ function requestGroupInbox(groupID) {
+ console.debug(UI);
+ if (groupConnID[groupID]) { //close existing request connection (if any)
+ floCloudAPI.closeRequest(groupConnID[groupID]);
+ delete groupConnID[groupID];
+ }
let callbackFn = function(dataSet, error) {
if (error)
return console.error(error)
@@ -78,7 +132,7 @@
let infoChange = false;
for (let vc in dataSet) {
if (groupID !== dataSet[vc].receiverID ||
- !floGlobals.groups[groupID].members.includes(dataSet[vc].senderID))
+ !_loaded.groups[groupID].members.includes(dataSet[vc].senderID))
continue;
try {
let data = {
@@ -86,33 +140,33 @@
sender: dataSet[vc].senderID,
groupID: dataSet[vc].receiverID
}
- let k = floGlobals.groups[groupID].eKey;
- if (floGlobals.expiredKeys[groupID]) {
- var ex = Object.keys(floGlobals.expiredKeys[groupID]).sort()
+ let k = _loaded.groups[groupID].eKey;
+ if (expiredKeys[groupID]) {
+ var ex = Object.keys(expiredKeys[groupID]).sort()
while (ex.lenght && vc > ex[0]) ex.shift()
if (ex.length)
- k = floGlobals.expiredKeys[groupID][ex.shift()]
+ k = expiredKeys[groupID][ex.shift()]
}
dataSet[vc].message = decrypt(dataSet[vc].message, k)
//store the pubKey if not stored already
floDapps.storePubKey(dataSet[vc].senderID, dataSet[vc].pubKey)
if (dataSet[vc].type === "GROUP_MSG")
data.message = encrypt(dataSet[vc].message);
- else if (data.sender === floGlobals.groups[groupID].admin) {
- let groupInfo = floGlobals.groups[groupID]
+ else if (data.sender === _loaded.groups[groupID].admin) {
+ let groupInfo = _loaded.groups[groupID]
data.admin = true;
if (dataSet[vc].type === "ADD_MEMBERS") {
data.newMembers = dataSet[vc].message.split("|")
data.note = dataSet[vc].comment
- groupInfo.members = [...new Set(groupInfo.members.concat(data
- .newMembers))]
+ groupInfo.members = [...new Set(groupInfo.members.concat(data.newMembers))]
} else if (dataSet[vc].type === "RM_MEMBERS") {
data.rmMembers = dataSet[vc].message.split("|")
data.note = dataSet[vc].comment
- groupInfo.members = groupInfo.members.filter(m => !data.rmMembers
- .includes(m))
- if (data.rmMembers.includes(myFloID))
- groupInfo.status = false
+ groupInfo.members = groupInfo.members.filter(m => !data.rmMembers.includes(m))
+ if (data.rmMembers.includes(myFloID)) {
+ disableGroup(groupID);
+ return;
+ }
} else if (dataSet[vc].type === "UP_DESCRIPTION") {
data.description = dataSet[vc].message
groupInfo.description = data.description
@@ -131,40 +185,35 @@
console.log(data)
if (data.sender !== myFloID)
addMark(data.groupID, "unread")
- if (!floGlobals.appendix[`lastReceived_${groupID}`] ||
- floGlobals.appendix[`lastReceived_${groupID}`] < vc)
- floGlobals.appendix[`lastReceived_${groupID}`] = vc;
+ if (!_loaded.appendix[`lastReceived_${groupID}`] ||
+ _loaded.appendix[`lastReceived_${groupID}`] < vc)
+ _loaded.appendix[`lastReceived_${groupID}`] = vc;
} catch (error) {
console.log(error)
}
}
- compactIDB.writeData("appendix", floGlobals.appendix[`lastReceived_${groupID}`],
+ compactIDB.writeData("appendix", _loaded.appendix[`lastReceived_${groupID}`],
`lastReceived_${groupID}`);
if (infoChange) {
let newInfo = {
- ...floGlobals.groups[groupID]
+ ..._loaded.groups[groupID]
}
newInfo.eKey = encrypt(newInfo.eKey)
compactIDB.writeData("groups", newInfo, groupID)
}
console.debug(newInbox);
- UIcallback.group(newInbox);
+ UI.group(newInbox);
}
- return floCloudAPI.requestApplicationData(null, {
- receiverID: groupID,
- lowerVectorClock: floGlobals.appendix[`lastReceived_${groupID}`] + 1,
- callback: callbackFn
- })
+ floCloudAPI.requestApplicationData(null, {
+ receiverID: groupID,
+ lowerVectorClock: _loaded.appendix[`lastReceived_${groupID}`] + 1,
+ callback: callbackFn
+ }).then(conn_id => groupConnID[groupID] = conn_id)
+ .catch(error => console.error(`request-group(${groupID}):`, error))
+
}
- messenger.setUIcallbacks = function(directUI = null, groupUI = null) {
- if (directUI instanceof Function)
- UIcallback["direct"] = directUI
- if (groupUI instanceof Function)
- UIcallback["group"] = groupUI
- }
-
- messenger.initUserDB = function() {
+ const initUserDB = function() {
return new Promise((resolve, reject) => {
var obj = {
messages: {},
@@ -173,6 +222,7 @@
chats: {},
groups: {},
gkeys: {},
+ blocked: {},
appendix: {},
userSettings: {}
}
@@ -184,8 +234,30 @@
})
}
+ messenger.blockUser = function(floID) {
+ return new Promise((resolve, reject) => {
+ if (_loaded.blocked.has(floID))
+ return resolve("User is already blocked");
+ compactIDB.addData("blocked", true, floID).then(result => {
+ _loaded.blocked.add(floID);
+ resolve("Blocked User: " + floID);
+ }).catch(error => reject(error))
+ })
+ }
+
+ messenger.unblockUser = function(floID) {
+ return new Promise((resolve, reject) => {
+ if (!_loaded.blocked.has(floID))
+ return resolve("User is not blocked");
+ compactIDB.removeData("blocked", floID).then(result => {
+ _loaded.blocked.delete(floID);
+ resolve("Unblocked User: " + floID);
+ }).catch(error => reject(error))
+ })
+ }
+
messenger.sendMessage = function(message, receiver) {
- return new Promise(async (resolve, reject) => {
+ return new Promise((resolve, reject) => {
sendRaw(message, receiver, "MESSAGE").then(result => {
let vc = result.vectorClock;
let data = {
@@ -194,7 +266,7 @@
category: 'sent',
message: encrypt(message)
}
- floGlobals.chats[receiver] = parseInt(vc)
+ _loaded.chats[receiver] = parseInt(vc)
compactIDB.writeData("chats", parseInt(vc), receiver)
compactIDB.addData("messages", {
...data
@@ -208,7 +280,7 @@
}
messenger.sendMail = function(subject, content, recipients, prev = null) {
- return new Promise(async (resolve, reject) => {
+ return new Promise((resolve, reject) => {
if (!Array.isArray(recipients))
recipients = [recipients]
let mail = {
@@ -240,112 +312,114 @@
})
}
- messenger.requestDirectInbox = function() {
- return new Promise((resolve, reject) => {
- let callbackFn = function(dataSet, error) {
- if (error)
- return console.error(error)
- let newInbox = {
- messages: {},
- mails: {},
- newgroups: [],
- keyrevoke: []
- }
- console.log(dataSet)
- for (let vc in dataSet) {
- try {
- //store the pubKey if not stored already
- floDapps.storePubKey(dataSet[vc].senderID, dataSet[vc].pubKey)
- if (dataSet[vc].message instanceof Object && "secret" in dataSet[vc].message)
- dataSet[vc].message = floCrypto.decryptData(dataSet[vc].message, myPrivKey)
- if (dataSet[vc].type === "MESSAGE") {
- //process as message
- let dm = {
- time: dataSet[vc].time,
- floID: dataSet[vc].senderID,
- category: "received",
- message: encrypt(dataSet[vc].message)
- }
- compactIDB.addData("messages", {
- ...dm
- }, `${dm.floID}|${vc}`)
- floGlobals.chats[dm.floID] = parseInt(vc)
- compactIDB.writeData("chats", parseInt(vc), dm.floID)
- dm.message = dataSet[vc].message;
- newInbox.messages[vc] = dm;
- addMark(dm.floID, "unread")
- } else if (dataSet[vc].type === "MAIL") {
- //process as mail
- let data = JSON.parse(dataSet[vc].message);
- let mail = {
- time: dataSet[vc].time,
- from: dataSet[vc].senderID,
- to: [myFloID],
- subject: data.subject,
- content: encrypt(data.content),
- ref: data.ref,
- prev: data.prev
- }
- compactIDB.addData("mails", {
- ...mail
- }, mail.ref);
- mail.content = data.content;
- newInbox.mails[mail.ref] = mail;
- addMark(mail.ref, "unread")
- } else if (dataSet[vc].type === "CREATE_GROUP") {
- //process create group
- let groupInfo = JSON.parse(dataSet[vc].message);
- let h = ["groupID", "created", "admin"].map(x => groupInfo[x]).join('|')
- if (groupInfo.admin === dataSet[vc].senderID &&
- floCrypto.verifySign(h, groupInfo.hash, groupInfo.pubKey) &&
- floCrypto.getFloID(groupInfo.pubKey) === groupInfo.groupID) {
- let eKey = groupInfo.eKey
- groupInfo.eKey = encrypt(eKey)
- compactIDB.writeData("groups", {
- ...groupInfo
- }, groupInfo.groupID)
- groupInfo.eKey = eKey
- floGlobals.groups[groupInfo.groupID] = groupInfo
- groupConn(groupInfo.groupID)
- newInbox.newgroups.push(groupInfo.groupID)
- }
- } else if (dataSet[vc].type === "REVOKE_KEY") {
- let r = JSON.parse(dataSet[vc].message);
- let groupInfo = floGlobals.groups[r.groupID]
- if (dataSet[vc].senderID === groupInfo.admin) {
- if (typeof floGlobals.expiredKeys[r.groupID] !== "object")
- floGlobals.expiredKeys[r.groupID] = {}
- floGlobals.expiredKeys[r.groupID][vc] = groupInfo.eKey
- let eKey = r.newKey
- groupInfo.eKey = encrypt(eKey);
- compactIDB.writeData("groups", {
- ...groupInfo
- }, groupInfo.groupID)
- groupInfo.eKey = eKey
- newInbox.keyrevoke.push(groupInfo.groupID)
- }
+ const requestDirectInbox = function() {
+ if (directInboxConn) { //close existing request connection (if any)
+ floCloudAPI.closeRequest(directConnID);
+ directConnID = undefined;
+ }
+ let callbackFn = function(dataSet, error) {
+ if (error)
+ return console.error(error)
+ let newInbox = {
+ messages: {},
+ mails: {},
+ newgroups: [],
+ keyrevoke: []
+ }
+ console.debug("Check if key is vc", dataSet);
+ for (let vc in dataSet) {
+ try {
+ //store the pubKey if not stored already
+ floDapps.storePubKey(dataSet[vc].senderID, dataSet[vc].pubKey);
+ if (_loaded.blocked.has(dataSet[vc].senderID) && dataSet[vc].type !== "REVOKE_KEY")
+ throw "blocked-user";
+ if (dataSet[vc].message instanceof Object && "secret" in dataSet[vc].message)
+ dataSet[vc].message = floCrypto.decryptData(dataSet[vc].message, myPrivKey)
+ if (dataSet[vc].type === "MESSAGE") {
+ //process as message
+ let dm = {
+ time: dataSet[vc].time,
+ floID: dataSet[vc].senderID,
+ category: "received",
+ message: encrypt(dataSet[vc].message)
+ }
+ compactIDB.addData("messages", {
+ ...dm
+ }, `${dm.floID}|${vc}`)
+ _loaded.chats[dm.floID] = parseInt(vc)
+ compactIDB.writeData("chats", parseInt(vc), dm.floID)
+ dm.message = dataSet[vc].message;
+ newInbox.messages[vc] = dm;
+ addMark(dm.floID, "unread")
+ } else if (dataSet[vc].type === "MAIL") {
+ //process as mail
+ let data = JSON.parse(dataSet[vc].message);
+ let mail = {
+ time: dataSet[vc].time,
+ from: dataSet[vc].senderID,
+ to: [myFloID],
+ subject: data.subject,
+ content: encrypt(data.content),
+ ref: data.ref,
+ prev: data.prev
+ }
+ compactIDB.addData("mails", {
+ ...mail
+ }, mail.ref);
+ mail.content = data.content;
+ newInbox.mails[mail.ref] = mail;
+ addMark(mail.ref, "unread")
+ } else if (dataSet[vc].type === "CREATE_GROUP") {
+ //process create group
+ let groupInfo = JSON.parse(dataSet[vc].message);
+ let h = ["groupID", "created", "admin"].map(x => groupInfo[x]).join('|')
+ if (groupInfo.admin === dataSet[vc].senderID &&
+ floCrypto.verifySign(h, groupInfo.hash, groupInfo.pubKey) &&
+ floCrypto.getFloID(groupInfo.pubKey) === groupInfo.groupID) {
+ let eKey = groupInfo.eKey
+ groupInfo.eKey = encrypt(eKey)
+ compactIDB.writeData("groups", {
+ ...groupInfo
+ }, groupInfo.groupID)
+ groupInfo.eKey = eKey
+ _loaded.groups[groupInfo.groupID] = groupInfo
+ requestGroupInbox(groupInfo.groupID)
+ newInbox.newgroups.push(groupInfo.groupID)
+ }
+ } else if (dataSet[vc].type === "REVOKE_KEY") {
+ let r = JSON.parse(dataSet[vc].message);
+ let groupInfo = _loaded.groups[r.groupID]
+ if (dataSet[vc].senderID === groupInfo.admin) {
+ if (typeof expiredKeys[r.groupID] !== "object")
+ expiredKeys[r.groupID] = {}
+ expiredKeys[r.groupID][vc] = groupInfo.eKey
+ let eKey = r.newKey
+ groupInfo.eKey = encrypt(eKey);
+ compactIDB.writeData("groups", {
+ ...groupInfo
+ }, groupInfo.groupID)
+ groupInfo.eKey = eKey
+ newInbox.keyrevoke.push(groupInfo.groupID)
}
- } catch (error) {
- console.log(error)
- } finally {
- if (floGlobals.appendix.lastReceived < vc)
- floGlobals.appendix.lastReceived = vc;
}
+ } catch (error) {
+ if (error !== "blocked-user")
+ console.log(error);
+ } finally {
+ if (_loaded.appendix.lastReceived < vc)
+ _loaded.appendix.lastReceived = vc;
}
- compactIDB.writeData("appendix", floGlobals.appendix.lastReceived, "lastReceived");
- console.debug(newInbox);
- UIcallback.direct(newInbox)
}
-
- var options = {
+ compactIDB.writeData("appendix", _loaded.appendix.lastReceived, "lastReceived");
+ console.debug(newInbox);
+ UI.direct(newInbox)
+ }
+ floCloudAPI.requestApplicationData(null, {
receiverID: myFloID,
- lowerVectorClock: floGlobals.appendix.lastReceived + 1,
+ lowerVectorClock: _loaded.appendix.lastReceived + 1,
callback: callbackFn
- }
- floCloudAPI.requestApplicationData(null, options)
- .then(result => resolve(result))
- .catch(error => reject(error))
- })
+ }).then(conn_id => directConnID = conn_id)
+ .catch(error => console.error("request-direct:", error));
}
messenger.getMail = function(mailRef) {
@@ -357,35 +431,32 @@
});
}
- messenger.getChatOrder = function(type = ["direct", "group", "mixed"]) {
- if (typeof type === "string")
- type = type.split('|')
- let result = {}
- if (type.includes("direct"))
- result.direct = Object.keys(floGlobals.chats).map(a => [floGlobals.chats[a], a])
- .sort((a, b) => b[0] - a[0]).map(a => a[1])
- if (type.includes("group"))
- result.group = Object.keys(floGlobals.groups).map(a => [parseInt(floGlobals.appendix[`lastReceived_${a}`]), a])
- .sort((a, b) => b[0] - a[0]).map(a => a[1])
- if (type.includes("mixed"))
- result.mixed = Object.keys(floGlobals.chats).map(a => [floGlobals.chats[a], a])
- .concat(Object.keys(floGlobals.groups).map(a => [parseInt(floGlobals.appendix[`lastReceived_${a}`]), a]))
- .sort((a, b) => b[0] - a[0]).map(a => a[1])
- if (type.length === 1)
- result = result[type[0]]
- return result
+ const getChatOrder = messenger.getChatOrder = function(seperate = false) {
+ let result;
+ if (seperate) {
+ result = {};
+ result.direct = Object.keys(_loaded.chats).map(a => [_loaded.chats[a], a])
+ .sort((a, b) => b[0] - a[0]).map(a => a[1]);
+ result.group = Object.keys(_loaded.groups).map(a => [parseInt(_loaded.appendix[`lastReceived_${a}`]), a])
+ .sort((a, b) => b[0] - a[0]).map(a => a[1]);
+ } else {
+ result = Object.keys(_loaded.chats).map(a => [_loaded.chats[a], a])
+ .concat(Object.keys(_loaded.groups).map(a => [parseInt(_loaded.appendix[`lastReceived_${a}`]), a]))
+ .sort((a, b) => b[0] - a[0]).map(a => a[1])
+ }
+ return result;
}
messenger.storeContact = function(floID, name) {
return floDapps.storeContact(floID, name)
}
- const loadDataFromIDB = messenger.loadDataFromIDB = function(dataList = 'default') {
+ const loadDataFromIDB = function(defaultList = true) {
return new Promise((resolve, reject) => {
- if (dataList === 'default')
- dataList = ["mails", "marked", "groups", "chats", "appendix"]
- else if (dataList === 'all')
- dataList = ["messages", "mails", "marked", "chats", "groups", "gkeys", "appendix"]
+ if (defaultList)
+ dataList = ["mails", "marked", "groups", "chats", "blocked", "appendix"]
+ else
+ dataList = ["messages", "mails", "marked", "chats", "groups", "gkeys", "blocked", "appendix"]
let promises = []
for (var i = 0; i < dataList.length; i++)
promises[i] = compactIDB.readAllData(dataList[i])
@@ -393,7 +464,7 @@
let data = {}
for (var i = 0; i < dataList.length; i++)
data[dataList[i]] = results[i]
- data.appendix.lastReceived = data.appendix.lastReceived || '0'
+ data.appendix.lastReceived = data.appendix.lastReceived || '0';
if (data.appendix.AESKey) {
try {
let AESKey = floCrypto.decryptData(data.appendix.AESKey, myPrivKey);
@@ -401,16 +472,16 @@
if (dataList.includes("messages"))
for (let m in data.messages)
if (data.messages[m].message)
- data.messages[m].message = decrypt(data.messages[m].message, AESKey)
+ data.messages[m].message = decrypt(data.messages[m].message, AESKey);
if (dataList.includes("mails"))
for (let m in data.mails)
- data.mails[m].content = decrypt(data.mails[m].content, AESKey)
+ data.mails[m].content = decrypt(data.mails[m].content, AESKey);
if (dataList.includes("groups"))
for (let g in data.groups)
- data.groups[g].eKey = decrypt(data.groups[g].eKey, AESKey)
+ data.groups[g].eKey = decrypt(data.groups[g].eKey, AESKey);
if (dataList.includes("gkeys"))
for (let k in data.gkeys)
- data.gkeys[k] = decrypt(data.gkeys[k], AESKey)
+ data.gkeys[k] = decrypt(data.gkeys[k], AESKey);
resolve(data)
} catch (error) {
reject("Corrupted AES Key");
@@ -418,7 +489,7 @@
} else {
if (Object.keys(data.mails).length)
return reject("AES Key not Found")
- let AESKey = floCrypto.randString(32);
+ let AESKey = floCrypto.randString(32, false);
let encryptedKey = floCrypto.encryptData(AESKey, myPubKey);
compactIDB.addData("appendix", encryptedKey, "AESKey").then(result => {
data.appendix.AESKey = AESKey;
@@ -430,14 +501,14 @@
}
messenger.addMark = function(key, mark) {
- if (floGlobals.marked.hasOwnProperty(key) && !floGlobals.marked[key].includes(mark))
- floGlobals.marked[key].push(mark)
+ if (_loaded.marked.hasOwnProperty(key) && !_loaded.marked[key].includes(mark))
+ _loaded.marked[key].push(mark)
return addMark(key, mark)
}
messenger.removeMark = function(key, mark) {
- if (floGlobals.marked.hasOwnProperty(key))
- floGlobals.marked[key] = floGlobals.marked[key].filter(v => v !== mark)
+ if (_loaded.marked.hasOwnProperty(key))
+ _loaded.marked[key] = _loaded.marked[key].filter(v => v !== mark)
return removeMark(key, mark)
}
@@ -491,7 +562,7 @@
messenger.backupData = function() {
return new Promise((resolve, reject) => {
- loadDataFromIDB("all").then(data => {
+ loadDataFromIDB(false).then(data => {
delete data.appendix.AESKey;
data.contacts = floGlobals.contacts;
data.pubKeys = floGlobals.pubKeys;
@@ -556,14 +627,14 @@
for (let g in data.groups)
data.groups[g].eKey = encrypt(data.groups[g].eKey)
for (let c in data.chats)
- if (data.chats[c] <= floGlobals.chats[c])
+ if (data.chats[c] <= _loaded.chats[c])
delete data.chats[c]
for (let l in data.appendix)
- if (l.startsWith('lastReceived') && data.appendix[l] <= floGlobals.appendix[l])
+ if (l.startsWith('lastReceived') && data.appendix[l] <= _loaded.appendix[l])
delete data.appendix[l]
for (let c in data.contacts)
if (c in floGlobals.contacts)
- delete data.contact[c]
+ delete data.contacts[c]
for (let p in data.pubKeys)
if (p in floGlobals.pubKeys)
delete data.pubKeys[p]
@@ -623,12 +694,12 @@
groupInfo.hash = floCrypto.signData(h, id.privKey)
let eKey = floCrypto.randString(16, false)
groupInfo.eKey = encrypt(eKey)
- p1 = compactIDB.addData("groups", groupInfo, id.floID)
- p2 = compactIDB.addData("gkeys", encrypt(id.privKey), id.floID)
+ let p1 = compactIDB.addData("groups", groupInfo, id.floID)
+ let p2 = compactIDB.addData("gkeys", encrypt(id.privKey), id.floID)
Promise.all([p1, p2]).then(r => {
groupInfo.eKey = eKey
- floGlobals.groups[id.floID] = groupInfo;
- groupConn(id.floID)
+ _loaded.groups[id.floID] = groupInfo;
+ requestGroupInbox(id.floID)
resolve(groupInfo)
}).catch(e => reject(e))
})
@@ -636,7 +707,7 @@
messenger.changeGroupName = function(groupID, name) {
return new Promise((resolve, reject) => {
- let groupInfo = floGlobals.groups[groupID]
+ let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!")
let message = encrypt(name, groupInfo.eKey)
@@ -648,7 +719,7 @@
messenger.changeGroupDescription = function(groupID, description) {
return new Promise((resolve, reject) => {
- let groupInfo = floGlobals.groups[groupID]
+ let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!")
let message = encrypt(description, groupInfo.eKey)
@@ -674,11 +745,10 @@
else if (imem2.length)
return reject(`Invalid Members (pubKey not available): ${imem2}`)
//send new newMem list to existing members
- let groupInfo = floGlobals.groups[groupID]
+ let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!")
//send groupInfo to new newMem
- let k = groupInfo.eKey
groupInfo = JSON.stringify(groupInfo)
let promises = newMem.map(m => sendRaw(groupInfo, m, "CREATE_GROUP", true));
Promise.allSettled(promises).then(results => {
@@ -689,8 +759,8 @@
success.push(newMem[i])
else if (results[i].status === "rejected")
failed.push(newMem[i])
- console.log(success.join("|"), k)
- let message = encrypt(success.join("|"), k)
+ console.log(success.join("|"))
+ let message = encrypt(success.join("|"), groupInfo.eKey)
sendRaw(message, groupID, "ADD_MEMBERS", false, note)
.then(r => resolve(`Members added: ${success}`))
.catch(e => reject(e))
@@ -702,16 +772,16 @@
return new Promise((resolve, reject) => {
if (!Array.isArray(rmMem) && typeof rmMem === "string")
rmMem = [rmMem]
- let groupInfo = floGlobals.groups[groupID]
+ let groupInfo = _loaded.groups[groupID]
let imem = rmMem.filter(m => !groupInfo.members.includes(m))
if (imem.length)
return reject(`Invalid members: ${imem}`)
if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!")
let message = encrypt(rmMem.join("|"), groupInfo.eKey)
- p1 = sendRaw(message, groupID, "RM_MEMBERS", false, note)
+ let p1 = sendRaw(message, groupID, "RM_MEMBERS", false, note)
groupInfo.members = groupInfo.members.filter(m => !rmMem.includes(m))
- p2 = revokeKey(groupID)
+ let p2 = revokeKey(groupID)
Promise.all([p1, p2])
.then(r => resolve(`Members removed: ${rmMem}`))
.catch(e => reject(e))
@@ -720,7 +790,7 @@
const revokeKey = messenger.revokeKey = function(groupID) {
return new Promise((resolve, reject) => {
- let groupInfo = floGlobals.groups[groupID]
+ let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!")
let newKey = floCrypto.randString(16, false);
@@ -734,8 +804,8 @@
}
messenger.sendGroupMessage = function(message, groupID) {
- return new Promise(async (resolve, reject) => {
- let k = floGlobals.groups[groupID].eKey
+ return new Promise((resolve, reject) => {
+ let k = _loaded.groups[groupID].eKey
message = encrypt(message, k)
sendRaw(message, groupID, "GROUP_MSG", false)
.then(result => resolve(`${groupID}: ${message}`))
@@ -743,32 +813,46 @@
})
}
- messenger.requestGroupInbox = function() {
- return new Promise((resolve) => {
- let promises = []
- let reqFn = (g) => new Promise((res, rej) => {
- groupConn(g)
- .then(r => res([g, r]))
- .catch(e => rej([g, e]))
- })
- for (let g in floGlobals.groups)
- if (floGlobals.groups[g].status !== false)
- promises.push(reqFn(g))
- Promise.allSettled(promises).then(result => {
- let ret = {};
- result.forEach(r => {
- if (r.status === 'fulfilled')
- ret[r.value[0]] = {
- status: r.status,
- value: r.value[1]
- }
- else if (r.status === "rejected")
- ret[r.reason[0]] = {
- status: r.status,
- reason: r.reason[1]
- }
- })
- resolve(ret)
+ const disableGroup = messenger.disableGroup = function(groupID) {
+ return new Promise((resolve, reject) => {
+ if (!_loaded.groups[groupID])
+ return reject("Group not found");
+ let groupInfo = {
+ ..._loaded.groups[groupID]
+ };
+ if (groupInfo.disabled)
+ return resolve("Group already diabled");
+ groupInfo.disabled = true;
+ groupInfo.eKey = encrypt(groupInfo.eKey)
+ compactIDB.writeData("groups", groupInfo, groupID).then(result => {
+ floCloudAPI.closeRequest(groupConnID[groupID]);
+ delete groupConnID[groupID];
+ resolve("Group diabled");
+ }).catch(error => reject(error))
+ })
+ }
+
+ messenger.init = function() {
+ return new Promise((resolve, reject) => {
+ initUserDB().then(result => {
+ console.debug(result);
+ loadDataFromIDB().then(data => {
+ console.debug(data);
+ //load data to memory
+ _loaded.appendix = data.appendix;
+ _loaded.groups = data.groups;
+ _loaded.chats = data.chats;
+ _loaded.marked = data.marked;
+ _loaded.blocked = new Set(Object.keys(data.blocked));
+ //call UI render functions
+ UI.chats(getChatOrder());
+ UI.mails(data.mail);
+ UI.marked(data.marked);
+ //request data from cloud
+ requestDirectInbox();
+ data.groups.map(g => requestGroupInbox(g))
+ resolve("Messenger initiated");
+ }).catch(error => reject(error));
})
})
}