aboutsummaryrefslogtreecommitdiffhomepage
path: root/public/scripts/chat.js
diff options
context:
space:
mode:
authorMarvin Borner2019-02-13 17:14:47 +0100
committerMarvin Borner2019-02-13 17:14:47 +0100
commit6a967887df29c0051a22df96463aed63b7ece729 (patch)
tree15b91fccb40990ebc2e0c822b843582e672f0465 /public/scripts/chat.js
parent8cad9c810741088a1874b58e80245ce83909b582 (diff)
Code cleanup
Diffstat (limited to 'public/scripts/chat.js')
-rw-r--r--public/scripts/chat.js505
1 files changed, 288 insertions, 217 deletions
diff --git a/public/scripts/chat.js b/public/scripts/chat.js
index 1777318..c1dee3e 100644
--- a/public/scripts/chat.js
+++ b/public/scripts/chat.js
@@ -7,16 +7,19 @@
// general imports
const $ = require('jquery');
+const swal = require('sweetalert');
+const xkcdPassword = require('xkcd-password');
const encryption = require('./encryption');
const wordList = require('./wordlist');
const pinInput = require('./input_pin');
-const swal = require('sweetalert');
-const xkcdPassword = require('xkcd-password');
// setup vars
const host = 'meta.marvinborner.de';
-let peerId, call, fingerprint, connectedPeer;
-let connectedPeers = []; // TODO: Save new peers in array
+let peerId;
+let call;
+let fingerprint;
+let connectedPeer;
+const connectedPeers = []; // TODO: Save new peers in array
// setup generator
const generator = new xkcdPassword();
@@ -26,15 +29,17 @@ generator.initWithWordList(wordList);
* Sets up encryption, user etc.
*/
(async () => {
- // generate peerId
- if (localStorage.getItem('peer_id') === null) {
- peerId = await generator.generate().then(words => words.join('-'));
- localStorage.setItem('peer_id', peerId);
- } else
- peerId = localStorage.getItem('peer_id');
+ // generate peerId
+ if (localStorage.getItem('peer_id') === null) {
+ peerId = await generator.generate()
+ .then(words => words.join('-'));
+ localStorage.setItem('peer_id', peerId);
+ } else {
+ peerId = localStorage.getItem('peer_id');
+ }
- encryption.setup();
- await evaluateKeyGeneration();
+ encryption.setupDatabase();
+ await evaluateKeyGeneration();
})();
/**
@@ -42,239 +47,305 @@ generator.initWithWordList(wordList);
* @returns {Promise<void>}
*/
async function evaluateKeyGeneration() {
- if (localStorage.getItem('database') === 'success' && await encryption.check()) {
- pinInput.init(async (pin, tryCount) => {
- try {
- if (await encryption.getId(await encryption.getPublic()) !== peerId ||
- await encryption.getFingerprint(await encryption.getPublic()) !== await encryption.generateFingerprint(pin)) throw "Not verified!";
- fingerprint = await encryption.generateFingerprint(pin);
- await encryption.decryptPrivate(await encryption.getPrivate(), fingerprint);
- chat()
- } catch (err) { // decrypting failed
- if (tryCount === 3) {
- encryption.reset();
- console.error('Too many tries!');
- pinInput.failure('This account got removed, the site will reload.');
- setTimeout(() => location.reload(true), 1500)
- } else if (err === 'Not verified!') {
- console.error(err);
- pinInput.failure(err);
- } else {
- console.error(err);
- pinInput.failure(err.message);
- }
- }
- });
- } else {
- pinInput.init(async pin => {
- console.log('[LOG] No existing keys found! Generating...');
- pinInput.generate();
- fingerprint = await encryption.generateFingerprint(pin);
- await encryption.generate(peerId, fingerprint).then(() => chat())
- });
- }
+ if (localStorage.getItem('database') === 'success' && await encryption.isEncrypted()) {
+ pinInput.init(async (pin, tryCount) => {
+ try {
+ if (await encryption.getPublicKeyPeerId(await encryption.getPublicKey()) !== peerId
+ || await encryption.getPublicKeyFingerprint(await encryption.getPublicKey())
+ !== await encryption.generateFingerprint(pin)) {
+ throw 'Not verified!';
+ }
+ fingerprint = await encryption.generateFingerprint(pin);
+ await encryption.decryptPrivateKey(await encryption.getPrivateKey(), fingerprint);
+ chat();
+ } catch (err) { // decrypting failed
+ if (tryCount === 3) {
+ encryption.reset();
+ console.error('Too many tries!');
+ pinInput.failure('This account got removed, the site will reload.');
+ setTimeout(() => location.reload(true), 1500);
+ } else if (err === 'Not verified!') {
+ console.error(err);
+ pinInput.failure(err);
+ } else {
+ console.error(err);
+ pinInput.failure(err.message);
+ }
+ }
+ });
+ } else {
+ pinInput.init(async (pin) => {
+ console.log('[LOG] No existing keys found! Generating...');
+ pinInput.generate();
+ fingerprint = await encryption.generateFingerprint(pin);
+ await encryption.generateKeys(peerId, fingerprint)
+ .then(() => chat());
+ });
+ }
}
/**
* Initializes chat functions
*/
function chat() {
- // hide pin input and display chat
- $('#enter_pin').hide();
- $('#chat').fadeIn();
+ // hide pin input and display chat
+ $('#enter_pin')
+ .hide();
+ $('#chat')
+ .fadeIn();
+
+ // start the peer
+ const peer = new Peer(peerId, {
+ host,
+ port: 4242,
+ path: '/api',
+ secure: true,
+ debug: 0,
+ });
- // start the peer
- const peer = new Peer(peerId, {host: host, port: 4242, path: '/api', secure: true, debug: 0});
+ // Peer events
+ peer.on('call', call => getMediaStream(stream => call.answer(stream))); // TODO: Ask for call accept
- // Peer events
- peer.on('call', call => getMediaStream(stream => call.answer(stream))); // TODO: Ask for call accept
- peer.on('open', id => {
- console.log('[LOG] Your ID is', id);
- swal('Hello world!', 'Your ID is "' + id + '".\nYou can share this ID with your friends so they can chat with you!', 'success')
+ peer.on('open', (id) => {
+ console.log('[LOG] Your ID is', id);
+ swal(
+ 'Hello world!',
+ `Your ID is "${id}".\nYou can share this ID with your friends so they can chat with you!`,
+ 'success',
+ );
+ });
+
+ peer.on('error', (err) => {
+ console.error(err);
+ if (err.type === 'network') {
+ swal('Connection to server lost!', '', 'error');
+ } else if (err.type === 'browser-incompatible') {
+ swal('Your server is not compatible!', 'Please update or use another browser!', 'error');
+ } else if (err.type === 'peer-unavailable') {
+ swal('Peer could not be found!', '', 'error');
+ } else if (err.type === 'unavailable-id') {
+ swal('Ou snap! Your ID isn\'t available!', '', 'error');
+ } else {
+ swal('Unhandled Error!', `You just threw up this error: ${err.type}`, 'error');
+ }
+ });
+
+ peer.on('connection', async (conn) => {
+ connectedPeer = conn;
+ console.log('[LOG] Connected to', connectedPeer.peer);
+ swal(
+ 'New connection!',
+ `You have successfully connected to the user ${connectedPeer.peer}!`,
+ 'success',
+ );
+ encryption.getMessages(
+ connectedPeer.peer,
+ await encryption.getPublicKeyPeerId(connectedPeer.peer),
+ await encryption.getPrivateKey(), fingerprint,
+ )
+ .then(messages => messages.forEach(async data => await receivedMessage(`${data.message} - ${data.time}`, true)));
+ connectedPeer.on('open', async () => transferKey(await encryption.getPublicKey()));
+ connectedPeer.on('data', async (message) => {
+ console.log('[LOG] Received new message!');
+ await receivedMessage(message);
});
- peer.on('error', err => {
- console.error(err);
- if (err.type === 'network') swal('Connection to server lost!', '', 'error');
- else if (err.type === 'browser-incompatible') swal('Your server is not compatible!', 'Please update or use another browser!', 'error');
- else if (err.type === 'peer-unavailable') swal('Peer could not be found!', '', 'error');
- else if (err.type === 'unavailable-id') swal('Ou snap! Your ID isn\'t available!', '', 'error');
- else swal('Unhandled Error!', 'You just threw up this error: ' + err.type, 'error');
+ });
+
+ /**
+ * Connects to a peer via his id
+ * @param id
+ * @returns {Promise<void>}
+ */
+ async function connect(id) {
+ const connectionId = (await generator.generate()).join('-');
+ console.log('[LOG] Connecting to', id);
+ console.log('[LOG] Your connection ID is', connectionId);
+ connectedPeer = peer.connect(id, { label: connectionId });
+ console.log('[LOG] Connected with', connectedPeer.peer);
+ encryption.getMessages(
+ connectedPeer.peer,
+ await encryption.getPublicKeyPeerId(connectedPeer.peer),
+ await encryption.getPrivateKey(), fingerprint,
+ )
+ .then(messages => messages.forEach(async data => await receivedMessage(`${data.message} - ${data.time}`, true)));
+ connectedPeer.on('open', async () => {
+ swal(`Successfully connected to "${connectedPeer.peer}"!`, '', 'success');
+ transferKey(await encryption.getPublicKey());
});
- peer.on('connection', async conn => {
- connectedPeer = conn;
- console.log('[LOG] Connected to', connectedPeer.peer);
- swal('New connection!', `You have successfully connected to the user ${connectedPeer.peer}!`, 'success');
- encryption.getMsgs(connectedPeer.peer, await encryption.get(connectedPeer.peer), await encryption.getPrivate(), fingerprint).then(messages =>
- messages.forEach(async data => await receivedMessage(`${data.message} - ${data.time}`, true))
- );
- connectedPeer.on('open', async () => transferKey(await encryption.getPublic()));
- connectedPeer.on('data', async message => {
- console.log('[LOG] Received new message!');
- await receivedMessage(message);
- })
+ connectedPeer.on('data', async (message) => {
+ console.log('[LOG] Received new message!');
+ await receivedMessage(message);
});
+ }
- /**
- * Connects to a peer via his id
- * @param id
- * @returns {Promise<void>}
- */
- async function connect(id) {
- const connectionId = (await generator.generate()).join('-');
- console.log('[LOG] Connecting to', id);
- console.log('[LOG] Your connection ID is', connectionId);
- connectedPeer = peer.connect(id, {label: connectionId});
- console.log('[LOG] Connected with', connectedPeer.peer);
- encryption.getMsgs(connectedPeer.peer, await encryption.get(connectedPeer.peer), await encryption.getPrivate(), fingerprint).then(messages =>
- messages.forEach(async data => await receivedMessage(`${data.message} - ${data.time}`, true))
- );
- connectedPeer.on('open', async () => {
- swal(`Successfully connected to "${connectedPeer.peer}"!`, '', 'success');
- transferKey(await encryption.getPublic())
- });
- connectedPeer.on('data', async message => {
- console.log('[LOG] Received new message!');
- await receivedMessage(message);
- });
- }
-
- /**
- * Sends a message to the peer with which you're currently connected
- * @param message
- * @returns {Promise<void>}
- */
- async function sendMessage(message) {
- console.log(`[LOG] Sending message '${message}' to ${connectedPeer.peer}`);
- connectedPeer.send({
- type: 'text',
- data: await encryption.encrypt(message, await encryption.get(connectedPeer.peer), await encryption.getPrivate(), fingerprint)
- });
- await receivedMessage(message, true);
- }
+ /**
+ * Sends a message to the peer with which you're currently connected
+ * @param message
+ * @returns {Promise<void>}
+ */
+ async function sendMessage(message) {
+ console.log(`[LOG] Sending message '${message}' to ${connectedPeer.peer}`);
+ connectedPeer.send({
+ type: 'text',
+ data: await encryption.encrypt(
+ message,
+ await encryption.getPeerPublicKey(connectedPeer.peer),
+ await encryption.getPrivateKey(), fingerprint,
+ ),
+ });
+ await receivedMessage(message, true);
+ }
- /**
- * Transfers the (public) key to the currently connected peer
- * @param key
- */
- function transferKey(key) {
- console.log(`[LOG] Transferring key to ${connectedPeer.peer}`);
- connectedPeer.send({type: 'key', data: key});
- }
+ /**
+ * Transfers the (public) key to the currently connected peer
+ * @param key
+ */
+ function transferKey(key) {
+ console.log(`[LOG] Transferring key to ${connectedPeer.peer}`);
+ connectedPeer.send({
+ type: 'key',
+ data: key,
+ });
+ }
- /**
- * Renders and processes the incoming messages
- * @param message
- * @param self
- */
- async function receivedMessage(message, self = false) {
- if (self) {
- $('#messages').append(`<span style="color: green">${message}</span><br>`);
- } else {
- if (message.type === 'text') {
- await encryption.storeMsg(connectedPeer.peer, message.data, fingerprint);
- await encryption.decrypt(message.data, await encryption.get(connectedPeer.peer), await encryption.getPrivate(), fingerprint)
- .then(plaintext => $('#messages').append(`<span>${plaintext}</span><br>`));
- } else if (message.type === 'key') {
- await encryption.store(connectedPeer.peer, message.data)
- }
- }
+ /**
+ * Renders and processes the incoming messages
+ * @param message
+ * @param self
+ */
+ async function receivedMessage(message, self = false) {
+ if (self) {
+ $('#messages')
+ .append(`<span style="color: green">${message}</span><br>`);
+ } else if (message.type === 'text') {
+ await encryption.storeMessage(connectedPeer.peer, message.data, fingerprint);
+ await encryption.decrypt(
+ message.data,
+ await encryption.getPeerPublicKey(connectedPeer.peer),
+ await encryption.getPrivateKey(),
+ fingerprint,
+ )
+ .then(plaintext => $('#messages')
+ .append(`<span>${plaintext}</span><br>`));
+ } else if (message.type === 'key') {
+ await encryption.storePeerPublicKey(connectedPeer.peer, message.data);
}
+ }
- /**
- * Sends a message of the text input field
- * @returns {Promise<void>}
- */
- async function sendMessageFromInput() {
- return await sendMessage($('#message').val()) & $('#message').val('')
- }
+ /**
+ * Sends a message of the text input field
+ * @returns {Promise<String>}
+ */
+ async function sendMessageFromInput() {
+ const messageInput = $('#message');
+ return await sendMessage(messageInput.val()) & messageInput.val('');
+ }
- /*+
- * Shows warning modal and deletes account
- */
- function deleteAccount() {
- swal({
- title: 'Are you sure?',
- text: 'Once deleted, you will not be able to recover any messages or connections!',
- icon: 'warning',
- buttons: true,
- dangerMode: true,
- }).then(willDelete => {
- if (willDelete) {
- encryption.reset();
- swal('Successfully deleted your data.', '', 'success').then(() => location.reload(true));
- }
- });
- }
+ /**
+ * Shows warning modal and deletes account
+ */
+ function deleteAccount() {
+ swal({
+ title: 'Are you sure?',
+ text: 'Once deleted, you will not be able to recover any messages or connections!',
+ icon: 'warning',
+ buttons: true,
+ dangerMode: true,
+ })
+ .then((willDelete) => {
+ if (willDelete) {
+ encryption.reset();
+ swal('Successfully deleted your data.', '', 'success')
+ .then(() => location.reload(true));
+ }
+ });
+ }
- /**
- * Shows modal for adding a contact
- */
- function addContact() {
- swal('Add a contact', {
- buttons: true,
- content: 'input',
- attributes: {
- placeholder: 'Contact ID',
- },
- }).then(contactId => {
- if (contactId.match(/^([a-zA-Z]*-[a-zA-Z]*)+$/)) {
- connect(contactId).then(() => swal({
- title: 'Connecting...',
- icon: 'info',
- text: ' ',
- buttons: false,
- closeOnClickOutside: false,
- closeOnEsc: false
- }))
- } else
- swal('Invalid ID!', '', 'error')
- })
- }
+ /**
+ * Shows modal for adding a contact
+ */
+ function addContact() {
+ swal('Add a contact', {
+ buttons: true,
+ content: 'input',
+ attributes: {
+ placeholder: 'Contact ID',
+ },
+ })
+ .then((contactId) => {
+ if (contactId.match(/^([a-zA-Z]*-[a-zA-Z]*)+$/)) {
+ connect(contactId)
+ .then(() => swal({
+ title: 'Connecting...',
+ icon: 'info',
+ text: ' ',
+ buttons: false,
+ closeOnClickOutside: false,
+ closeOnEsc: false,
+ }));
+ } else {
+ swal('Invalid ID!', '', 'error');
+ }
+ });
+ }
- /**
- * Click events
- */
- $(document).ready(() => {
- $('#send_message').on('click', async () => await sendMessageFromInput());
- $('#message').on('keydown', async e => {
- if (e.key === 'Enter') await sendMessageFromInput()
+ /**
+ * Click events
+ */
+ $(document)
+ .ready(() => {
+ $('#send_message')
+ .on('click', async () => await sendMessageFromInput());
+ $('#message')
+ .on('keydown', async (e) => {
+ if (e.key === 'Enter') await sendMessageFromInput();
});
- // FABs
- $('#add_contact').on('click', () => addContact());
- $('#logout').on('click', () => location.reload(true));
- $('#delete').on('click', () => deleteAccount());
- $('#anonymize').on('click', () => {
- if (peer.disconnected) {
- swal('Reconnected to broker server!', 'You can now connect to new peers again.', 'success').then(() =>
- peer.reconnect()
- )
- } else {
- peer.disconnect();
- swal('Disconnected from broker server!', 'You will still be able to send and receive messages.', 'success')
- }
+ // FABs
+ $('#add_contact')
+ .on('click', () => addContact());
+ $('#logout')
+ .on('click', () => location.reload(true));
+ $('#delete')
+ .on('click', () => deleteAccount());
+ $('#anonymize')
+ .on('click', () => {
+ if (peer.disconnected) {
+ swal('Reconnected to broker server!', 'You can now connect to new peers again.', 'success')
+ .then(() => peer.reconnect());
+ } else {
+ peer.disconnect();
+ swal('Disconnected from broker server!', 'You will still be able to send and receive messages.', 'success');
+ }
});
- $('#call').on('click', () => getMediaStream(stream => {
- call = peer.call(peerId, stream); // TODO: Encrypt call
- initCall(call)
+ $('#call')
+ .on('click', () => getMediaStream((stream) => {
+ call = peer.call(peerId, stream); // TODO: Encrypt call
+ initCall(call);
}));
});
}
function getMediaStream(callback) {
- navigator.getUserMedia(
- {audio: true, video: {width: 1280, height: 720}},
- stream => callback(stream),
- err => console.error(err)
- )
+ navigator.getUserMedia(
+ {
+ audio: true,
+ video: {
+ width: 1280,
+ height: 720,
+ },
+ },
+ stream => callback(stream),
+ err => console.error(err),
+ );
}
function initCall(call) {
- call.on('stream', stream => {
- const video = document.querySelector('video');
- video.srcObject = stream;
- video.onloadedmetadata = () => {
- video.play();
- };
- })
+ call.on('stream', (stream) => {
+ const video = document.querySelector('video');
+ video.srcObject = stream;
+ video.onloadedmetadata = () => {
+ video.play();
+ };
+ });
}