WIP: clean up V1 multi device

This commit is contained in:
Ryan ZHAO
2021-02-17 10:51:02 +11:00
parent c5cc191ff3
commit 3285975b1a
19 changed files with 19 additions and 791 deletions

View File

@@ -9,7 +9,6 @@ import org.session.libsignal.utilities.Base64
import org.session.libsignal.utilities.JsonUtil
import org.session.libsignal.service.loki.api.onionrequests.OnionRequestAPI
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
import org.session.libsignal.service.loki.protocol.shelved.multidevice.DeviceLink
import org.session.libsignal.service.loki.utilities.*
import java.net.URL
import java.util.concurrent.ConcurrentHashMap
@@ -17,21 +16,6 @@ import java.util.concurrent.ConcurrentHashMap
class FileServerAPI(public val server: String, userPublicKey: String, userPrivateKey: ByteArray, private val database: LokiAPIDatabaseProtocol) : DotNetAPI() {
companion object {
// region Settings
/**
* Deprecated.
*/
private val deviceLinkType = "network.loki.messenger.devicemapping"
/**
* Deprecated.
*/
private val deviceLinkRequestCache = ConcurrentHashMap<String, Promise<Set<DeviceLink>, Exception>>()
/**
* Deprecated.
*/
private val deviceLinkUpdateInterval = 60 * 1000
private val lastDeviceLinkUpdate = ConcurrentHashMap<String, Long>()
internal val fileServerPublicKey = "62509D59BDEEC404DD0D489C1E15BA8F94FD3D619B01C1BF48A9922BFCB7311C"
internal val maxRetryCount = 4
@@ -63,172 +47,6 @@ class FileServerAPI(public val server: String, userPublicKey: String, userPrivat
// endregion
}
// region Device Link Update Result
sealed class DeviceLinkUpdateResult {
class Success(val publicKey: String, val deviceLinks: Set<DeviceLink>) : DeviceLinkUpdateResult()
class Failure(val publicKey: String, val error: Exception) : DeviceLinkUpdateResult()
}
// endregion
// region API
public fun hasDeviceLinkCacheExpired(referenceTime: Long = System.currentTimeMillis(), publicKey: String): Boolean {
return !lastDeviceLinkUpdate.containsKey(publicKey) || (referenceTime - lastDeviceLinkUpdate[publicKey]!! > deviceLinkUpdateInterval)
}
fun getDeviceLinks(publicKey: String, isForcedUpdate: Boolean = false): Promise<Set<DeviceLink>, Exception> {
return Promise.of(setOf())
/*
if (deviceLinkRequestCache.containsKey(publicKey) && !isForcedUpdate) {
val result = deviceLinkRequestCache[publicKey]
if (result != null) { return result } // A request was already pending
}
val promise = getDeviceLinks(setOf(publicKey), isForcedUpdate)
deviceLinkRequestCache[publicKey] = promise
promise.always {
deviceLinkRequestCache.remove(publicKey)
}
return promise
*/
}
fun getDeviceLinks(publicKeys: Set<String>, isForcedUpdate: Boolean = false): Promise<Set<DeviceLink>, Exception> {
return Promise.of(setOf())
/*
val validPublicKeys = publicKeys.filter { PublicKeyValidation.isValid(it) }
val now = System.currentTimeMillis()
// IMPORTANT: Don't fetch device links for the current user (i.e. don't remove the it != userHexEncodedPublicKey) check below
val updatees = validPublicKeys.filter { it != userPublicKey && (hasDeviceLinkCacheExpired(now, it) || isForcedUpdate) }.toSet()
val cachedDeviceLinks = validPublicKeys.minus(updatees).flatMap { database.getDeviceLinks(it) }.toSet()
if (updatees.isEmpty()) {
return Promise.of(cachedDeviceLinks)
} else {
return getUserProfiles(updatees, server, true).map(SnodeAPI.sharedContext) { data ->
data.map dataMap@ { node ->
val publicKey = node["username"] as String
val annotations = node["annotations"] as List<Map<*, *>>
val deviceLinksAnnotation = annotations.find {
annotation -> (annotation["type"] as String) == deviceLinkType
} ?: return@dataMap DeviceLinkUpdateResult.Success(publicKey, setOf())
val value = deviceLinksAnnotation["value"] as Map<*, *>
val deviceLinksAsJSON = value["authorisations"] as List<Map<*, *>>
val deviceLinks = deviceLinksAsJSON.mapNotNull { deviceLinkAsJSON ->
try {
val masterPublicKey = deviceLinkAsJSON["primaryDevicePubKey"] as String
val slavePublicKey = deviceLinkAsJSON["secondaryDevicePubKey"] as String
var requestSignature: ByteArray? = null
var authorizationSignature: ByteArray? = null
if (deviceLinkAsJSON["requestSignature"] != null) {
val base64EncodedSignature = deviceLinkAsJSON["requestSignature"] as String
requestSignature = Base64.decode(base64EncodedSignature)
}
if (deviceLinkAsJSON["grantSignature"] != null) {
val base64EncodedSignature = deviceLinkAsJSON["grantSignature"] as String
authorizationSignature = Base64.decode(base64EncodedSignature)
}
val deviceLink = DeviceLink(masterPublicKey, slavePublicKey, requestSignature, authorizationSignature)
val isValid = deviceLink.verify()
if (!isValid) {
Log.d("Loki", "Ignoring invalid device link: $deviceLinkAsJSON.")
return@mapNotNull null
}
deviceLink
} catch (e: Exception) {
Log.d("Loki", "Failed to parse device links for $publicKey from $deviceLinkAsJSON due to error: $e.")
null
}
}.toSet()
DeviceLinkUpdateResult.Success(publicKey, deviceLinks)
}
}.recover { e ->
publicKeys.map { DeviceLinkUpdateResult.Failure(it, e) }
}.success { updateResults ->
for (updateResult in updateResults) {
if (updateResult is DeviceLinkUpdateResult.Success) {
database.clearDeviceLinks(updateResult.publicKey)
updateResult.deviceLinks.forEach { database.addDeviceLink(it) }
} else {
// Do nothing
}
}
}.map(SnodeAPI.sharedContext) { updateResults ->
val deviceLinks = mutableListOf<DeviceLink>()
for (updateResult in updateResults) {
when (updateResult) {
is DeviceLinkUpdateResult.Success -> {
lastDeviceLinkUpdate[updateResult.publicKey] = now
deviceLinks.addAll(updateResult.deviceLinks)
}
is DeviceLinkUpdateResult.Failure -> {
if (updateResult.error is SnodeAPI.Error.ParsingFailed) {
lastDeviceLinkUpdate[updateResult.publicKey] = now // Don't infinitely update in case of a parsing failure
}
deviceLinks.addAll(database.getDeviceLinks(updateResult.publicKey)) // Fall back on cached device links in case of a failure
}
}
}
// Updatees that didn't show up in the response provided by the file server are assumed to not have any device links
val excludedUpdatees = updatees.filter { updatee ->
updateResults.find { updateResult ->
when (updateResult) {
is DeviceLinkUpdateResult.Success -> updateResult.publicKey == updatee
is DeviceLinkUpdateResult.Failure -> updateResult.publicKey == updatee
}
} == null
}
excludedUpdatees.forEach {
lastDeviceLinkUpdate[it] = now
}
deviceLinks.union(cachedDeviceLinks)
}.recover {
publicKeys.flatMap { database.getDeviceLinks(it) }.toSet()
}
}
*/
}
fun setDeviceLinks(deviceLinks: Set<DeviceLink>): Promise<Unit, Exception> {
return Promise.of(Unit)
/*
val isMaster = deviceLinks.find { it.masterPublicKey == userPublicKey } != null
val deviceLinksAsJSON = deviceLinks.map { it.toJSON() }
val value = if (deviceLinks.isNotEmpty()) mapOf( "isPrimary" to isMaster, "authorisations" to deviceLinksAsJSON ) else null
val annotation = mapOf( "type" to deviceLinkType, "value" to value )
val parameters = mapOf( "annotations" to listOf( annotation ) )
return retryIfNeeded(maxRetryCount) {
execute(HTTPVerb.PATCH, server, "/users/me", parameters = parameters)
}.map { Unit }
*/
}
fun addDeviceLink(deviceLink: DeviceLink): Promise<Unit, Exception> {
return Promise.of(Unit)
/*
Log.d("Loki", "Updating device links.")
return getDeviceLinks(userPublicKey, true).bind { deviceLinks ->
val mutableDeviceLinks = deviceLinks.toMutableSet()
mutableDeviceLinks.add(deviceLink)
setDeviceLinks(mutableDeviceLinks)
}.success {
database.addDeviceLink(deviceLink)
}.map { Unit }
*/
}
fun removeDeviceLink(deviceLink: DeviceLink): Promise<Unit, Exception> {
return Promise.of(Unit)
/*
Log.d("Loki", "Updating device links.")
return getDeviceLinks(userPublicKey, true).bind { deviceLinks ->
val mutableDeviceLinks = deviceLinks.toMutableSet()
mutableDeviceLinks.remove(deviceLink)
setDeviceLinks(mutableDeviceLinks)
}.success {
database.removeDeviceLink(deviceLink)
}.map { Unit }
*/
}
// endregion
// region Open Group Server Public Key
fun getPublicKeyForOpenGroupServer(openGroupServer: String): Promise<String, Exception> {
val publicKey = database.getOpenGroupPublicKey(openGroupServer)

View File

@@ -38,7 +38,6 @@ import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.color.MaterialColor;
import org.session.libsignal.utilities.logging.Log;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.loki.protocol.shelved.multidevice.MultiDeviceProtocol;
import org.session.libsession.messaging.avatars.ContactColors;
import org.session.libsession.messaging.avatars.ContactPhoto;
import org.session.libsession.messaging.avatars.GroupRecordContactPhoto;
@@ -550,12 +549,7 @@ public class Recipient implements RecipientModifiedListener {
}
public synchronized boolean isBlocked() {
String masterPublicKey = MultiDeviceProtocol.shared.getMasterDevice(this.address.serialize());
if (masterPublicKey != null) {
return Recipient.from(context, Address.Companion.fromSerialized(masterPublicKey), false).blocked;
} else {
return blocked;
}
return blocked;
}
public void setBlocked(boolean blocked) {