121 lines
5.4 KiB
Vue
121 lines
5.4 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>
|
|
<div class="bd-e2eeTaContainer">
|
|
<v-popover :popoverClass="['bd-popover', 'bd-e2eePopover', {'bd-e2eePopoverOver': popoutPositionSetting.value === 'over'}]"
|
|
:trigger="popoutPositionSetting.value === 'over' && popoutTriggerSetting.value === 'hover' ? 'hover' : 'click'"
|
|
:placement="popoutPositionSetting.value === 'over' ? 'top-start' : 'top'"
|
|
:disabled="error && DiscordApi.currentChannel.type !== 'DM'">
|
|
|
|
<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 v-tooltip="'Toggle Encryption'" /></div>
|
|
<div v-close-popover @click="showUploadDialog" v-if="!error"><MiImagePlus v-tooltip="'Upload Encrypted Image'" /></div>
|
|
<div v-close-popover @click="generatePublicKey" v-if="DiscordApi.currentChannel.type === 'DM'"><MiIcVpnKey v-tooltip="'Begin Key Exchange'" /></div>
|
|
</template>
|
|
</v-popover>
|
|
<div class="bd-taDivider"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { Utils, FileUtils, ClientIPC } from 'common';
|
|
import { E2EE } from 'builtin';
|
|
import { Settings, DiscordApi, Reflection } from 'modules';
|
|
import { Toasts } from 'ui';
|
|
import { MiLock, MiImagePlus, MiIcVpnKey } from 'commoncomponents';
|
|
|
|
export default {
|
|
components: {
|
|
MiLock, MiImagePlus, MiIcVpnKey
|
|
},
|
|
data() {
|
|
return {
|
|
E2EE,
|
|
DiscordApi,
|
|
state: 'loading',
|
|
error: null,
|
|
popoutPositionSetting: Settings.getSetting('security', 'e2ee-popout', 'position'),
|
|
popoutTriggerSetting: Settings.getSetting('security', 'e2ee-popout', 'trigger')
|
|
};
|
|
},
|
|
methods: {
|
|
async showUploadDialog() {
|
|
const dialogResult = await ClientIPC.send('bd-native-open', {properties: ['openFile']});
|
|
if (!dialogResult || !dialogResult.length) return;
|
|
|
|
const readFile = await FileUtils.readFileBuffer(dialogResult[0]);
|
|
const FileActions = Reflection.module.byProps('makeFile');
|
|
const Uploader = Reflection.module.byProps('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() {
|
|
const keyExchange = E2EE.createKeyExchange(DiscordApi.currentChannel.id);
|
|
if (keyExchange === null) {
|
|
Toasts.warning('Key exchange for channel already in progress!');
|
|
return;
|
|
}
|
|
E2EE.preExchangeState = E2EE.encryptNewMessages;
|
|
E2EE.encryptNewMessages = false; // Disable encrypting new messages so we won't encrypt public keys
|
|
const publicKeyMessage = `\`\`\`\n-----BEGIN PUBLIC KEY-----\n${keyExchange}\n-----END PUBLIC KEY-----\n\`\`\``;
|
|
Reflection.modules.DraftActions.saveDraft(DiscordApi.currentChannel.id, publicKeyMessage);
|
|
Toasts.info('Key exchange started. Expires in 30 seconds');
|
|
}
|
|
},
|
|
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>
|