mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +00:00
unsealing channel subject in mobile app
This commit is contained in:
parent
356ec4dc45
commit
fd086e2333
@ -33,6 +33,9 @@ import { removeContactChannelTopic } from 'api/removeContactChannelTopic';
|
||||
import { getContactChannelNotifications } from 'api/getContactChannelNotifications';
|
||||
import { setContactChannelNotifications } from 'api/setContactChannelNotifications';
|
||||
|
||||
import CryptoJS from 'crypto-js';
|
||||
import { JSEncrypt } from 'jsencrypt'
|
||||
|
||||
export function useCardContext() {
|
||||
const [state, setState] = useState({
|
||||
cards: new Map(),
|
||||
@ -595,6 +598,36 @@ export function useCardContext() {
|
||||
const { detail, profile } = getCardEntry(cardId);
|
||||
return await setContactChannelNotifications(profile.node, `${profile.guid}.${detail.token}`, channelId, notify);
|
||||
},
|
||||
unsealChannelSubject: async (cardId, channelId, revision, sealKey) => {
|
||||
try {
|
||||
const { guid } = session.current;
|
||||
const card = cards.current.get(cardId);
|
||||
const channel = card.channels.get(channelId);
|
||||
const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.detail.data);
|
||||
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));
|
||||
}
|
||||
}
|
||||
});
|
||||
await store.actions.setCardChannelItemUnsealedDetail(guid, cardId, channelId, revision, channel.unsealedDetail);
|
||||
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();
|
||||
|
@ -334,6 +334,34 @@ export function useChannelContext() {
|
||||
const { server, appToken } = session.current;
|
||||
return await setChannelNotifications(server, appToken, channelId, notify);
|
||||
},
|
||||
unsealChannelSubject: async (channelId, revision, sealKey) => {
|
||||
try {
|
||||
const { guid } = session.current;
|
||||
const channel = channels.current.get(channelId);
|
||||
const { subjectEncrypted, subjectIv, seals } = JSON.parse(channel.detail.data);
|
||||
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));
|
||||
}
|
||||
}
|
||||
});
|
||||
await store.actions.setChannelItemUnsealedDetail(guid, channelId, revision, channel.unsealedDetail);
|
||||
channels.current.set(channelId, { ...channel });
|
||||
updateState({ channels: channels.current });
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, useRef, useContext } from 'react';
|
||||
import SQLite from "react-native-sqlite-storage";
|
||||
|
||||
const DATABAG_DB = 'databag_v064.db';
|
||||
const DATABAG_DB = 'databag_v068.db';
|
||||
|
||||
export function useStoreContext() {
|
||||
const [state, setState] = useState({});
|
||||
@ -221,6 +221,9 @@ export function useStoreContext() {
|
||||
setChannelItemDetail: async (guid, channelId, revision, detail) => {
|
||||
await db.current.executeSql(`UPDATE channel_${guid} set detail_revision=?, detail=?, unsealed_detail=null where channel_id=?`, [revision, encodeObject(detail), channelId]);
|
||||
},
|
||||
setChannelItemUnsealedDetail: async (guid, channelId, revision, unsealed) => {
|
||||
await db.current.executeSql(`UPDATE channel_${guid} set unsealed_detail=? where detail_revision=? AND channel_id=?`, [encodeObject(unsealed), revision, channelId]);
|
||||
},
|
||||
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]);
|
||||
},
|
||||
@ -236,7 +239,7 @@ export function useStoreContext() {
|
||||
};
|
||||
},
|
||||
getChannelItems: async (guid) => {
|
||||
const values = await getAppValues(db.current, `SELECT channel_id, read_revision, revision, sync_revision, blocked, detail_revision, topic_revision, detail, summary FROM channel_${guid}`, []);
|
||||
const values = await getAppValues(db.current, `SELECT channel_id, read_revision, revision, sync_revision, blocked, detail_revision, topic_revision, detail, unsealed_detail, summary, unsealed_summary FROM channel_${guid}`, []);
|
||||
return values.map(channel => ({
|
||||
channelId: channel.channel_id,
|
||||
revision: channel.revision,
|
||||
@ -254,7 +257,7 @@ export function useStoreContext() {
|
||||
|
||||
|
||||
getChannelTopicItems: async (guid, channelId) => {
|
||||
const values = await getAppValues(db.current, `SELECT topic_id, revision, blocked, detail_revision, detail FROM channel_topic_${guid} WHERE channel_id=?`, [channelId]);
|
||||
const values = await getAppValues(db.current, `SELECT topic_id, revision, blocked, detail_revision, detail, unsealed_detail FROM channel_topic_${guid} WHERE channel_id=?`, [channelId]);
|
||||
return values.map(topic => ({
|
||||
topicId: topic.topic_id,
|
||||
revision: topic.revision,
|
||||
@ -305,6 +308,9 @@ export function useStoreContext() {
|
||||
setCardChannelItemDetail: async (guid, cardId, channelId, revision, detail) => {
|
||||
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) => {
|
||||
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]);
|
||||
},
|
||||
@ -320,7 +326,7 @@ export function useStoreContext() {
|
||||
};
|
||||
},
|
||||
getCardChannelItems: async (guid) => {
|
||||
const values = await getAppValues(db.current, `SELECT card_id, channel_id, read_revision, sync_revision, revision, blocked, detail_revision, topic_revision, detail, summary FROM card_channel_${guid}`, []);
|
||||
const values = await getAppValues(db.current, `SELECT card_id, channel_id, read_revision, sync_revision, revision, blocked, detail_revision, topic_revision, detail, unsealed_detail, summary, unsealed_summary FROM card_channel_${guid}`, []);
|
||||
return values.map(channel => ({
|
||||
cardId: channel.card_id,
|
||||
channelId: channel.channel_id,
|
||||
@ -341,7 +347,7 @@ export function useStoreContext() {
|
||||
},
|
||||
|
||||
getCardChannelTopicItems: async (guid, cardId, channelId) => {
|
||||
const values = await getAppValues(db.current, `SELECT topic_id, revision, blocked, detail_revision, detail FROM card_channel_topic_${guid} WHERE card_id=? AND channel_id=?`, [cardId, channelId]);
|
||||
const values = await getAppValues(db.current, `SELECT topic_id, revision, blocked, detail_revision, detail, unsealed_detail FROM card_channel_topic_${guid} WHERE card_id=? AND channel_id=?`, [cardId, channelId]);
|
||||
return values.map(topic => ({
|
||||
topicId: topic.topic_id,
|
||||
revision: topic.revision,
|
||||
|
@ -3,6 +3,8 @@ import { TouchableOpacity } from 'react-native-gesture-handler';
|
||||
import { Logo } from 'utils/Logo';
|
||||
import { styles } from './ChannelItem.styled';
|
||||
import { useChannelItem } from './useChannelItem.hook';
|
||||
import Colors from 'constants/Colors';
|
||||
import Ionicons from '@expo/vector-icons/MaterialCommunityIcons';
|
||||
|
||||
export function ChannelItem({ item, openConversation }) {
|
||||
|
||||
@ -12,7 +14,15 @@ export function ChannelItem({ item, openConversation }) {
|
||||
<TouchableOpacity style={styles.container} activeOpacity={1} onPress={() => openConversation(item.cardId, item.channelId, item.revision)}>
|
||||
<Logo src={item.logo} width={32} height={32} radius={6} />
|
||||
<View style={styles.detail}>
|
||||
<Text style={styles.subject} numberOfLines={1} ellipsizeMode={'tail'}>{ item.subject }</Text>
|
||||
<View style={styles.subject}>
|
||||
{ item.locked && !item.unlocked && (
|
||||
<Ionicons name="lock" style={styles.subjectIcon} size={16} color={Colors.text} />
|
||||
)}
|
||||
{ item.locked && item.unlocked && (
|
||||
<Ionicons name="lock-open-variant-outline" style={styles.subjectIcon} size={16} color={Colors.text} />
|
||||
)}
|
||||
<Text style={styles.subjectText} numberOfLines={1} ellipsizeMode={'tail'}>{ item.subject }</Text>
|
||||
</View>
|
||||
<Text style={styles.message} numberOfLines={1} ellipsizeMode={'tail'}>{ item.message }</Text>
|
||||
</View>
|
||||
{ item.updated && (
|
||||
|
@ -22,6 +22,13 @@ export const styles = StyleSheet.create({
|
||||
flexShrink: 1,
|
||||
},
|
||||
subject: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
subjectIcon: {
|
||||
paddingRight: 4,
|
||||
},
|
||||
subjectText: {
|
||||
color: Colors.text,
|
||||
fontSize: 14,
|
||||
},
|
||||
|
@ -133,8 +133,32 @@ export function useChannels() {
|
||||
logo = 'appstore';
|
||||
}
|
||||
|
||||
let locked = false;
|
||||
let unlocked = false;
|
||||
let subject = null;
|
||||
if (item?.detail?.data) {
|
||||
if (item?.detail?.dataType === 'sealed') {
|
||||
locked = true;
|
||||
if (state.sealable) {
|
||||
try {
|
||||
if (item.unsealedDetail == null) {
|
||||
if (item.cardId) {
|
||||
card.actions.unsealChannelSubject(item.cardId, item.channelId, item.detailRevision, account.state.sealKey);
|
||||
}
|
||||
else {
|
||||
channel.actions.unsealChannelSubject(item.channelId, item.detailRevision, account.state.sealKey);
|
||||
}
|
||||
}
|
||||
else {
|
||||
unlocked = true;
|
||||
subject = item.unsealedDetail.subject;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
subject = JSON.parse(item?.detail?.data).subject;
|
||||
}
|
||||
@ -170,7 +194,7 @@ export function useChannels() {
|
||||
}
|
||||
}
|
||||
|
||||
return { cardId: item.cardId, channelId: item.channelId, contacts, logo, subject, message, updated, revision: item.revision, timestamp: created, blocked: item.blocked === 1 };
|
||||
return { cardId: item.cardId, channelId: item.channelId, contacts, logo, subject, locked, unlocked, message, updated, revision: item.revision, timestamp: created, blocked: item.blocked === 1 };
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -214,7 +238,7 @@ export function useChannels() {
|
||||
});
|
||||
|
||||
updateState({ channels: sorted });
|
||||
}, [channel, card, state.filter]);
|
||||
}, [channel, card, state.filter, state.sealable]);
|
||||
|
||||
const actions = {
|
||||
setSealed: (sealed) => {
|
||||
|
Loading…
Reference in New Issue
Block a user