Update attachment pipeline to upload and download from loki fileserver

This commit is contained in:
Beaudan Brown 2019-10-15 13:40:56 +11:00
parent 6eef0b6d6b
commit 4e85435bf7
7 changed files with 58 additions and 43 deletions

View File

@ -136,7 +136,7 @@
<div class='capture-audio hide'>
<button class='microphone' {{#disable-inputs}} disabled="disabled" {{/disable-inputs}}></button>
</div>
<div class='choose-file hide'>
<div class='choose-file'>
<button class='paperclip thumbnail' {{#disable-inputs}} disabled="disabled" {{/disable-inputs}}></button>
<input type='file' class='file-input' multiple='multiple'>
</div>

View File

@ -220,7 +220,13 @@ class LokiAppDotNetServerAPI {
// make a request to the server
async serverRequest(endpoint, options = {}) {
const { params = {}, method, objBody, forceFreshToken = false } = options;
const {
params = {},
method,
rawBody,
objBody,
forceFreshToken = false,
} = options;
const url = new URL(`${this.baseServerUrl}/${endpoint}`);
if (params) {
url.search = new URLSearchParams(params);
@ -247,6 +253,8 @@ class LokiAppDotNetServerAPI {
if (objBody) {
headers['Content-Type'] = 'application/json';
fetchOptions.body = JSON.stringify(objBody);
} else if (rawBody) {
fetchOptions.body = rawBody;
}
fetchOptions.headers = new Headers(headers);
result = await nodeFetch(url, fetchOptions || undefined);

View File

@ -1,5 +1,7 @@
const LokiAppDotNetAPI = require('./loki_app_dot_net_api');
/* global log */
const DEVICE_MAPPING_ANNOTATION_KEY = 'network.loki.messenger.devicemapping';
// returns the LokiFileServerAPI constructor with the serverUrl already consumed
@ -31,6 +33,26 @@ class LokiFileServerAPI {
content
);
}
async uploadData(data) {
const endpoint = 'files';
const options = {
method: 'POST',
rawBody: data,
};
const { statusCode, response } = await this._server.serverRequest(
endpoint,
options
);
if (statusCode !== 200) {
log.warn('Failed to upload data to fileserver');
return null;
}
const url = response.data && response.data.url;
return url;
}
}
module.exports = LokiFileServerAPIWrapper;

View File

@ -2,10 +2,11 @@ const WebSocket = require('websocket').w3cwebsocket;
const fetch = require('node-fetch');
const ProxyAgent = require('proxy-agent');
const { Agent } = require('https');
const FormData = require('form-data');
const is = require('@sindresorhus/is');
/* global Buffer, setTimeout, log, _ */
/* global Buffer, setTimeout, log, _, lokiFileServerAPI */
/* eslint-disable more/no-then, no-bitwise, no-nested-ternary */
@ -843,41 +844,27 @@ function initialize({
});
}
function getAttachment(id) {
return _ajax({
call: 'attachment',
httpType: 'GET',
urlParameters: `/${id}`,
responseType: 'json',
validateResponse: { location: 'string' },
}).then(response =>
// Using _outerAJAX, since it's not hardcoded to the Signal Server
_outerAjax(response.location, {
contentType: 'application/octet-stream',
proxyUrl,
responseType: 'arraybuffer',
timeout: 0,
type: 'GET',
})
);
function getAttachment(fileUrl) {
return _outerAjax(fileUrl, {
contentType: 'application/octet-stream',
proxyUrl,
responseType: 'arraybuffer',
timeout: 0,
type: 'GET',
});
}
function putAttachment(encryptedBin) {
return _ajax({
call: 'attachment',
httpType: 'GET',
responseType: 'json',
}).then(response =>
// Using _outerAJAX, since it's not hardcoded to the Signal Server
_outerAjax(response.location, {
contentType: 'application/octet-stream',
data: encryptedBin,
processData: false,
proxyUrl,
timeout: 0,
type: 'PUT',
}).then(() => response.idString)
);
const formData = new FormData();
const buffer = Buffer.from(encryptedBin);
formData.append('type', 'network.loki');
formData.append('content', buffer, {
contentType: 'application/octet-stream',
name: 'content',
filename: 'attachment',
});
return lokiFileServerAPI.uploadData(formData);
}
// eslint-disable-next-line no-shadow

View File

@ -18,6 +18,7 @@
/* global lokiMessageAPI: false */
/* global lokiP2pAPI: false */
/* global feeds: false */
/* global WebAPI: false */
/* eslint-disable more/no-then */
/* eslint-disable no-unreachable */
@ -28,6 +29,7 @@ function MessageReceiver(username, password, signalingKey, options = {}) {
this.signalingKey = signalingKey;
this.username = username;
this.password = password;
this.server = WebAPI.connect({ username, password });
if (!options.serverTrustRoot) {
throw new Error('Server trust root is required!');
@ -1435,9 +1437,7 @@ MessageReceiver.prototype.extend({
};
},
async downloadAttachment(attachment) {
window.log.info('Not downloading attachments.');
return Promise.reject();
// The attachment id is actually just the absolute url of the attachment
const encrypted = await this.server.getAttachment(attachment.id);
const { key, digest, size } = attachment;

View File

@ -191,8 +191,8 @@ MessageSender.prototype = {
return textsecure.crypto
.encryptAttachment(attachment.data, proto.key, iv)
.then(result =>
this.server.putAttachment(result.ciphertext).then(id => {
proto.id = id;
this.server.putAttachment(result.ciphertext).then(url => {
proto.id = url;
proto.contentType = attachment.contentType;
proto.digest = result.digest;
@ -310,8 +310,6 @@ MessageSender.prototype = {
const silent = false;
// Remove this when we add support for attachments
message.attachments = [];
message.attachmentPointers = [];
message.preview = [];
if (message.quote) {
message.quote.attachments = [];

View File

@ -309,7 +309,7 @@ message AttachmentPointer {
VOICE_MESSAGE = 1;
}
optional fixed64 id = 1;
optional string id = 1;
optional string contentType = 2;
optional bytes key = 3;
optional uint32 size = 4;