@ -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 LokiFileServer AP I {
class LokiFileServer Instance {
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 . getDeviceMappingFor Users( 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 ;