mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-25 22:17:20 +00:00
Handle unpair request flag.
This commit is contained in:
parent
c66786e0f1
commit
3a79e1f215
@ -331,11 +331,21 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||||
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent();
|
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent();
|
||||||
|
|
||||||
|
if (message.isUnpairingRequest()) {
|
||||||
|
// Make sure we got the request from our primary device
|
||||||
|
String ourPrimaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
|
||||||
|
if (ourPrimaryDevice != null && ourPrimaryDevice.equals(content.getSender())) {
|
||||||
|
MultiDeviceUtilities.checkForRevocation(context);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (message.isEndSession()) handleEndSessionMessage(content, smsMessageId);
|
if (message.isEndSession()) handleEndSessionMessage(content, smsMessageId);
|
||||||
else if (message.isGroupUpdate()) handleGroupMessage(content, message, smsMessageId);
|
else if (message.isGroupUpdate()) handleGroupMessage(content, message, smsMessageId);
|
||||||
else if (message.isExpirationUpdate()) handleExpirationUpdate(content, message, smsMessageId);
|
else if (message.isExpirationUpdate())
|
||||||
else if (isMediaMessage) handleMediaMessage(content, message, smsMessageId, Optional.absent());
|
handleExpirationUpdate(content, message, smsMessageId);
|
||||||
else if (message.getBody().isPresent()) handleTextMessage(content, message, smsMessageId, Optional.absent());
|
else if (isMediaMessage)
|
||||||
|
handleMediaMessage(content, message, smsMessageId, Optional.absent());
|
||||||
|
else if (message.getBody().isPresent())
|
||||||
|
handleTextMessage(content, message, smsMessageId, Optional.absent());
|
||||||
|
|
||||||
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))) {
|
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))) {
|
||||||
handleUnknownGroupMessage(content, message.getGroupInfo().get());
|
handleUnknownGroupMessage(content, message.getGroupInfo().get());
|
||||||
@ -352,6 +362,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
|
|
||||||
// Loki - Handle friend request logic if needed
|
// Loki - Handle friend request logic if needed
|
||||||
updateFriendRequestStatusIfNeeded(envelope, content, message);
|
updateFriendRequestStatusIfNeeded(envelope, content, message);
|
||||||
|
}
|
||||||
} else if (content.getSyncMessage().isPresent()) {
|
} else if (content.getSyncMessage().isPresent()) {
|
||||||
TextSecurePreferences.setMultiDevice(context, true);
|
TextSecurePreferences.setMultiDevice(context, true);
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.*
|
|||||||
import org.thoughtcrime.securesms.util.DynamicTheme
|
import org.thoughtcrime.securesms.util.DynamicTheme
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage
|
import org.thoughtcrime.securesms.util.DynamicLanguage
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
import nl.komponents.kovenant.then
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender
|
import org.thoughtcrime.securesms.sms.MessageSender
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
@ -44,9 +45,10 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity(), DeviceLinki
|
|||||||
val database = DatabaseFactory.getLokiAPIDatabase(this)
|
val database = DatabaseFactory.getLokiAPIDatabase(this)
|
||||||
database.removePairingAuthorisation(ourPublicKey, devicePublicKey)
|
database.removePairingAuthorisation(ourPublicKey, devicePublicKey)
|
||||||
// Update mapping on the file server
|
// Update mapping on the file server
|
||||||
LokiStorageAPI.shared.updateUserDeviceMappings()
|
LokiStorageAPI.shared.updateUserDeviceMappings().success {
|
||||||
// Send a background message to let the device know that it has been revoked
|
// Send an unpair request to let the device know that it has been revoked
|
||||||
MessageSender.sendBackgroundMessage(this, devicePublicKey)
|
MessageSender.sendUnpairRequest(this, devicePublicKey)
|
||||||
|
}
|
||||||
// Refresh the list
|
// Refresh the list
|
||||||
this.deviceListFragment.refresh()
|
this.deviceListFragment.refresh()
|
||||||
Toast.makeText(this, R.string.DeviceListActivity_unlinked_device, Toast.LENGTH_LONG).show()
|
Toast.makeText(this, R.string.DeviceListActivity_unlinked_device, Toast.LENGTH_LONG).show()
|
||||||
|
@ -6,6 +6,7 @@ import nl.komponents.kovenant.Promise
|
|||||||
import nl.komponents.kovenant.all
|
import nl.komponents.kovenant.all
|
||||||
import nl.komponents.kovenant.functional.bind
|
import nl.komponents.kovenant.functional.bind
|
||||||
import nl.komponents.kovenant.functional.map
|
import nl.komponents.kovenant.functional.map
|
||||||
|
import nl.komponents.kovenant.then
|
||||||
import nl.komponents.kovenant.toFailVoid
|
import nl.komponents.kovenant.toFailVoid
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||||
@ -27,6 +28,23 @@ import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.concurrent.schedule
|
import kotlin.concurrent.schedule
|
||||||
|
|
||||||
|
fun checkForRevocation(context: Context) {
|
||||||
|
val primaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context) ?: return
|
||||||
|
val ourDevice = TextSecurePreferences.getLocalNumber(context)
|
||||||
|
|
||||||
|
LokiStorageAPI.shared.fetchDeviceMappings(primaryDevice).bind { mappings ->
|
||||||
|
val ourMapping = mappings.find { it.secondaryDevicePublicKey == ourDevice }
|
||||||
|
if (ourMapping != null) throw Error("Device has not been revoked")
|
||||||
|
// remove pairing auths for our device
|
||||||
|
DatabaseFactory.getLokiAPIDatabase(context).removePairingAuthorisations(ourDevice)
|
||||||
|
LokiStorageAPI.shared.updateUserDeviceMappings()
|
||||||
|
}.success {
|
||||||
|
// TODO: Revoke here
|
||||||
|
}.fail { error ->
|
||||||
|
Log.d("Loki", "Revocation check failed: $error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Promise<Map<String, LokiThreadFriendRequestStatus>, Exception> {
|
fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Promise<Map<String, LokiThreadFriendRequestStatus>, Exception> {
|
||||||
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||||
return LokiStorageAPI.shared.getAllDevicePublicKeys(hexEncodedPublicKey).map { keys ->
|
return LokiStorageAPI.shared.getAllDevicePublicKeys(hexEncodedPublicKey).map { keys ->
|
||||||
|
@ -11,39 +11,58 @@ import org.whispersystems.libsignal.util.guava.Optional
|
|||||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
|
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
data class BackgroundMessage private constructor(val recipient: String, val body: String?, val friendRequest: Boolean, val unpairingRequest: Boolean) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun create(recipient: String) = BackgroundMessage(recipient, null, false, false)
|
||||||
|
@JvmStatic
|
||||||
|
fun createFriendRequest(recipient: String, messageBody: String) = BackgroundMessage(recipient, messageBody, true, false)
|
||||||
|
@JvmStatic
|
||||||
|
fun createUnpairingRequest(recipient: String) = BackgroundMessage(recipient, null, false, true)
|
||||||
|
|
||||||
|
internal fun parse(serialized: String): BackgroundMessage {
|
||||||
|
val node = JsonUtil.fromJson(serialized)
|
||||||
|
val recipient = node.get("recipient").asText()
|
||||||
|
val body = if (node.hasNonNull("body")) node.get("body").asText() else null
|
||||||
|
val friendRequest = node.get("friendRequest").asBoolean(false)
|
||||||
|
val unpairingRequest = node.get("unpairingRequest").asBoolean(false)
|
||||||
|
return BackgroundMessage(recipient, body, friendRequest, unpairingRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serialize(): String {
|
||||||
|
val map = mapOf("recipient" to recipient, "body" to body, "friendRequest" to friendRequest, "unpairingRequest" to unpairingRequest)
|
||||||
|
return JsonUtil.toJson(map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PushBackgroundMessageSendJob private constructor(
|
class PushBackgroundMessageSendJob private constructor(
|
||||||
parameters: Parameters,
|
parameters: Parameters,
|
||||||
private val recipient: String,
|
private val message: BackgroundMessage
|
||||||
private val messageBody: String?,
|
|
||||||
private val friendRequest: Boolean
|
|
||||||
) : BaseJob(parameters) {
|
) : BaseJob(parameters) {
|
||||||
companion object {
|
companion object {
|
||||||
const val KEY = "PushBackgroundMessageSendJob"
|
const val KEY = "PushBackgroundMessageSendJob"
|
||||||
|
|
||||||
private val TAG = PushBackgroundMessageSendJob::class.java.simpleName
|
private val TAG = PushBackgroundMessageSendJob::class.java.simpleName
|
||||||
|
|
||||||
private val KEY_RECIPIENT = "recipient"
|
private val KEY_MESSAGE = "message"
|
||||||
private val KEY_MESSAGE_BODY = "message_body"
|
|
||||||
private val KEY_FRIEND_REQUEST = "asFriendRequest"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(recipient: String): this(recipient, null, false)
|
constructor(message: BackgroundMessage) : this(Parameters.Builder()
|
||||||
constructor(recipient: String, messageBody: String?, friendRequest: Boolean) : this(Parameters.Builder()
|
|
||||||
.addConstraint(NetworkConstraint.KEY)
|
.addConstraint(NetworkConstraint.KEY)
|
||||||
.setQueue(KEY)
|
.setQueue(KEY)
|
||||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||||
.setMaxAttempts(1)
|
.setMaxAttempts(1)
|
||||||
.build(),
|
.build(),
|
||||||
recipient, messageBody, friendRequest)
|
message)
|
||||||
|
|
||||||
override fun serialize(): Data {
|
override fun serialize(): Data {
|
||||||
return Data.Builder()
|
return Data.Builder()
|
||||||
.putString(KEY_RECIPIENT, recipient)
|
.putString(KEY_MESSAGE, message.serialize())
|
||||||
.putString(KEY_MESSAGE_BODY, messageBody)
|
|
||||||
.putBoolean(KEY_FRIEND_REQUEST, friendRequest)
|
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,22 +71,24 @@ class PushBackgroundMessageSendJob private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun onRun() {
|
public override fun onRun() {
|
||||||
val message = SignalServiceDataMessage.newBuilder()
|
val dataMessage = SignalServiceDataMessage.newBuilder()
|
||||||
.withTimestamp(System.currentTimeMillis())
|
.withTimestamp(System.currentTimeMillis())
|
||||||
.withBody(messageBody)
|
.withBody(message.body)
|
||||||
|
|
||||||
if (friendRequest) {
|
if (message.friendRequest) {
|
||||||
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(recipient)
|
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(message.recipient)
|
||||||
message.withPreKeyBundle(bundle)
|
dataMessage.withPreKeyBundle(bundle)
|
||||||
.asFriendRequest(true)
|
.asFriendRequest(true)
|
||||||
|
} else if (message.unpairingRequest) {
|
||||||
|
dataMessage.asUnpairingRequest(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||||
val address = SignalServiceAddress(recipient)
|
val address = SignalServiceAddress(message.recipient)
|
||||||
try {
|
try {
|
||||||
messageSender.sendMessage(-1, address, Optional.absent<UnidentifiedAccessPair>(), message.build()) // The message ID doesn't matter
|
messageSender.sendMessage(-1, address, Optional.absent<UnidentifiedAccessPair>(), dataMessage.build()) // The message ID doesn't matter
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to send background message to: $recipient.")
|
Log.d("Loki", "Failed to send background message to: ${message.recipient}.")
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,10 +103,8 @@ class PushBackgroundMessageSendJob private constructor(
|
|||||||
class Factory : Job.Factory<PushBackgroundMessageSendJob> {
|
class Factory : Job.Factory<PushBackgroundMessageSendJob> {
|
||||||
override fun create(parameters: Parameters, data: Data): PushBackgroundMessageSendJob {
|
override fun create(parameters: Parameters, data: Data): PushBackgroundMessageSendJob {
|
||||||
try {
|
try {
|
||||||
val recipient = data.getString(KEY_RECIPIENT)
|
val messageJSON = data.getString(KEY_MESSAGE)
|
||||||
val messageBody = if (data.hasString(KEY_MESSAGE_BODY)) data.getString(KEY_MESSAGE_BODY) else null
|
return PushBackgroundMessageSendJob(parameters, BackgroundMessage.parse(messageJSON))
|
||||||
val friendRequest = data.getBooleanOrDefault(KEY_FRIEND_REQUEST, false)
|
|
||||||
return PushBackgroundMessageSendJob(parameters, recipient, messageBody, friendRequest)
|
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
throw AssertionError(e)
|
throw AssertionError(e)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package org.thoughtcrime.securesms.sms;
|
package org.thoughtcrime.securesms.sms;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
@ -44,6 +45,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob;
|
|||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
import org.thoughtcrime.securesms.loki.BackgroundMessage;
|
||||||
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
|
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
|
||||||
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
|
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
|
||||||
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
||||||
@ -58,7 +60,11 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||||
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
||||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
|
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
|
||||||
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
|
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
|
||||||
@ -123,11 +129,15 @@ public class MessageSender {
|
|||||||
// We don't call the message sender here directly and instead we just opt to create a specific job for the send
|
// We don't call the message sender here directly and instead we just opt to create a specific job for the send
|
||||||
// This is because calling message sender directly would cause the application to freeze in some cases as it was blocking the thread when waiting for a response from the send
|
// This is because calling message sender directly would cause the application to freeze in some cases as it was blocking the thread when waiting for a response from the send
|
||||||
public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) {
|
public static void sendBackgroundMessage(Context context, String contactHexEncodedPublicKey) {
|
||||||
ApplicationContext.getInstance(context).getJobManager().add(new PushBackgroundMessageSendJob(contactHexEncodedPublicKey));
|
ApplicationContext.getInstance(context).getJobManager().add(new PushBackgroundMessageSendJob(BackgroundMessage.create(contactHexEncodedPublicKey)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendBackgroundFriendRequest(Context context, String contactHexEncodedPublicKey, String messageBody) {
|
public static void sendBackgroundFriendRequest(Context context, String contactHexEncodedPublicKey, String messageBody) {
|
||||||
ApplicationContext.getInstance(context).getJobManager().add(new PushBackgroundMessageSendJob(contactHexEncodedPublicKey, messageBody, true));
|
ApplicationContext.getInstance(context).getJobManager().add(new PushBackgroundMessageSendJob(BackgroundMessage.createFriendRequest(contactHexEncodedPublicKey, messageBody)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendUnpairRequest(Context context, String contactHexEncodedPublicKey) {
|
||||||
|
ApplicationContext.getInstance(context).getJobManager().add(new PushBackgroundMessageSendJob(BackgroundMessage.createUnpairingRequest(contactHexEncodedPublicKey)));
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user