diff --git a/app/sql.js b/app/sql.js index 24835bbc4..77bde9694 100644 --- a/app/sql.js +++ b/app/sql.js @@ -95,7 +95,7 @@ module.exports = { saveConversations, getConversationById, savePublicServerToken, - getPublicServerTokenByServerName, + getPublicServerTokenByServerUrl, updateConversation, removeConversation, getAllConversations, @@ -795,7 +795,7 @@ async function updateToLokiSchemaVersion1(currentVersion, instance) { await instance.run( `CREATE TABLE servers( - server STRING PRIMARY KEY ASC, + serverUrl STRING PRIMARY KEY ASC, token TEXT );` ); @@ -833,7 +833,7 @@ async function updateToLokiSchemaVersion1(currentVersion, instance) { }; const lokiPublicServerData = { - server: 'chat.lokinet.org', + serverUrl: 'https://chat.lokinet.org', token: null, }; @@ -851,24 +851,24 @@ async function updateToLokiSchemaVersion1(currentVersion, instance) { const publicChatData = { ...baseData, - id: `publicChat:1@${lokiPublicServerData.server}`, - server: lokiPublicServerData.server, + id: 'publicChat:1@chat.lokinet.org', + server: lokiPublicServerData.serverUrl, name: 'Loki Public Chat', channelId: '1', }; - const { server, token } = lokiPublicServerData; + const { serverUrl, token } = lokiPublicServerData; await instance.run( `INSERT INTO servers ( - server, + serverUrl, token ) values ( - $server, + $serverUrl, $token );`, { - $server: server, + $serverUrl: serverUrl, $token: token, } ); @@ -1622,27 +1622,27 @@ async function removeConversation(id) { } async function savePublicServerToken(data) { - const { server, token } = data; + const { serverUrl, token } = data; await db.run( `INSERT OR REPLACE INTO servers ( - server, + serverUrl, token ) values ( - $server, + $serverUrl, $token )`, { - $server: server, + $serverUrl: serverUrl, $token: token, } ); } -async function getPublicServerTokenByServerName(server) { +async function getPublicServerTokenByServerUrl(serverUrl) { const row = await db.get( - 'SELECT * FROM servers WHERE server = $server;', + 'SELECT * FROM servers WHERE serverUrl = $serverUrl;', { - $server: server, + $serverUrl: serverUrl, } ); diff --git a/js/models/conversations.js b/js/models/conversations.js index f3c47596d..4b674503e 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -11,6 +11,7 @@ clipboard, BlockedNumberController, lokiP2pAPI, + lokiPublicChatAPI, JobQueue */ @@ -1376,7 +1377,7 @@ options.messageType = message.get('type'); options.isPublic = this.isPublic(); if (this.isPublic()) { - options.channelSettings = this.getPublicSource(); + options.publicSendData = await this.getPublicSendData(); } const groupNumbers = this.getRecipients(); @@ -2068,6 +2069,22 @@ conversationId: this.get('id'), }; }, + async getPublicSendData() { + const serverAPI = lokiPublicChatAPI.findOrCreateServer( + this.get('server') + ); + // Can be null if fails + const token = await serverAPI.getOrRefreshServerToken(); + const channelAPI = serverAPI.findOrCreateChannel( + this.get('channelId'), + this.id + ); + const publicEndpoint = channelAPI.getEndpoint(); + return { + publicEndpoint, + token, + }; + }, // SIGNAL PROFILES diff --git a/js/modules/data.js b/js/modules/data.js index 9d9978843..80c21bdee 100644 --- a/js/modules/data.js +++ b/js/modules/data.js @@ -122,7 +122,7 @@ module.exports = { getAllPublicConversations, getPublicConversationsByServer, savePublicServerToken, - getPublicServerTokenByServerName, + getPublicServerTokenByServerUrl, getAllGroupsInvolvingId, searchConversations, @@ -773,8 +773,8 @@ async function savePublicServerToken(data) { await channels.savePublicServerToken(data); } -async function getPublicServerTokenByServerName(server) { - const token = await channels.getPublicServerTokenByServerName(server); +async function getPublicServerTokenByServerUrl(serverUrl) { + const token = await channels.getPublicServerTokenByServerUrl(serverUrl); return token; } diff --git a/js/modules/loki_message_api.js b/js/modules/loki_message_api.js index 3e7767bb9..556069bb0 100644 --- a/js/modules/loki_message_api.js +++ b/js/modules/loki_message_api.js @@ -1,7 +1,6 @@ /* eslint-disable no-await-in-loop */ /* eslint-disable no-loop-func */ -/* global log, dcodeIO, window, callWorker, - lokiP2pAPI, lokiSnodeAPI, lokiPublicChatAPI, textsecure */ +/* global log, dcodeIO, window, callWorker, lokiP2pAPI, lokiSnodeAPI, textsecure */ const _ = require('lodash'); const { rpc } = require('./loki_rpc'); @@ -81,7 +80,7 @@ class LokiMessageAPI { isPing = false, isPublic = false, numConnections = DEFAULT_CONNECTIONS, - channelSettings = null, + publicSendData = null, } = options; // Data required to identify a message in a conversation const messageEventData = { @@ -90,20 +89,12 @@ class LokiMessageAPI { }; if (isPublic) { - // could we emit back to LokiPublicChannelAPI somehow? - const { server, channelId, conversationId } = channelSettings; - const serverAPI = lokiPublicChatAPI.findOrCreateServer(server); - const token = await serverAPI.getServerToken(); + const { token, publicEndpoint } = publicSendData; if (!token) { throw new window.textsecure.PublicChatError( - `Failed to retrieve valid token for ${conversationId}` + `Failed to retrieve valid token for ${publicEndpoint}` ); } - const channelAPI = serverAPI.findOrCreateChannel( - channelId, - conversationId - ); - const publicEndpoint = channelAPI.getEndpoint(conversationId); const { profile } = data; let displayName = 'Anonymous'; diff --git a/js/modules/loki_public_chat_api.js b/js/modules/loki_public_chat_api.js index 6f2e1b916..89d0fea7c 100644 --- a/js/modules/loki_public_chat_api.js +++ b/js/modules/loki_public_chat_api.js @@ -46,12 +46,11 @@ class LokiPublicChatAPI extends EventEmitter { } class LokiPublicServerAPI { - constructor(chatAPI, hostport) { + constructor(chatAPI, url) { this.chatAPI = chatAPI; - this.server = hostport; this.channels = []; this.tokenPromise = null; - this.baseServerUrl = `https://${this.server}`; + this.baseServerUrl = url; } findOrCreateChannel(channelId, conversationId) { let thisChannel = this.channels.find( @@ -80,12 +79,14 @@ class LokiPublicServerAPI { } async getOrRefreshServerToken() { - let token = await Signal.Data.getPublicServerTokenByServerName(this.server); + let token = await Signal.Data.getPublicServerTokenByServerUrl( + this.baseServerUrl + ); if (!token) { token = await this.refreshServerToken(); if (token) { await Signal.Data.savePublicServerToken({ - server: this.server, + serverUrl: this.baseServerUrl, token, }); } @@ -176,7 +177,7 @@ class LokiPublicChannelAPI { } getEndpoint() { - const endpoint = `https://${this.serverAPI.server}/channels/${ + const endpoint = `${this.serverAPI.baseServerUrl}/channels/${ this.channelId }/messages`; return endpoint; @@ -255,7 +256,10 @@ class LokiPublicChannelAPI { let timestamp = new Date(adnMessage.created_at).getTime(); let from = adnMessage.user.username; let source; - if (adnMessage.annotations.length) { + if (adnMessage.is_deleted) { + return; + } + if (adnMessage.annotations !== []) { const noteValue = adnMessage.annotations[0].value; ({ from, timestamp, source } = noteValue); } diff --git a/libloki/crypto.js b/libloki/crypto.js index df0b60a7f..f8ad8d7f2 100644 --- a/libloki/crypto.js +++ b/libloki/crypto.js @@ -34,8 +34,8 @@ async function DHDecrypt(symmetricKey, ivAndCiphertext) { const iv = ivAndCiphertext.slice(0, IV_LENGTH); - const cipherText = ivAndCiphertext.slice(IV_LENGTH); - return libsignal.crypto.decrypt(symmetricKey, cipherText, iv); + const ciphertext = ivAndCiphertext.slice(IV_LENGTH); + return libsignal.crypto.decrypt(symmetricKey, ciphertext, iv); } class FallBackSessionCipher { @@ -131,18 +131,18 @@ return this._ephemeralPubKeyHex; } - async decrypt(snodeAddress, ivAndCipherTextBase64) { - const ivAndCipherText = dcodeIO.ByteBuffer.wrap( - ivAndCipherTextBase64, + async decrypt(snodeAddress, ivAndCiphertextBase64) { + const ivAndCiphertext = dcodeIO.ByteBuffer.wrap( + ivAndCiphertextBase64, 'base64' ).toArrayBuffer(); const symmetricKey = await this._getSymmetricKey(snodeAddress); try { - const decrypted = await DHDecrypt(symmetricKey, ivAndCipherText); + const decrypted = await DHDecrypt(symmetricKey, ivAndCiphertext); const decoder = new TextDecoder(); return decoder.decode(decrypted); } catch (e) { - return ivAndCipherText; + return ivAndCiphertext; } } @@ -153,17 +153,15 @@ plainText = textEncoder.encode(plainText); } const symmetricKey = await this._getSymmetricKey(snodeAddress); - const cipherText = await DHEncrypt(symmetricKey, plainText); - return dcodeIO.ByteBuffer.wrap(cipherText).toString('base64'); + const ciphertext = await DHEncrypt(symmetricKey, plainText); + return dcodeIO.ByteBuffer.wrap(ciphertext).toString('base64'); } } - async function decryptToken({ ivAndCipherText64, serverPubKey64 }) { - const ivAndCipherText = new Uint8Array( - dcodeIO.ByteBuffer.fromBase64(ivAndCipherText64).toArrayBuffer() + async function decryptToken({ cipherText64, serverPubKey64 }) { + const ivAndCiphertext = new Uint8Array( + dcodeIO.ByteBuffer.fromBase64(cipherText64).toArrayBuffer() ); - const iv = ivAndCipherText.slice(0, IV_LENGTH); - const cipherText = ivAndCipherText.slice(IV_LENGTH); const serverPubKey = new Uint8Array( dcodeIO.ByteBuffer.fromBase64(serverPubKey64).toArrayBuffer() @@ -174,7 +172,8 @@ privKey ); - const token = await libsignal.crypto.decrypt(symmetricKey, cipherText, iv); + const token = await DHDecrypt(symmetricKey, ivAndCiphertext); + const tokenString = dcodeIO.ByteBuffer.wrap(token).toString('utf8'); return tokenString; } diff --git a/libtextsecure/outgoing_message.js b/libtextsecure/outgoing_message.js index 996983590..ca4142313 100644 --- a/libtextsecure/outgoing_message.js +++ b/libtextsecure/outgoing_message.js @@ -50,12 +50,12 @@ function OutgoingMessage( messageType, isPing, isPublic, - channelSettings, + publicSendData, } = options || {}; this.numberInfo = numberInfo; this.isPublic = isPublic; - this.channelSettings = channelSettings; + this.publicSendData = publicSendData; this.senderCertificate = senderCertificate; this.online = online; this.messageType = messageType || 'outgoing'; @@ -205,7 +205,7 @@ OutgoingMessage.prototype = { }; options.isPublic = this.isPublic; if (this.isPublic) { - options.channelSettings = this.channelSettings; + options.publicSendData = this.publicSendData; } await lokiMessageAPI.sendMessage(pubKey, data, timestamp, ttl, options); } catch (e) {