diff --git a/app/mobile/ios/Databag/Info.plist b/app/mobile/ios/Databag/Info.plist
index 879e8c36..9447df13 100644
--- a/app/mobile/ios/Databag/Info.plist
+++ b/app/mobile/ios/Databag/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
$(PRODUCT_BUNDLE_PACKAGE_TYPE)
CFBundleShortVersionString
- 1.5
+ 1.8
CFBundleSignature
????
CFBundleVersion
diff --git a/app/mobile/ios/Podfile.lock b/app/mobile/ios/Podfile.lock
index e1bdc265..2e908c83 100644
--- a/app/mobile/ios/Podfile.lock
+++ b/app/mobile/ios/Podfile.lock
@@ -669,7 +669,7 @@ SPEC CHECKSUMS:
FirebaseInstallations: 99d24bac0243cf8b0e96cf5426340d211f0bcc80
FirebaseMessaging: 4487bbff9b9b927ba1dd3ea40d1ceb58e4ee3cb5
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
- glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a
+ glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f
GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
diff --git a/app/mobile/src/context/useAccountContext.hook.js b/app/mobile/src/context/useAccountContext.hook.js
index eef7251e..fc33ad65 100644
--- a/app/mobile/src/context/useAccountContext.hook.js
+++ b/app/mobile/src/context/useAccountContext.hook.js
@@ -16,7 +16,7 @@ export function useAccountContext() {
const curRevision = useRef(null);
const setRevision = useRef(null);
const syncing = useRef(false);
-
+
const updateState = (value) => {
setState((s) => ({ ...s, ...value }))
}
diff --git a/app/mobile/src/context/useCardContext.hook.js b/app/mobile/src/context/useCardContext.hook.js
index 5e2f9680..2a0a7afa 100644
--- a/app/mobile/src/context/useCardContext.hook.js
+++ b/app/mobile/src/context/useCardContext.hook.js
@@ -56,6 +56,20 @@ export function useCardContext() {
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 getCardEntry = (cardId) => {
const card = cards.current.get(cardId);
if (!card) {
@@ -135,9 +149,9 @@ export function useCardContext() {
detailRevision: channel?.data?.detailRevision,
topicRevision: channel?.data?.topicRevision,
detail: channel?.data?.channelDetail,
- unsealed_detail: null,
+ unsealedDetail: null,
summary: channel?.data?.channelSummary,
- unsealed_summary: null,
+ unsealedSummary: null,
});
}
const setCardChannelItem = (cardId, channel) => {
@@ -153,7 +167,7 @@ export function useCardContext() {
let channel = card.channels.get(channelId);
if (channel) {
channel.detail = detail;
- channel.unsealed_detail = null;
+ channel.unsealedDetail = null;
channel.detailRevision = revision;
card.channels.set(channelId, channel);
cards.current.set(cardId, card);
@@ -166,7 +180,7 @@ export function useCardContext() {
let channel = card.channels.get(channelId);
if (channel) {
channel.summary = summary;
- channel.unsealed_summary = null;
+ channel.unsealedSummary = null;
channel.topicRevision = revision;
card.channels.set(channelId, channel);
cards.current.set(cardId, card);
@@ -619,25 +633,15 @@ export function useCardContext() {
const card = cards.current.get(cardId);
const channel = card.channels.get(channelId);
const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.detail.data);
- let unsealed = false;
- 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 });
- if (revision === channel.detailRevision) {
- channel.unsealedDetail = JSON.parse(dec.toString(CryptoJS.enc.Utf8));
- unsealed = true;
- }
- }
- });
- if (unsealed) {
+ 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 });
+ if (revision === channel.detailRevision) {
+ channel.unsealedDetail = JSON.parse(dec.toString(CryptoJS.enc.Utf8));
await store.actions.setCardChannelItemUnsealedDetail(guid, cardId, channelId, revision, channel.unsealedDetail);
card.channels.set(channelId, { ...channel });
cards.current.set(cardId, { ...card });
@@ -649,6 +653,33 @@ export function useCardContext() {
console.log(err);
}
},
+ unsealChannelSummary: async (cardId, channelId, revision, sealKey) => {
+ try {
+ const { guid } = session.current;
+ const card = cards.current.get(cardId);
+ const channel = card.channels.get(channelId);
+ const { seals } = JSON.parse(channel.detail.data);
+ const { messageEncrypted, messageIv } = JSON.parse(channel.summary.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);
+ let cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv });
+ const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv });
+ if (revision === channel.topicRevision) {
+ channel.unsealedSummary = JSON.parse(dec.toString(CryptoJS.enc.Utf8));
+ await store.actions.setCardChannelItemUnsealedSummary(guid, cardId, channelId, revision, channel.unsealedSummary);
+ card.channels.set(channelId, { ...channel });
+ cards.current.set(cardId, { ...card });
+ updateState({ cards: cards.current });
+ }
+ }
+ }
+ catch(err) {
+ console.log(err);
+ }
+ },
resync: (cardId) => {
resync.current.push(cardId);
sync();
diff --git a/app/mobile/src/context/useChannelContext.hook.js b/app/mobile/src/context/useChannelContext.hook.js
index 1fce52bb..b7127921 100644
--- a/app/mobile/src/context/useChannelContext.hook.js
+++ b/app/mobile/src/context/useChannelContext.hook.js
@@ -38,6 +38,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 setChannel = (channelId, channel) => {
let update = channels.current.get(channelId);
if (!update) {
@@ -286,6 +300,10 @@ export function useChannelContext() {
const { guid } = session.current;
await store.actions.setChannelTopicItemUnsealedDetail(guid, channelId, topicId, revision, unsealed);
},
+ setTopicUnsealedSummary: async (channelId, topicId, revision, unsealed) => {
+ const { guid } = seassion.current;
+ await store.actions.setChannelTopicItemUnsealedSummary(guid, channelId, topicId, revision, unsealed);
+ },
setSubject: async (channelId, subject) => {
const { server, appToken } = session.current;
return await setChannelSubject(server, appToken, channelId, 'superbasic', { subject });
@@ -373,25 +391,15 @@ export function useChannelContext() {
const { guid } = session.current;
const channel = channels.current.get(channelId);
const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.detail.data);
- if (seals?.length) {
- let unsealed = false;
- 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 });
- if (revision === channel.detailRevision) {
- channel.unsealedDetail = JSON.parse(dec.toString(CryptoJS.enc.Utf8));
- unsealed = true;
- }
- }
- });
- if (unsealed) {
+ 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 });
+ if (revision === channel.detailRevision) {
+ channel.unsealedDetail = JSON.parse(dec.toString(CryptoJS.enc.Utf8));
await store.actions.setChannelItemUnsealedDetail(guid, channelId, revision, channel.unsealedDetail);
channels.current.set(channelId, { ...channel });
updateState({ channels: channels.current });
@@ -402,6 +410,31 @@ export function useChannelContext() {
console.log(err);
}
},
+ unsealChannelSummary: async (channelId, revision, sealKey) => {
+ try {
+ const { guid } = session.current;
+ const channel = channels.current.get(channelId);
+ const { seals } = JSON.parse(channel.detail.data);
+ const { messageEncrypted, messageIv } = JSON.parse(channel.summary.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);
+ let cipher = CryptoJS.lib.CipherParams.create({ ciphertext: enc, iv: iv });
+ const dec = CryptoJS.AES.decrypt(cipher, key, { iv: iv });
+ if (revision === channel.topicRevision) {
+ channel.unsealedSummary = JSON.parse(dec.toString(CryptoJS.enc.Utf8));
+ await store.actions.setChannelItemUnsealedSummary(guid, channelId, revision, channel.unsealedSummary);
+ channels.current.set(channelId, { ...channel });
+ updateState({ channels: channels.current });
+ }
+ }
+ }
+ catch(err) {
+ console.log(err);
+ }
+ },
}
return { state, actions }
diff --git a/app/mobile/src/context/useStoreContext.hook.js b/app/mobile/src/context/useStoreContext.hook.js
index 735b0448..8eb86e85 100644
--- a/app/mobile/src/context/useStoreContext.hook.js
+++ b/app/mobile/src/context/useStoreContext.hook.js
@@ -1,7 +1,7 @@
import { useEffect, useState, useRef, useContext } from 'react';
import SQLite from "react-native-sqlite-storage";
-const DATABAG_DB = 'databag_v068.db';
+const DATABAG_DB = 'databag_v081.db';
export function useStoreContext() {
const [state, setState] = useState({});
@@ -227,6 +227,9 @@ export function useStoreContext() {
setChannelItemSummary: async (guid, channelId, revision, summary) => {
await db.current.executeSql(`UPDATE channel_${guid} set topic_revision=?, summary=?, unsealed_summary=null where channel_id=?`, [revision, encodeObject(summary), channelId]);
},
+ setChannelItemUnsealedSummary: async (guid, channelId, revision, unsealed) => {
+ await db.current.executeSql(`UPDATE channel_${guid} set unsealed_summary=? where topic_revision=? AND channel_id=?`, [encodeObject(unsealed), revision, channelId]);
+ },
getChannelItemView: async (guid, channelId) => {
const values = await getAppValues(db.current, `SELECT revision, detail_revision, topic_revision FROM channel_${guid} WHERE channel_id=?`, [channelId]);
if (!values.length) {
@@ -272,7 +275,6 @@ export function useStoreContext() {
await db.current.executeSql(`INSERT OR REPLACE INTO channel_topic_${guid} (channel_id, topic_id, revision, detail_revision, detail, unsealed_detail) values (?, ?, ?, ?, ?, null);`, [channelId, id, revision, data.detailRevision, encodeObject(data.topicDetail)]);
},
setChannelTopicItemUnsealedDetail: async (guid, channelId, topicId, revision, unsealed) => {
-console.log("SAVING:", channelId, revision, unsealed);
await db.current.executeSql(`UPDATE channel_topic_${guid} set unsealed_detail=? where detail_revision=? AND channel_id=? AND topic_id=?`, [encodeObject(unsealed), revision, channelId, topicId]);
},
clearChannelTopicItem: async (guid, channelId, topicId) => {
@@ -313,12 +315,14 @@ console.log("SAVING:", channelId, revision, unsealed);
await db.current.executeSql(`UPDATE card_channel_${guid} set detail_revision=?, detail=?, unsealed_detail=null where card_id=? and channel_id=?`, [revision, encodeObject(detail), cardId, channelId]);
},
setCardChannelItemUnsealedDetail: async (guid, cardId, channelId, revision, unsealed) => {
-console.log("SAVING:", cardId, channelId, revision, unsealed);
await db.current.executeSql(`UPDATE card_channel_${guid} set unsealed_detail=? where detail_revision=? AND card_id=? AND channel_id=?`, [encodeObject(unsealed), revision, cardId, channelId]);
},
setCardChannelItemSummary: async (guid, cardId, channelId, revision, summary) => {
await db.current.executeSql(`UPDATE card_channel_${guid} set topic_revision=?, summary=?, unsealed_summary=null where card_id=? and channel_id=?`, [revision, encodeObject(summary), cardId, channelId]);
},
+ setCardChannelItemUnsealedSummary: async (guid, cardId, channelId, revision, unsealed) => {
+ await db.current.executeSql(`UPDATE card_channel_${guid} set unsealed_summary=? where topic_revision=? AND card_id=? AND channel_id=?`, [encodeObject(unsealed), revision, cardId, channelId]);
+ },
getCardChannelItemView: async (guid, cardId, channelId) => {
const values = await getAppValues(db.current, `SELECT revision, detail_revision, topic_revision FROM card_channel_${guid} WHERE card_id=? and channel_id=?`, [cardId, channelId]);
if (!values.length) {
diff --git a/app/mobile/src/session/channels/useChannels.hook.js b/app/mobile/src/session/channels/useChannels.hook.js
index 13cfe81f..b96d50f0 100644
--- a/app/mobile/src/session/channels/useChannels.hook.js
+++ b/app/mobile/src/session/channels/useChannels.hook.js
@@ -94,7 +94,8 @@ export function useChannels() {
let updated = false;
const login = app.state.loginTimestamp;
- const { created, guid } = item?.summary?.lastTopic;
+ const created = item?.summary?.lastTopic?.created;
+ const guid = item?.summary?.lastTopic?.guid;
if (created && login && login < created) {
if (!item.readRevision || item.readRevision < item.revision) {
if (profile.state.profile.guid != guid) {
@@ -193,6 +194,28 @@ export function useChannels() {
console.log(err);
}
}
+ if (item?.summary?.lastTopic?.dataType === 'sealedtopic') {
+ if (state.sealable) {
+ try {
+ if (item.unsealedSummary == null) {
+ if (item.cardId) {
+ card.actions.unsealChannelSummary(item.cardId, item.channelId, item.topicRevision, account.state.sealKey);
+ }
+ else {
+ channel.actions.unsealChannelSummary(item.channelId, item.topicRevision, account.state.sealKey);
+ }
+ }
+ else {
+ if (typeof item.unsealedSummary.message.text === 'string') {
+ message = item.unsealedSummary.message.text;
+ }
+ }
+ }
+ catch (err) {
+ console.log(err)
+ }
+ }
+ }
return { cardId: item.cardId, channelId: item.channelId, contacts, logo, subject, locked, unlocked, message, updated, revision: item.revision, timestamp: created, blocked: item.blocked === 1 };
}