171 lines
8.1 KiB
Vue
171 lines
8.1 KiB
Vue
/**
|
|
* BetterDiscord E2EE Component
|
|
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
|
* All rights reserved.
|
|
* https://betterdiscord.net
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
<template>
|
|
<<<<<<< Updated upstream
|
|
<div class="bd-e2eeTaContainer" @contextmenu.prevent="channelType === 'DM' && $refs.ee2eLockContextMenu.open()">
|
|
=======
|
|
<div class="bd-e2eeTaContainer" @contextmenu.prevent="currentChannel.type === 'DM' && $refs.ee2eLockContextMenu.open()">
|
|
>>>>>>> Stashed changes
|
|
<v-popover popoverClass="bd-popover bd-e2eePopover" placement="top">
|
|
<div v-if="error" class="bd-e2eeTaBtn bd-e2eeLock bd-error">
|
|
<MiLock v-tooltip="error" />
|
|
</div>
|
|
<div v-else-if="state === 'loading'" class="bd-e2eeTaBtn bd-e2eeLock bd-loading bd-warn">
|
|
<MiLock v-tooltip="'Loading'" />
|
|
</div>
|
|
|
|
<div v-else-if="!E2EE.encryptNewMessages" class="bd-e2eeTaBtn bd-e2eeLock bd-warn">
|
|
<MiLock v-tooltip="'New messages will not be encrypted.'" />
|
|
</div>
|
|
|
|
<div v-else class="bd-e2eeTaBtn bd-e2eeLock bd-ok">
|
|
<MiLock v-tooltip="'Ready!'" />
|
|
</div>
|
|
<template slot="popover">
|
|
<div @click="toggleEncrypt" :class="{'bd-warn': !E2EE.encryptNewMessages, 'bd-ok': E2EE.encryptNewMessages}"><MiLock size="16" v-tooltip="'Toggle Encryption'" /></div>
|
|
<div v-close-popover @click="showUploadDialog" v-if="!error"><MiImagePlus size="16" v-tooltip="'Upload Encrypted Image'" /></div>
|
|
<!-- Using these icons for now -->
|
|
<div v-close-popover @click="generatePublicKey" v-if="currentChannel.type === 'DM'"><MiPencil size="16" v-tooltip="'Generate Public Key'" /></div>
|
|
<div v-close-popover @click="receivePublicKey" v-if="currentChannel.type === 'DM' && E2EE.ecdhStorage[currentChannel.id]"><MiRefresh size="16" v-tooltip="'Receive Public Key'" /></div>
|
|
</template>
|
|
</v-popover>
|
|
<div class="bd-taDivider"></div>
|
|
<context-menu id="bd-e2eeLockContextMenu" class="bd-e2eeLockContextMenu" ref="ee2eLockContextMenu" v-if="channelType === 'DM'">
|
|
<li class="bd-e2eeLockContextMenuOption" @click="generatePublicKey()">Generate Public Key</li>
|
|
<li class="bd-e2eeLockContextMenuOption" @click="computeSharedSecret()">Receive Public Key</li>
|
|
</context-menu>
|
|
</div>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
import fs from 'fs';
|
|
import { Utils } from 'common';
|
|
import { remote } from 'electron';
|
|
import { E2EE } from 'builtin';
|
|
import { DiscordApi, Security } from 'modules';
|
|
<<<<<<< Updated upstream
|
|
import { MiLock, MiPlus, MiImagePlus } from '../ui/components/common/MaterialIcon';
|
|
import contextMenu from 'vue-context-menu';
|
|
=======
|
|
import { MiLock, MiPlus, MiImagePlus, MiPencil, MiRefresh } from '../ui/components/common/MaterialIcon';
|
|
>>>>>>> Stashed changes
|
|
import { Toasts } from 'ui';
|
|
|
|
export default {
|
|
components: { MiLock, MiPlus, MiImagePlus, MiPencil, MiRefresh },
|
|
data() {
|
|
return {
|
|
E2EE,
|
|
state: 'loading',
|
|
error: null,
|
|
<<<<<<< Updated upstream
|
|
channelType: DiscordApi.currentChannel.type
|
|
=======
|
|
currentChannel: DiscordApi.currentChannel
|
|
>>>>>>> Stashed changes
|
|
};
|
|
},
|
|
methods: {
|
|
async showUploadDialog() {
|
|
const dialogResult = remote.dialog.showOpenDialog({ properties: ['openFile'] });
|
|
if (!dialogResult) return;
|
|
|
|
const readFile = fs.readFileSync(dialogResult[0]);
|
|
const FileActions = _bd.WebpackModules.getModuleByProps(["makeFile"]);
|
|
const Uploader = _bd.WebpackModules.getModuleByProps(["instantBatchUpload"]);
|
|
|
|
const img = await Utils.getImageFromBuffer(readFile);
|
|
|
|
const canvas = document.createElement('canvas');
|
|
canvas.height = img.height;
|
|
canvas.width = img.width;
|
|
const arrBuffer = await Utils.canvasToArrayBuffer(canvas);
|
|
const encrypted = E2EE.encrypt(img.src.replace('data:;base64,', ''));
|
|
const hmac = await E2EE.createHmac(encrypted);
|
|
const encodedBytes = new TextEncoder().encode(encrypted + hmac);
|
|
Uploader.upload(DiscordApi.currentChannel.id, FileActions.makeFile(new Uint8Array([...new Uint8Array(arrBuffer), ...encodedBytes]), 'bde2ee.png'));
|
|
},
|
|
toggleEncrypt() {
|
|
const newState = !E2EE.encryptNewMessages;
|
|
E2EE.encryptNewMessages = newState;
|
|
if (!newState) {
|
|
Toasts.warning('New messages will not be encrypted');
|
|
return;
|
|
}
|
|
Toasts.success('New messages will be encrypted');
|
|
},
|
|
generatePublicKey() {
|
|
<<<<<<< Updated upstream
|
|
const dmChannelID = location.pathname.split("/")[3];
|
|
=======
|
|
const dmChannelID = DiscordApi.currentChannel.id;
|
|
>>>>>>> Stashed changes
|
|
const publicKeyMessage = `My public key is: \`${E2EE.createKeyExchange(dmChannelID)}\`. Please give me your public key if you haven't done so and add my public key by pasting it in the chat textbox, right clicking the lock icon, and selecting \`Receive Public Key\`.`;
|
|
const chatInput = document.getElementsByClassName('da-textArea')[0];
|
|
chatInput.value = publicKeyMessage;
|
|
const evt = { currentTarget: chatInput };
|
|
chatInput[Object.keys(chatInput).find(k => k.startsWith('__reactEventHandlers'))].onChange.call(chatInput, evt);
|
|
<<<<<<< Updated upstream
|
|
},
|
|
computeSharedSecret() {
|
|
try {
|
|
const dmChannelID = location.pathname.split("/")[3];
|
|
const chatInput = document.getElementsByClassName('da-textArea')[0];
|
|
const otherPublicKey = chatInput.value;
|
|
const secret = E2EE.computeSecret(dmChannelID, otherPublicKey);
|
|
E2EE.setKey(dmChannelID, secret);
|
|
chatInput.value = "";
|
|
const evt = { currentTarget: chatInput };
|
|
chatInput[Object.keys(chatInput).find(k => k.startsWith('__reactEventHandlers'))].onChange.call(chatInput, evt);
|
|
Toasts.success("Encryption key has been set for this DM channel.");
|
|
} catch (e) {
|
|
Toasts.error("Invalid public key. Please set up a new key exchange.");
|
|
console.error(e);
|
|
=======
|
|
this.$forceUpdate();
|
|
},
|
|
receivePublicKey() {
|
|
try {
|
|
const dmChannelID = DiscordApi.currentChannel.id;
|
|
const chatInput = document.getElementsByClassName('da-textArea')[0];
|
|
const otherPublicKey = chatInput.value;
|
|
const secret = E2EE.computeSecret(dmChannelID, otherPublicKey);
|
|
E2EE.setKey(dmChannelID, secret);
|
|
chatInput.value = "";
|
|
const evt = { currentTarget: chatInput };
|
|
chatInput[Object.keys(chatInput).find(k => k.startsWith('__reactEventHandlers'))].onChange.call(chatInput, evt);
|
|
Toasts.success("Encryption key has been set for this DM channel.");
|
|
this.$forceUpdate();
|
|
} catch (e) {
|
|
Toasts.error("Invalid public key. Please set up a new key exchange.");
|
|
console.error(e);
|
|
>>>>>>> Stashed changes
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
if (!E2EE.master) {
|
|
this.error = 'No master key set!';
|
|
return;
|
|
}
|
|
const haveKey = E2EE.getKey(DiscordApi.currentChannel.id);
|
|
if (!haveKey) {
|
|
this.error = 'No key for channel!';
|
|
return;
|
|
}
|
|
this.state = 'OK';
|
|
this.error = null;
|
|
}
|
|
}
|
|
</script>
|