From 3f48f26327d789dc2642842dfbfd03d95a8571c8 Mon Sep 17 00:00:00 2001 From: marlon-erler Date: Mon, 22 Jul 2024 00:52:54 +0200 Subject: [PATCH] prevent errors with corrupt files --- dist/index.js | 14 ++++++++-- src/Model/chatListModel.ts | 1 + src/Model/chatModel.ts | 52 +++++++++++++++++++++++--------------- src/Model/fileModel.ts | 25 ++++++++++-------- 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/dist/index.js b/dist/index.js index 3ffd50eb..b90f5340 100644 --- a/dist/index.js +++ b/dist/index.js @@ -444,6 +444,7 @@ handleStringifiedFile = (stringifiedFile) => { const file = parseValidObject(stringifiedFile); if (file == null) return; + this.storeFile(file); }; // methods addFile = (file) => { @@ -461,6 +462,8 @@ file, fileContentName ); + const existingFileContent = this.storageModel.read(fileContentPath); + if (existingFileContent != null) return; const stringifiedContent = stringify(fileContent); this.storageModel.write(fileContentPath, stringifiedContent); }; @@ -500,6 +503,13 @@ const filePath = _FileModel.getFilePath(file.id); return [...filePath, fileContentName]; }; + static createFile = () => { + return { + dataVersion: DATA_VERSION, + id: v4_default(), + contentVersions: [] + }; + }; }; // src/Model/Utility/crypto.ts @@ -757,7 +767,7 @@ // utility static generateChatInfo = (primaryChannel) => { return { - dataVersion: "v2", + dataVersion: DATA_VERSION, primaryChannel, secondaryChannels: [], encryptionKey: "", @@ -766,7 +776,7 @@ }; static createChatMessage = async (channel, sender, encryptionKey, body, file) => { const chatMessage = { - dataVersion: "v2", + dataVersion: DATA_VERSION, id: v4_default(), channel, sender, diff --git a/src/Model/chatListModel.ts b/src/Model/chatListModel.ts index 8bc2fdcd..d297fe78 100644 --- a/src/Model/chatListModel.ts +++ b/src/Model/chatListModel.ts @@ -66,6 +66,7 @@ export default class ChatListModel { let allChannels: string[] = []; for (const chatModel of this.chatModels) { + if (chatModel.info.primaryChannel == undefined) continue; allChannels.push(chatModel.info.primaryChannel); } diff --git a/src/Model/chatModel.ts b/src/Model/chatModel.ts index 7c9e118e..d64a9411 100644 --- a/src/Model/chatModel.ts +++ b/src/Model/chatModel.ts @@ -1,6 +1,10 @@ // this file is responsible for managing chats. -import { DATA_VERSION, ValidObject, checkIsValidObject } from "./Utility/typeSafety"; +import { + DATA_VERSION, + ValidObject, + checkIsValidObject, +} from "./Utility/typeSafety"; import FileModel, { File } from "./fileModel"; import StorageModel, { storageKeys } from "./storageModel"; import { @@ -35,7 +39,7 @@ export default class ChatModel { // sorting get index(): number { return this.chatListModel.getIndexOfPrimaryChannel( - this.info.primaryChannel + this.info.primaryChannel ?? "" ); } @@ -90,6 +94,7 @@ export default class ChatModel { addMessage = async (chatMessage: ChatMessage): Promise => { await this.decryptMessage(chatMessage); + if (chatMessage.id == undefined) return; // message if (chatMessage.body != "") { @@ -99,7 +104,7 @@ export default class ChatModel { } // file - this.fileModel.handleStringifiedFile(chatMessage.stringifiedFile); + this.fileModel.handleStringifiedFile(chatMessage.stringifiedFile ?? ""); }; // delete @@ -146,7 +151,7 @@ export default class ChatModel { } const sorted = messages.sort((a, b) => - a.dateSent.localeCompare(b.dateSent) + (a.dateSent ?? "").localeCompare(b.dateSent ?? "") ); return sorted; } @@ -157,7 +162,7 @@ export default class ChatModel { if (senderName == "") return false; const allChannels = [this.info.primaryChannel]; - for (const secondaryChannel of this.info.secondaryChannels) { + for (const secondaryChannel of this.info.secondaryChannels ?? []) { allChannels.push(secondaryChannel); } @@ -166,7 +171,7 @@ export default class ChatModel { const chatMessage: ChatMessage = await ChatModel.createChatMessage( combinedChannel, senderName, - this.info.encryptionKey, + this.info.encryptionKey ?? "", body, file ); @@ -191,12 +196,12 @@ export default class ChatModel { decryptMessage = async (chatMessage: ChatMessage): Promise => { const decryptedBody: string = await decryptString( - chatMessage.body, - this.info.encryptionKey + chatMessage.body ?? "", + this.info.encryptionKey ?? "" ); const decryptedFile: string = await decryptString( chatMessage.stringifiedFile ?? "", - this.info.encryptionKey + this.info.encryptionKey ?? "" ); chatMessage.body = decryptedBody; chatMessage.stringifiedFile = decryptedFile; @@ -207,6 +212,8 @@ export default class ChatModel { }; subscribe = (): void => { + if (this.info.primaryChannel == undefined || this.info.primaryChannel == "") + return; this.connectionModel.addChannel(this.info.primaryChannel); }; @@ -271,9 +278,12 @@ export default class ChatModel { } if (encryptionKey != "") { - chatMessage.body = await encryptString(chatMessage.body, encryptionKey); + chatMessage.body = await encryptString( + chatMessage.body ?? "", + encryptionKey + ); chatMessage.stringifiedFile = await encryptString( - chatMessage.stringifiedFile, + chatMessage.stringifiedFile ?? "", encryptionKey ); } @@ -284,11 +294,11 @@ export default class ChatModel { // types export interface ChatInfo extends ValidObject { - primaryChannel: string; - secondaryChannels: string[]; - encryptionKey: string; + primaryChannel?: string; + secondaryChannels?: string[]; + encryptionKey?: string; - hasUnreadMessages: boolean; + hasUnreadMessages?: boolean; } export enum ChatMessageStatus { @@ -298,14 +308,14 @@ export enum ChatMessageStatus { } export interface ChatMessage extends ValidObject { - id: string; + id?: string; - channel: string; - sender: string; - body: string; - dateSent: string; + channel?: string; + sender?: string; + body?: string; + dateSent?: string; status?: ChatMessageStatus; - stringifiedFile: string; + stringifiedFile?: string; } diff --git a/src/Model/fileModel.ts b/src/Model/fileModel.ts index 0948db1d..2b3e0141 100644 --- a/src/Model/fileModel.ts +++ b/src/Model/fileModel.ts @@ -26,6 +26,7 @@ export default class FileModel { // storage storeFile = (file: File): void => { + if (file.contentVersions == undefined) return; for (const fileContent of file.contentVersions) { this.storeFileContent(file, fileContent); } @@ -39,7 +40,8 @@ export default class FileModel { ); // check if fileContent already exists - const existingFileContent: string | null = this.storageModel.read(fileContentPath); + const existingFileContent: string | null = + this.storageModel.read(fileContentPath); if (existingFileContent != null) return; const stringifiedContent: string = stringify(fileContent); @@ -51,6 +53,7 @@ export default class FileModel { }; listFileContents = (file: File): string[] => { + if (file.id == undefined) return []; const filePath: string[] = FileModel.getFilePath(file.id); return this.storageModel.list(filePath); }; @@ -88,14 +91,14 @@ export default class FileModel { }; static getFileContentName = (fileContent: FileContent): string => { - return fileContent.creationDate + fileContent.id; + return fileContent.creationDate ?? "" + fileContent.id ?? ""; }; static getFileContentPath = ( file: File, fileContentName: string ): string[] => { - const filePath: string[] = FileModel.getFilePath(file.id); + const filePath: string[] = FileModel.getFilePath(file.id ?? ""); return [...filePath, fileContentName]; }; @@ -104,20 +107,20 @@ export default class FileModel { dataVersion: DATA_VERSION, id: v4(), - contentVersions: [] - } - } + contentVersions: [], + }; + }; } // types export interface File extends ValidObject { - id: string; - contentVersions: FileContent[]; + id?: string; + contentVersions?: FileContent[]; } export interface FileContent extends ValidObject { - id: string; - creationDate: string; + id?: string; + creationDate?: string; - type: string; + type?: string; }