diff --git a/net/web/src/api/setContactChannelTopicSubject.js b/net/web/src/api/setContactChannelTopicSubject.js index dce13224..66abdc43 100644 --- a/net/web/src/api/setContactChannelTopicSubject.js +++ b/net/web/src/api/setContactChannelTopicSubject.js @@ -1,6 +1,7 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil'; -export async function setContactChannelTopicSubject(server, token, channelId, topicId, data) { +export async function setContactChannelTopicSubject(server, token, channelId, topicId, datatype, data) { +console.log(data); let host = ""; if (server) { host = `https://${server}`; @@ -8,7 +9,7 @@ export async function setContactChannelTopicSubject(server, token, channelId, to let subject = { data: JSON.stringify(data, (key, value) => { if (value !== null) return value - }), datatype: 'superbasictopic' }; + }), datatype }; let channel = await fetchWithTimeout(`${host}/content/channels/${channelId}/topics/${topicId}/subject?contact=${token}&confirm=true`, { method: 'PUT', body: JSON.stringify(subject) }); diff --git a/net/web/src/context/useCardContext.hook.js b/net/web/src/context/useCardContext.hook.js index 79359170..8c779bf0 100644 --- a/net/web/src/context/useCardContext.hook.js +++ b/net/web/src/context/useCardContext.hook.js @@ -60,6 +60,20 @@ export function useCardContext() { } } + const unsealKey = (seals, sealKey) => { + let unsealedKey; + if (seals?.length) { + seals.forEach(seal => { + if (seal.publicKey === sealKey.public) { + let crypto = new JSEncrypt(); + crypto.setPrivateKey(sealKey.private); + unsealedKey = crypto.decrypt(seal.sealedKey); + } + }); + } + return unsealedKey; + }; + const updateCards = async () => { let delta = await getCards(access.current, revision.current); for (let card of delta) { @@ -159,6 +173,7 @@ export function useCardContext() { let detail = await getContactChannelDetail(node, guid + "." + token, channel.id); cur.data.channelDetail = detail; } + cur.data.unsealedChannel = null; cur.data.detailRevision = channel.data.detailRevision; } if (cur.data.topicRevision !== channel.data.topicRevision) { @@ -169,6 +184,7 @@ export function useCardContext() { let summary = await getContactChannelSummary(node, guid + "." + token, channel.id); cur.data.channelSummary = summary; } + cur.data.unsealedSummary = null; cur.data.topicRevision = channel.data.topicRevision; } cur.revision = channel.revision; @@ -274,27 +290,48 @@ export function useCardContext() { return card.data.cardProfile.name; }, unsealChannelSubject: (cardId, channelId, sealKey) => { - const card = cards.current.get(cardId); - const channel = card.channels.get(channelId); - - const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.data.channelDetail.data); - if (seals?.length) { - seals.forEach(seal => { - if (seal.publicKey === sealKey.public) { - let crypto = new JSEncrypt(); - crypto.setPrivateKey(sealKey.private); - const unsealedKey = crypto.decrypt(seal.sealedKey); - const iv = CryptoJS.enc.Hex.parse(subjectIv); - const key = CryptoJS.enc.Hex.parse(unsealedKey); - const enc = CryptoJS.enc.Base64.parse(subjectEncrypted); - let cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv }); - const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv }); - channel.data.unsealedChannel = JSON.parse(dec.toString(CryptoJS.enc.Utf8)); - card.channels.set(channel.id, { ...channel }); - cards.current.set(cardId, { ...card }); - updateState({ cards: cards.current }); - } - }); + try { + const card = cards.current.get(cardId); + const channel = card.channels.get(channelId); + const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.data.channelDetail.data); + const unsealedKey = unsealKey(seals, sealKey); + if (unsealedKey) { + const iv = CryptoJS.enc.Hex.parse(subjectIv); + const key = CryptoJS.enc.Hex.parse(unsealedKey); + const enc = CryptoJS.enc.Base64.parse(subjectEncrypted); + let cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv }); + const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv }); + channel.data.unsealedChannel = JSON.parse(dec.toString(CryptoJS.enc.Utf8)); + card.channels.set(channel.id, { ...channel }); + cards.current.set(cardId, { ...card }); + updateState({ cards: cards.current }); + } + } + catch(err) { + console.log(err); + } + }, + unsealChannelSummary: (cardId, channelId, sealKey) => { + try { + const card = cards.current.get(cardId); + const channel = card.channels.get(channelId); + const { seals } = JSON.parse(channel.data.channelDetail.data); + const { messageEncrypted, messageIv } = JSON.parse(channel.data.channelSummary.lastTopic.data); + const unsealedKey = unsealKey(seals, sealKey); + if (unsealedKey) { + const iv = CryptoJS.enc.Hex.parse(messageIv); + const key = CryptoJS.enc.Hex.parse(unsealedKey); + const enc = CryptoJS.enc.Base64.parse(messageEncrypted); + const cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv }); + const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv }); + channel.data.unsealedSummary = JSON.parse(dec.toString(CryptoJS.enc.Utf8)); + card.channels.set(channel.id, { ...channel }); + cards.current.set(cardId, { ...card }); + updateState({ cards: cards.current }); + } + } + catch(err) { + console.log(err); } }, removeChannel: async (cardId, channelId) => { @@ -330,14 +367,12 @@ export function useCardContext() { } }, setSealedChannelTopicSubject: async (cardId, channelId, topicId, data, sealKey) => { -console.log("SETTING:", data, sealKey); - let { cardProfile, cardDetail } = cards.current.get(cardId).data; let token = cardProfile.guid + '.' + cardDetail.token; let node = cardProfile.node; const iv = CryptoJS.lib.WordArray.random(128 / 8); const key = CryptoJS.enc.Hex.parse(sealKey); - const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), key, { iv: iv }); + const encrypted = CryptoJS.AES.encrypt(JSON.stringify({ message: data }), key, { iv: iv }); const messageEncrypted = encrypted.ciphertext.toString(CryptoJS.enc.Base64) const messageIv = iv.toString(); await setContactChannelTopicSubject(node, token, channelId, topicId, 'sealedtopic', { messageEncrypted, messageIv }); diff --git a/net/web/src/context/useChannelContext.hook.js b/net/web/src/context/useChannelContext.hook.js index 7d0ede2e..1e687db4 100644 --- a/net/web/src/context/useChannelContext.hook.js +++ b/net/web/src/context/useChannelContext.hook.js @@ -32,6 +32,20 @@ export function useChannelContext() { setState((s) => ({ ...s, ...value })) } + const unsealKey = (seals, sealKey) => { + let unsealedKey; + if (seals?.length) { + seals.forEach(seal => { + if (seal.publicKey === sealKey.public) { + let crypto = new JSEncrypt(); + crypto.setPrivateKey(sealKey.private); + unsealedKey = crypto.decrypt(seal.sealedKey); + } + }); + } + return unsealedKey; + } + const updateChannels = async () => { let delta = await getChannels(access.current, revision.current); for (let channel of delta) { @@ -43,13 +57,12 @@ export function useChannelContext() { if (cur.data.detailRevision !== channel.data.detailRevision) { if (channel.data.channelDetail != null) { cur.data.channelDetail = channel.data.channelDetail; - cur.data.unsealedSubject = null; } else { let detail = await getChannelDetail(access.current, channel.id); cur.data.channelDetail = detail; - cur.data.unsealedChannel = null; } + cur.data.unsealedChannel = null; cur.data.detailRevision = channel.data.detailRevision; } if (cur.data.topicRevision !== channel.data.topicRevision) { @@ -60,6 +73,7 @@ export function useChannelContext() { let summary = await getChannelSummary(access.current, channel.id); cur.data.channelSummary = summary; } + cur.data.unsealedSummary = null; cur.data.topicRevision = channel.data.topicRevision; } cur.revision = channel.revision; @@ -131,25 +145,44 @@ export function useChannelContext() { return await addChannel(access.current, 'sealed', cards, data); }, unsealChannelSubject: (channelId, sealKey) => { - const channel = channels.current.get(channelId); - - const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.data.channelDetail.data); - if (seals?.length) { - seals.forEach(seal => { - if (seal.publicKey === sealKey.public) { - let crypto = new JSEncrypt(); - crypto.setPrivateKey(sealKey.private); - const unsealedKey = crypto.decrypt(seal.sealedKey); - const iv = CryptoJS.enc.Hex.parse(subjectIv); - const key = CryptoJS.enc.Hex.parse(unsealedKey); - const enc = CryptoJS.enc.Base64.parse(subjectEncrypted); - let cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv }); - const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv }); - channel.data.unsealedChannel = JSON.parse(dec.toString(CryptoJS.enc.Utf8)); - channels.current.set(channel.id, { ...channel }); - updateState({ channels: channels.current }); - } - }); + try { + const channel = channels.current.get(channelId); + const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.data.channelDetail.data); + const unsealedKey = unsealKey(seals, sealKey); + if (unsealKey) { + const iv = CryptoJS.enc.Hex.parse(subjectIv); + const key = CryptoJS.enc.Hex.parse(unsealedKey); + const enc = CryptoJS.enc.Base64.parse(subjectEncrypted); + const cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv }); + const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv }); + channel.data.unsealedChannel = JSON.parse(dec.toString(CryptoJS.enc.Utf8)); + channels.current.set(channel.id, { ...channel }); + updateState({ channels: channels.current }); + } + } + catch(err) { + console.log(err); + } + }, + unsealChannelSummary: (channelId, sealKey) => { + try { + const channel = channels.current.get(channelId); + const { seals } = JSON.parse(channel.data.channelDetail.data); + const { messageEncrypted, messageIv } = JSON.parse(channel.data.channelSummary.lastTopic.data); + const unsealedKey = unsealKey(seals, sealKey); + if (unsealKey) { + const iv = CryptoJS.enc.Hex.parse(messageIv); + const key = CryptoJS.enc.Hex.parse(unsealedKey); + const enc = CryptoJS.enc.Base64.parse(messageEncrypted); + const cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv }); + const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv }); + channel.data.unsealedSummary = JSON.parse(dec.toString(CryptoJS.enc.Utf8)); + channels.current.set(channel.id, { ...channel }); + updateState({ channels: channels.current }); + } + } + catch(err) { + console.log(err); } }, setChannelSubject: async (channelId, subject) => { diff --git a/net/web/src/session/channels/useChannels.hook.js b/net/web/src/session/channels/useChannels.hook.js index f602b229..e48b3e80 100644 --- a/net/web/src/session/channels/useChannels.hook.js +++ b/net/web/src/session/channels/useChannels.hook.js @@ -209,6 +209,26 @@ export function useChannels() { console.log(err); } } + if (chan.data.channelSummary?.lastTopic?.dataType === 'sealedtopic') { + try { + if (chan.data.unsealedSummary == null) { + if (chan.cardId) { + card.actions.unsealChannelSummary(chan.cardId, chan.id, account.state.sealKey); + } + else { + channel.actions.unsealChannelSummary(chan.id, account.state.sealKey); + } + } + else { + if (typeof chan.data.unsealedSummary.message.text === 'string') { + chan.message = chan.data.unsealedSummary.message.text; + } + } + } + catch (err) { + console.log(err) + } + } if (typeof message === 'string') { chan.message = message; diff --git a/net/web/src/session/conversation/topicItem/useTopicItem.hook.js b/net/web/src/session/conversation/topicItem/useTopicItem.hook.js index 0baefac5..7b5ca36f 100644 --- a/net/web/src/session/conversation/topicItem/useTopicItem.hook.js +++ b/net/web/src/session/conversation/topicItem/useTopicItem.hook.js @@ -86,8 +86,6 @@ export function useTopicItem(topic, sealed, sealKey) { } else if (dataType === 'sealedtopic') { if (topic.data.unsealedMessage) { -console.log("UNSEALED MESSAGE", topic.data.unsealedMessage); - text = topic.data.unsealedMessage.message?.text; sealed = false; } @@ -146,11 +144,9 @@ console.log("UNSEALED MESSAGE", topic.data.unsealedMessage); updateState({ busy: true }); try { if (sealed) { -console.log("SET SEALED"); await conversation.actions.setSealedTopicSubject(topic.id, {...state.message, text: editMessage.current }, sealKey); } else { -console.log("SET UNSEALED"); await conversation.actions.setTopicSubject(topic.id, { ...state.message, text: editMessage.current, assets: state.assets }); }