From f72aa4c5fa2e87a69bf819cb5621808891571ec0 Mon Sep 17 00:00:00 2001 From: balzack Date: Sun, 1 Dec 2024 13:34:31 -0800 Subject: [PATCH] implementing focus module --- app/client/web/src/MediaFiles.ts | 1 - .../src/conversation/useConversation.hook.ts | 11 +- app/sdk/src/contact.ts | 10 +- app/sdk/src/focus.ts | 152 ++++++++++-------- app/sdk/src/stream.ts | 10 +- app/sdk/src/types.ts | 2 +- 6 files changed, 108 insertions(+), 78 deletions(-) diff --git a/app/client/web/src/MediaFiles.ts b/app/client/web/src/MediaFiles.ts index d74553b1..70264947 100644 --- a/app/client/web/src/MediaFiles.ts +++ b/app/client/web/src/MediaFiles.ts @@ -31,7 +31,6 @@ export class MediaFiles implements Media { public async read(source: any): Promise<{ size: number, getData: (position: number, length: number)=>Promise, close: ()=>Promise }> { const data = await this.loadFileData(source); const size = data.byteLength; - const getData = async (position: number, length: number) => { if (position + length > data.byteLength) { throw new Error('invalid read request'); diff --git a/app/client/web/src/conversation/useConversation.hook.ts b/app/client/web/src/conversation/useConversation.hook.ts index d74b1ab1..2dc7ff1f 100644 --- a/app/client/web/src/conversation/useConversation.hook.ts +++ b/app/client/web/src/conversation/useConversation.hook.ts @@ -4,6 +4,9 @@ import { DisplayContext } from '../context/DisplayContext' import { Focus, Topic, AssetSource, HostingMode, TransformType } from 'databag-client-sdk' import { ContextType } from '../context/ContextType' +const img = + 'data:image/png;base64,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'; + export function useConversation() { const app = useContext(AppContext) as ContextType const display = useContext(DisplayContext) as ContextType @@ -51,6 +54,7 @@ export function useConversation() { } }, add: async (file: File) => { + const { focus } = app.state; if (focus) { const asset = { @@ -58,12 +62,11 @@ export function useConversation() { mimeType: 'image', extension: 'jpg', source: file, - transforms: [ {type: TransformType.Thumb, appId: '1'}, {type: TransformType.Copy, appId: '2'}], + transforms: [ {type: TransformType.Thumb, thumb: ()=>(img), appId: '1'}, {type: TransformType.Copy, appId: '2'}], } - const topicId = await focus.addTopic(false, 'superbasictopic', (assets: {assetId: string, appId: string}[])=>{ - console.log("HERER!!!"); + const topicId = await focus.addTopic(true, 'sealedtopic', (assets: {assetId: string, appId: string}[])=>{ console.log(assets); - return { text: 'addedasset', assets: [{ image: { thumb: '0', full: '1' } }] }; + return { text: 'addedasset', assets: [{ encrypted: { type: 'image', thumb: '0', parts: '1' } }] }; }, [asset], (percent: number)=>{ console.log(percent); }); diff --git a/app/sdk/src/contact.ts b/app/sdk/src/contact.ts index a14c81d4..e13beba9 100644 --- a/app/sdk/src/contact.ts +++ b/app/sdk/src/contact.ts @@ -1029,9 +1029,13 @@ export class ContactModule implements Contact { } if (item.channelKey) { const { messageEncrypted, messageIv } = JSON.parse(item.summary.data); - const { data } = await this.crypto.aesDecrypt(messageEncrypted, messageIv, item.channelKey); - item.unsealedSummary = data; - return true; + if (!messageEncrypted || !messageIv) { + this.log.warn('invalid sealed summary'); + } else { + const { data } = await this.crypto.aesDecrypt(messageEncrypted, messageIv, item.channelKey); + item.unsealedSummary = data; + return true; + } } } catch (err) { this.log.warn(err); diff --git a/app/sdk/src/focus.ts b/app/sdk/src/focus.ts index 6477efac..04c166b3 100644 --- a/app/sdk/src/focus.ts +++ b/app/sdk/src/focus.ts @@ -221,7 +221,6 @@ export class FocusModule implements Focus { this.emitTopics(); } } - this.syncing = false; } } @@ -241,8 +240,12 @@ export class FocusModule implements Focus { xhr.setRequestHeader('Content-Type', 'text/plain'); xhr.progress = progress; xhr.onload = () => { - if (xhr.status >= 200 && xhr.status < 300 && xhr.response?.assetId) { - resolve(xhr.response.assetId) + if (xhr.status >= 200 && xhr.status < 300) { + try { + resolve(JSON.parse(xhr.response).assetId); + } catch (err) { + reject('invalid block response'); + } } else { reject(xhr.statusText) } @@ -271,7 +274,11 @@ export class FocusModule implements Focus { xhr.progress = progress; xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { - resolve(xhr.response) + try { + resolve(JSON.parse(xhr.response)); + } catch (err) { + reject('invalid asset response'); + } } else { reject(xhr.statusText) } @@ -343,7 +350,7 @@ export class FocusModule implements Focus { for (const transform of asset.transforms) { if (transform.type === TransformType.Thumb && transform.thumb) { const assetItem = { - assetId: `${assetItems.size}`, + assetId: `${assetItems.length}`, encrytped: true, hosting: HostingMode.Inline, inline: await transform.thumb(), @@ -351,18 +358,18 @@ export class FocusModule implements Focus { appAsset.push({appId: transform.appId, assetId: assetItem.assetId}); assetItems.push(assetItem); } else if (transform.type === TransformType.Copy) { - const media = await this.file.read(asset.soure); - const split = [] as { blockId: string, blockIv: string }[]; - for (let i = 0; media.size < i * ENCRYPT_BLOCK_SIZE; i++) { - const length = media.size - (i * ENCRYPT_BLOCK_SIZE) > ENCRYPT_BLOCK_SIZE ? ENCRYPT_BLOCK_SIZE : media.size - (i * ENCRYPT_BLOCK_SIZE); - const base64Data = await media.getData(i * ENCRYPT_BLOCK_SIZE, length); + const mediaFile = await this.media.read(asset.source); + const split = [] as { partId: string, blockIv: string }[]; + for (let i = 0; i * ENCRYPT_BLOCK_SIZE < mediaFile.size; i++) { + const length = mediaFile.size - (i * ENCRYPT_BLOCK_SIZE) > ENCRYPT_BLOCK_SIZE ? ENCRYPT_BLOCK_SIZE : mediaFile.size - (i * ENCRYPT_BLOCK_SIZE); + const base64Data = await mediaFile.getData(i * ENCRYPT_BLOCK_SIZE, length); const { ivHex } = await crypto.aesIv(); const { encryptedDataB64 } = await crypto.aesEncrypt(base64Data, ivHex, channelKey); - const blockId = await uploadBlock(encryptedDataB64, topicId, (percent: number) => { console.log(`percent: ${percent}`) }); - split.push({ blockId, blockIv: ivHex }); + const partId = await this.uploadBlock(encryptedDataB64, topicId, (percent: number) => { console.log(`percent: ${percent}`) }); + split.push({ partId, blockIv: ivHex }); } const assetItem = { - assetId: `${assetItems.size}`, + assetId: `${assetItems.length}`, encrypted: true, hosting: HostingMode.Split, split, @@ -406,7 +413,7 @@ export class FocusModule implements Focus { } else if (transform.type === TransformType.Copy && asset.mimeType === 'binary') { const assetId = await this.mirrorFile(asset.source, topicId, (percent: number)=>{console.log(`progress: ${percent}`)}); const assetItem = { - assetId: `${assetItems.size}`, + assetId: `${assetItems.length}`, encrytped: false, hosting: HostingMode.Basic, basic: assetId, @@ -421,7 +428,7 @@ export class FocusModule implements Focus { const transformAssets = await this.transformFile(asset.source, topicId, transforms, (percent: number)=>{console.log(`progress: ${percent}`)}); for (let transformAsset of transformAssets) { const assetItem = { - assetId: `${assetItems.size}`, + assetId: `${assetItems.length}`, encrypted: false, hosting: HostingMode.Basic, basic: transformAsset.assetId, @@ -440,6 +447,9 @@ export class FocusModule implements Focus { const getAsset = (assetId: string) => { const index = parseInt(assetId); const item = assetItems[index]; + if (!item) { + throw new Error('invalid assetId in subject'); + } if (item.hosting === HostingMode.Inline) { return item.inline; } @@ -451,36 +461,38 @@ export class FocusModule implements Focus { } } - const mapped = !assets ? [] : assets.map(asset => { - if (asset.image) { + const filtered = !assets ? [] : assets.filter(asset => { + if (sealed && asset.encrypted) { + return true; + } else if (!sealed && !asset.encrypted) { + return true; + } else { + return false; + } + }); + const mapped = filtered.map(asset => { + if (sealed) { + const { type, thumb, parts } = asset.encrypted; + return { encrypted: { type, thumb: getAsset(thumb), parts: getAsset(parts) } }; + } else if (asset.image) { const { thumb, full } = asset.image; return { image: { thumb: getAsset(thumb), full: getAsset(full) } }; - } - if (asset.video) { + } else if (asset.video) { const { thumb, lq, hd } = asset.video; return { video: { thumb: getAsset(thumb), lq: getAsset(lq), hd: getAsset(hd) } }; - } - if (asset.audio) { + } else if (asset.audio) { const { label, fulle } = asset.audio; return { audio: { label, full: getAsset(full) } }; - } - if (asset.binary) { + } else if (asset.binary) { const { label, extension, data } = asset.binary; return { binary: { label, extension, data: getAsset(data) } }; } - if (asset.encrypted) { - const { type, thumb, parts } = asset.encrypted; - return { encrypted: { type, thumb: getAsset(thumb), parts: getAsset(parts) } }; - } }); const updated = { text, textColor, textSize, assets: mapped }; - -console.log("OK UPDATED: ", updated); - if (sealed) { - const subjectString = JSON.stringify(updated); + const subjectString = JSON.stringify({ message: updated }); const { ivHex } = await crypto.aesIv(); - const { encryptedDataB64 } = await crypto.aesEncrypt(decryptedString, ivHex, channelKey); + const { encryptedDataB64 } = await crypto.aesEncrypt(subjectString, ivHex, channelKey); const data = { messageEncrypted: encryptedDataB64, messageIv: ivHex }; await this.setRemoteChannelTopicSubject(topicId, type, data); } else { @@ -489,7 +501,6 @@ console.log("OK UPDATED: ", updated); return topicId; } - } public async setTopicSubject(topicId: string, type: string, subject: (assets: {assetId: string, appId: string}[])=>any, files: AssetSource[], progress: (percent: number)=>boolean) { @@ -511,7 +522,7 @@ console.log("OK UPDATED: ", updated); for (const transform of asset.transforms) { if (transform.type === TransformType.Thumb && transform.thumb) { const assetItem = { - assetId: `${assetItems.size}`, + assetId: `${assetItems.length}`, encrytped: true, hosting: HostingMode.Inline, inline: await transform.thumb(), @@ -519,18 +530,18 @@ console.log("OK UPDATED: ", updated); appAsset.push({appId: transform.appId, assetId: assetItem.assetId}); assetItems.push(assetItem); } else if (transform.type === TransformType.Copy) { - const media = await this.file.read(asset.soure); - const split = [] as { blockId: string, blockIv: string }[]; - for (let i = 0; media.size < i * ENCRYPT_BLOCK_SIZE; i++) { - const length = media.size - (i * ENCRYPT_BLOCK_SIZE) > ENCRYPT_BLOCK_SIZE ? ENCRYPT_BLOCK_SIZE : media.size - (i * ENCRYPT_BLOCK_SIZE); - const base64Data = await media.getData(i * ENCRYPT_BLOCK_SIZE, length); + const mediaFile = await this.file.read(asset.source); + const split = [] as { partId: string, blockIv: string }[]; + for (let i = 0; i * ENCRYPT_BLOCK_SIZE < mediaFile.size; i++) { + const length = mediaFile.size - (i * ENCRYPT_BLOCK_SIZE) > ENCRYPT_BLOCK_SIZE ? ENCRYPT_BLOCK_SIZE : mediaFile.size - (i * ENCRYPT_BLOCK_SIZE); + const base64Data = await mediaFile.getData(i * ENCRYPT_BLOCK_SIZE, length); const { ivHex } = await crypto.aesIv(); const { encryptedDataB64 } = await crypto.aesEncrypt(base64Data, ivHex, channelKey); - const blockId = await uploadBlock(encryptedDataB64, topicId, (percent: number) => { console.log(`percent: ${percent}`) }); - split.push({ blockId, blockIv: ivHex }); + const partId = await this.uploadBlock(encryptedDataB64, topicId, (percent: number) => { console.log(`percent: ${percent}`) }); + split.push({ partId, blockIv: ivHex }); } const assetItem = { - assetId: `${assetItems.size}`, + assetId: `${assetItems.length}`, encrypted: true, hosting: HostingMode.Split, split, @@ -568,7 +579,7 @@ console.log("OK UPDATED: ", updated); } else if (transform.type === TransformType.Copy && asset.mimeType === 'binary') { const assetId = await this.mirrorFile(asset.source, topicId, (percent: number)=>{console.log(`progress: ${percent}`)}); const assetItem = { - assetId: `${assetItems.size}`, + assetId: `${assetItems.length}`, encrytped: false, hosting: HostingMode.Basic, basic: assetId, @@ -610,34 +621,39 @@ console.log("OK UPDATED: ", updated); } } - const mapped = assets.map(asset => { - if (asset.image) { - const { thumb, full } = asset.image; - return { image: { thumb: getAsset(thumb), full: getAsset(full) } }; + const filtered = !assets ? [] : assets.filter(asset => { + if (sealed && asset.encrypted) { + return true; + } else if (!sealed && !asset.encrypted) { + return true; + } else { + return false; } - if (asset.video) { - const { thumb, lq, hd } = asset.video; - return { video: { thumb: getAsset(thumb), lq: getAsset(lq), hd: getAsset(hd) } }; - } - if (asset.audio) { - const { label, fulle } = asset.audio; - return { audio: { label, full: getAsset(full) } }; - } - if (asset.binary) { - const { label, extension, data } = asset.binary; - return { binary: { label, extension, data: getAsset(data) } }; - } - if (asset.encrypted) { + }); + const mapped = filtered.map(asset => { + if (sealed) { const { type, thumb, parts } = asset.encrypted; return { encrypted: { type, thumb: getAsset(thumb), parts: getAsset(parts) } }; + } else if (asset.image) { + const { thumb, full } = asset.image; + return { image: { thumb: getAsset(thumb), full: getAsset(full) } }; + } else if (asset.video) { + const { thumb, lq, hd } = asset.video; + return { video: { thumb: getAsset(thumb), lq: getAsset(lq), hd: getAsset(hd) } }; + } else if (asset.audio) { + const { label, fulle } = asset.audio; + return { audio: { label, full: getAsset(full) } }; + } else if (asset.binary) { + const { label, extension, data } = asset.binary; + return { binary: { label, extension, data: getAsset(data) } }; } }); const updated = { text, textColor, textSize, assets: mapped }; if (sealed) { - const subjectString = JSON.stringify(updated); + const subjectString = JSON.stringify({ message: updated }); const { ivHex } = await crypto.aesIv(); - const { encryptedDataB64 } = await crypto.aesEncrypt(decryptedString, ivHex, channelKey); + const { encryptedDataB64 } = await crypto.aesEncrypt(subjectString, ivHex, channelKey); const data = { messageEncrypted: encryptedDataB64, messageIv: ivHex }; return await this.setRemoteChannelTopicSubject(topicId, type, data); } else { @@ -667,10 +683,14 @@ console.log("OK UPDATED: ", updated); if (item.detail.sealed && !item.unsealedDetail && this.sealEnabled && this.channelKey && this.crypto) { try { const { messageEncrypted, messageIv } = item.detail.data; - const { data } = await this.crypto.aesDecrypt(messageEncrypted, messageIv, this.channelKey); - const { message } = JSON.parse(data); - item.unsealedDetail = message; - return true; + if (!messageEncrypted || !messageIv) { + this.log.warn('invalid sealed topic'); + } else { + const { data } = await this.crypto.aesDecrypt(messageEncrypted, messageIv, this.channelKey); + const { message } = JSON.parse(data); + item.unsealedDetail = message; + return true; + } } catch (err) { this.log.warn(err); } diff --git a/app/sdk/src/stream.ts b/app/sdk/src/stream.ts index 2eb12648..62b50b59 100644 --- a/app/sdk/src/stream.ts +++ b/app/sdk/src/stream.ts @@ -552,9 +552,13 @@ export class StreamModule { } if (item.channelKey) { const { messageEncrypted, messageIv } = JSON.parse(item.summary.data); - const { data } = await this.crypto.aesDecrypt(messageEncrypted, messageIv, item.channelKey); - item.unsealedSummary = data; - return true; + if (!messageEncrypted || !messageIv) { + this.log.warn('invalid sealed summary'); + } else { + const { data } = await this.crypto.aesDecrypt(messageEncrypted, messageIv, item.channelKey); + item.unsealedSummary = data; + return true; + } } } catch (err) { this.log.warn(err); diff --git a/app/sdk/src/types.ts b/app/sdk/src/types.ts index 8d1441b2..2a8716bf 100644 --- a/app/sdk/src/types.ts +++ b/app/sdk/src/types.ts @@ -111,7 +111,7 @@ export type Tag = { }; export enum HostingMode { - Inline = 'inlien', // sealed or unsealed + Inline = 'inline', // sealed or unsealed Split = 'split', // sealed only, split file into blocks Basic = 'basic', // unsealed only, basic download }