From 85185714ae94ef6797cc107dd052d211bc41bbdd Mon Sep 17 00:00:00 2001 From: Ryan Tharp Date: Tue, 19 Nov 2019 18:53:06 -0800 Subject: [PATCH] export a factory, LokiHomeServerInstance/LokiFileServerInstance split, verifyUserObjectDeviceMap change return to object, remove getDeviceMappingForUsers because too small, avatar map, adjust constant format --- js/modules/loki_file_server_api.js | 121 +++++++++++++++++++---------- 1 file changed, 79 insertions(+), 42 deletions(-) diff --git a/js/modules/loki_file_server_api.js b/js/modules/loki_file_server_api.js index 737b2ed6b..3a95a06fb 100644 --- a/js/modules/loki_file_server_api.js +++ b/js/modules/loki_file_server_api.js @@ -1,64 +1,49 @@ -/* global window, log, libloki */ +/* global log, libloki */ /* global storage: false */ /* global Signal: false */ /* global log: false */ const LokiAppDotNetAPI = require('./loki_app_dot_net_api'); -const DEVICE_MAPPING_ANNOTATION_KEY = 'network.loki.messenger.devicemapping'; +const DEVICE_MAPPING_USER_ANNOTATION_TYPE = + 'network.loki.messenger.devicemapping'; -// can have multiple of these objects instances as each user can have a +// can have multiple of these instances as each user can have a // different home server -class LokiFileServerAPI { +class LokiFileServerInstance { constructor(ourKey) { this.ourKey = ourKey; this._adnApi = new LokiAppDotNetAPI(ourKey); + this.avatarMap = {}; } - async establishConnection(serverUrl) { + // FIXME: we don't always need a token... this._server = await this._adnApi.findOrCreateServer(serverUrl); // TODO: Handle this failure gracefully if (!this._server) { log.error('Failed to establish connection to file server'); } } - async getUserDeviceMapping(pubKey) { const annotations = await this._server.getUserAnnotations(pubKey); const deviceMapping = annotations.find( - annotation => annotation.type === DEVICE_MAPPING_ANNOTATION_KEY + annotation => annotation.type === DEVICE_MAPPING_USER_ANNOTATION_TYPE ); return deviceMapping ? deviceMapping.value : null; } - async updateOurDeviceMapping() { - const isPrimary = !storage.get('isSecondaryDevice'); - let authorisations; - if (isPrimary) { - authorisations = await Signal.Data.getGrantAuthorisationsForPrimaryPubKey( - this.ourKey - ); - } else { - authorisations = [ - await Signal.Data.getGrantAuthorisationForSecondaryPubKey(this.ourKey), - ]; - } - return this._setOurDeviceMapping(authorisations, isPrimary); - } - - async getDeviceMappingForUsers(pubKeys) { - const users = await this._server.getUsers(pubKeys); - return users; - } - async verifyUserObjectDeviceMap(pubKeys, isRequest, iterator) { - const users = await this.getDeviceMappingForUsers(pubKeys); + const users = await this._server.getUsers(pubKeys); // go through each user and find deviceMap annotations const notFoundUsers = []; await Promise.all( users.map(async user => { let found = false; + // if this user has an avatar set, copy it into the map + this.avatarMap[user.username] = user.avatar_image + ? user.avatar_image.url + : false; if (!user.annotations || !user.annotations.length) { log.info( `verifyUserObjectDeviceMap no annotation for ${user.username}` @@ -66,7 +51,7 @@ class LokiFileServerAPI { return; } const mappingNote = user.annotations.find( - note => note.type === DEVICE_MAPPING_ANNOTATION_KEY + note => note.type === DEVICE_MAPPING_USER_ANNOTATION_TYPE ); const { authorisations } = mappingNote.value; if (!Array.isArray(authorisations)) { @@ -105,6 +90,10 @@ class LokiFileServerAPI { // checkSig disabled for now // const checkSigs = {}; // cache for authorisation const primaryPubKeys = []; + const result = { + verifiedPrimaryPKs: [], + slaveMap: {}, + }; // go through multiDeviceResults and get primary Pubkey await this.verifyUserObjectDeviceMap(pubKeys, true, (slaveKey, auth) => { @@ -144,7 +133,8 @@ class LokiFileServerAPI { // no valid primary pubkeys to check if (!primaryPubKeys.length) { // log.warn(`no valid primary pubkeys to check ${pubKeys}`); - return []; + // do we want to update slavePrimaryMap? + return result; } const verifiedPrimaryPKs = []; @@ -193,33 +183,80 @@ class LokiFileServerAPI { }); }); - // FIXME: move to a return value since we're only scoped to pubkeys given - // make new map final - window.lokiPublicChatAPI.slavePrimaryMap = newSlavePrimaryMap; - - log.info( - `Updated device mappings ${JSON.stringify( - window.lokiPublicChatAPI.slavePrimaryMap - )}` - ); + log.info(`Updated device mappings ${JSON.stringify(newSlavePrimaryMap)}`); - return verifiedPrimaryPKs; + result.verifiedPrimaryPKs = verifiedPrimaryPKs; + result.slaveMap = newSlavePrimaryMap; + return result; } +} +// extends LokiFileServerInstance with functions we'd only perform on our own home server +// so we don't accidentally send info to the wrong file server +class LokiHomeServerInstance extends LokiFileServerInstance { _setOurDeviceMapping(authorisations, isPrimary) { const content = { isPrimary: isPrimary ? '1' : '0', authorisations, }; return this._server.setSelfAnnotation( - DEVICE_MAPPING_ANNOTATION_KEY, + DEVICE_MAPPING_USER_ANNOTATION_TYPE, content ); } + async updateOurDeviceMapping() { + const isPrimary = !storage.get('isSecondaryDevice'); + let authorisations; + if (isPrimary) { + authorisations = await Signal.Data.getGrantAuthorisationsForPrimaryPubKey( + this.ourKey + ); + } else { + authorisations = [ + await Signal.Data.getGrantAuthorisationForSecondaryPubKey(this.ourKey), + ]; + } + return this._setOurDeviceMapping(authorisations, isPrimary); + } + uploadPrivateAttachment(data) { return this._server.uploadData(data); } } -module.exports = LokiFileServerAPI; +// this will be our instance factory +class LokiFileServerFactoryAPI { + constructor(ourKey) { + this.ourKey = ourKey; + this.servers = []; + } + + async establishHomeConnection(serverUrl) { + let thisServer = this.servers.find( + server => server._server.baseServerUrl === serverUrl + ); + if (!thisServer) { + thisServer = new LokiHomeServerInstance(this.ourKey); + log.info(`Registering HomeServer ${serverUrl}`); + await thisServer.establishConnection(serverUrl); + this.servers.push(thisServer); + } + return thisServer; + } + + async establishConnection(serverUrl) { + let thisServer = this.servers.find( + server => server._server.baseServerUrl === serverUrl + ); + if (!thisServer) { + thisServer = new LokiFileServerInstance(this.ourKey); + log.info(`Registering FileServer ${serverUrl}`); + await thisServer.establishConnection(serverUrl); + this.servers.push(thisServer); + } + return thisServer; + } +} + +module.exports = LokiFileServerFactoryAPI;