import { Observer } from "../observe/Observer"; import { TemplateFactory } from "../template/TemplateFactory"; import { ChatModel } from "../model/ChatModel"; import { ChatMessageViewModel } from "../viewmodel/ChatMessageViewModel"; import * as log from 'loglevel'; import * as DOMPurify from 'dompurify'; import { MarkDownService } from "../service/MarkDownService"; import { MarkDownItMarkDownService } from "../service/MarkDownItMarkDownService"; import { JsonAPI } from "../singleton/JsonAPI"; import { MessageCipherDTO } from "../dto/MessageCipherDTO"; import { SJCLEncryptionService } from "../service/SJCLEncryptionService"; import { EncryptionService } from "../service/EncryptionService"; import { ChatMessageDTO } from "../dto/ChatMessageDTO"; import { fetchHandler } from "./FetchHandler"; import { ChatViewDeps } from "./ChatViewDeps"; export class ChatView implements Observer { private readonly _chatModel: ChatModel; private readonly _messageContainer: HTMLElement; // private readonly _messageSendTemplate = TemplateFactory.getTemplate('msg_container_send_template'); // private readonly _messageReceiveTemplate = TemplateFactory.getTemplate('msg_container_template'); // private readonly _markdownService: MarkDownService = new MarkDownItMarkDownService(); // private readonly _encryptionService: EncryptionService = new SJCLEncryptionService(); private readonly _messageSendTemplate: Handlebars.TemplateDelegate; private readonly _messageReceiveTemplate: Handlebars.TemplateDelegate; private readonly _markdownService: MarkDownService; private readonly _encryptionService: EncryptionService; constructor(deps: ChatViewDeps) { this._messageContainer = deps.messageContainer; this._chatModel = deps.chatModel; this._messageSendTemplate = deps.messageSendTemplate; this._messageReceiveTemplate = deps.messageReceiveTemplate; this._markdownService = deps.markdownService; this._encryptionService = deps.encryptionService; this.addEventListeners(); } update(data: ChatMessageViewModel[]): void { log.info('ChatView: updating view'); // let html: string = ""; this._messageContainer.innerHTML = ""; data.forEach((vm: ChatMessageViewModel) => { const vmTemp = vm; vmTemp.message = this._markdownService.render(vm.message); /** Very Important!!! * Sanitizing HTML before displaying on webpage to prevent XSS attacks!! */ let rendered; if (vmTemp.fromUser == JsonAPI.principleName) { rendered = DOMPurify.sanitize(this._messageSendTemplate(vmTemp)); } else { rendered = DOMPurify.sanitize(this._messageReceiveTemplate(vmTemp)); } $(this._messageContainer).append(rendered); log.debug() // html += this._messageSendTemplate(vm); }); // html = DOMPurify.sanitize(md.render(html)); // this._element.innerHTML = html; // log.debug(this._element.innerHTML); } private addEventListeners(): void { this.addChatFormEL(); } private addChatFormEL() { const chatForm = document.getElementById('chatMessageForm') as HTMLSelectElement; if (chatForm == null) { log.error("Chat form is null"); } else { chatForm.addEventListener('submit', (e) => this.createChatMessageDTO(e, chatForm)) } } private createChatMessageDTO(e: Event, chatForm: HTMLSelectElement): void { e.preventDefault(); let contactName = JsonAPI.contactName; if(contactName == null) { log.error("Contact name is null"); return; } if (!chatForm.checkValidity()) { console.log("error"); chatForm.classList.add('was-validated'); return; } chatForm.classList.add('was-validated'); const chatInput = document.getElementById('chatInput') as HTMLInputElement; const passphraseInput = document.getElementById('passphrase') as HTMLInputElement; if (chatInput.value == '' || chatInput.value == null) { log.error("Chat input is null."); return; } if (passphraseInput.value == '' || passphraseInput.value == null) { log.error("Chat input is null."); return; } // @ts-ignore const messageContent = chatInput.value; const context = { fromUser: JsonAPI.principleName, toUser: "", message: this._markdownService.render(messageContent), messageTime: new Date().toLocaleString() }; // @ts-ignore const msgContainer: string = this._messageSendTemplate(context); $(this._messageContainer).append(DOMPurify.sanitize(msgContainer)); // scrollChatAreaAnimated(2400); // let messageCipher = sjcl.encrypt(passphraseInput.value, messageContent, { mode: "gcm", ts: 128, adata: "", iter: iterations }); let messageCipher: MessageCipherDTO = this._encryptionService.encrypt(passphraseInput.value, messageContent) // let messageCipherJson = JSON.parse(messageCipher); let chatMessageDTO = { "fromUser": JsonAPI.principleName, "toUser": contactName, "messageCipher": messageCipher, // "messageTime": null } // @ts-ignore this.sendMessageAJAX(chatMessageDTO); } private sendMessageAJAX(chatMessageDTO: ChatMessageDTO): void { let headers = new Headers(); // console.log("Token = " + btoa("hmm" + ":" + "hmm")) // headers.append('Accept','application/json') headers.append('Content-Type', 'application/json'); // headers.append('Authorization', basicAuthToken); // @ts-ignore headers.append('X-AUTH-TOKEN', JsonAPI.authToken); fetch(JsonAPI.MESSAGE_POST, { method: 'POST', headers: headers, body: JSON.stringify(chatMessageDTO) }) .then(response => { log.debug(response); return response.clone(); }) .then(response => fetchHandler(response)); } }