mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 20:15:21 +00:00
Handle unpair request flag.
This commit is contained in:
parent
c66786e0f1
commit
3a79e1f215
@ -331,27 +331,38 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
SignalServiceDataMessage message = content.getDataMessage().get();
|
||||
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent();
|
||||
|
||||
if (message.isEndSession()) handleEndSessionMessage(content, smsMessageId);
|
||||
else if (message.isGroupUpdate()) handleGroupMessage(content, message, smsMessageId);
|
||||
else if (message.isExpirationUpdate()) handleExpirationUpdate(content, message, smsMessageId);
|
||||
else if (isMediaMessage) handleMediaMessage(content, message, smsMessageId, Optional.absent());
|
||||
else if (message.getBody().isPresent()) handleTextMessage(content, message, smsMessageId, Optional.absent());
|
||||
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);
|
||||
else if (message.isGroupUpdate()) handleGroupMessage(content, message, smsMessageId);
|
||||
else if (message.isExpirationUpdate())
|
||||
handleExpirationUpdate(content, message, smsMessageId);
|
||||
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))) {
|
||||
handleUnknownGroupMessage(content, message.getGroupInfo().get());
|
||||
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))) {
|
||||
handleUnknownGroupMessage(content, message.getGroupInfo().get());
|
||||
}
|
||||
|
||||
if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) {
|
||||
handleProfileKey(content, message);
|
||||
}
|
||||
|
||||
// Loki - This doesn't get invoked for group chats
|
||||
if (content.isNeedsReceipt()) {
|
||||
handleNeedsDeliveryReceipt(content, message);
|
||||
}
|
||||
|
||||
// Loki - Handle friend request logic if needed
|
||||
updateFriendRequestStatusIfNeeded(envelope, content, message);
|
||||
}
|
||||
|
||||
if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) {
|
||||
handleProfileKey(content, message);
|
||||
}
|
||||
|
||||
// Loki - This doesn't get invoked for group chats
|
||||
if (content.isNeedsReceipt()) {
|
||||
handleNeedsDeliveryReceipt(content, message);
|
||||
}
|
||||
|
||||
// Loki - Handle friend request logic if needed
|
||||
updateFriendRequestStatusIfNeeded(envelope, content, message);
|
||||
} else if (content.getSyncMessage().isPresent()) {
|
||||
TextSecurePreferences.setMultiDevice(context, true);
|
||||
|
||||
|
@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.*
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage
|
||||
import network.loki.messenger.R
|
||||
import nl.komponents.kovenant.then
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
@ -44,9 +45,10 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity(), DeviceLinki
|
||||
val database = DatabaseFactory.getLokiAPIDatabase(this)
|
||||
database.removePairingAuthorisation(ourPublicKey, devicePublicKey)
|
||||
// Update mapping on the file server
|
||||
LokiStorageAPI.shared.updateUserDeviceMappings()
|
||||
// Send a background message to let the device know that it has been revoked
|
||||
MessageSender.sendBackgroundMessage(this, devicePublicKey)
|
||||
LokiStorageAPI.shared.updateUserDeviceMappings().success {
|
||||
// Send an unpair request to let the device know that it has been revoked
|
||||
MessageSender.sendUnpairRequest(this, devicePublicKey)
|
||||
}
|
||||
// Refresh the list
|
||||
this.deviceListFragment.refresh()
|
||||
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.functional.bind
|
||||
import nl.komponents.kovenant.functional.map
|
||||
import nl.komponents.kovenant.then
|
||||
import nl.komponents.kovenant.toFailVoid
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
@ -27,6 +28,23 @@ import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||
import java.util.*
|
||||
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> {
|
||||
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
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.messages.SignalServiceDataMessage
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||
import java.io.IOException
|
||||
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(
|
||||
parameters: Parameters,
|
||||
private val recipient: String,
|
||||
private val messageBody: String?,
|
||||
private val friendRequest: Boolean
|
||||
private val message: BackgroundMessage
|
||||
) : BaseJob(parameters) {
|
||||
companion object {
|
||||
const val KEY = "PushBackgroundMessageSendJob"
|
||||
|
||||
private val TAG = PushBackgroundMessageSendJob::class.java.simpleName
|
||||
|
||||
private val KEY_RECIPIENT = "recipient"
|
||||
private val KEY_MESSAGE_BODY = "message_body"
|
||||
private val KEY_FRIEND_REQUEST = "asFriendRequest"
|
||||
private val KEY_MESSAGE = "message"
|
||||
}
|
||||
|
||||
constructor(recipient: String): this(recipient, null, false)
|
||||
constructor(recipient: String, messageBody: String?, friendRequest: Boolean) : this(Parameters.Builder()
|
||||
constructor(message: BackgroundMessage) : this(Parameters.Builder()
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setQueue(KEY)
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(1)
|
||||
.build(),
|
||||
recipient, messageBody, friendRequest)
|
||||
message)
|
||||
|
||||
override fun serialize(): Data {
|
||||
return Data.Builder()
|
||||
.putString(KEY_RECIPIENT, recipient)
|
||||
.putString(KEY_MESSAGE_BODY, messageBody)
|
||||
.putBoolean(KEY_FRIEND_REQUEST, friendRequest)
|
||||
.putString(KEY_MESSAGE, message.serialize())
|
||||
.build()
|
||||
}
|
||||
|
||||
@ -52,22 +71,24 @@ class PushBackgroundMessageSendJob private constructor(
|
||||
}
|
||||
|
||||
public override fun onRun() {
|
||||
val message = SignalServiceDataMessage.newBuilder()
|
||||
val dataMessage = SignalServiceDataMessage.newBuilder()
|
||||
.withTimestamp(System.currentTimeMillis())
|
||||
.withBody(messageBody)
|
||||
.withBody(message.body)
|
||||
|
||||
if (friendRequest) {
|
||||
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(recipient)
|
||||
message.withPreKeyBundle(bundle)
|
||||
if (message.friendRequest) {
|
||||
val bundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(message.recipient)
|
||||
dataMessage.withPreKeyBundle(bundle)
|
||||
.asFriendRequest(true)
|
||||
} else if (message.unpairingRequest) {
|
||||
dataMessage.asUnpairingRequest(true)
|
||||
}
|
||||
|
||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||
val address = SignalServiceAddress(recipient)
|
||||
val address = SignalServiceAddress(message.recipient)
|
||||
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) {
|
||||
Log.d("Loki", "Failed to send background message to: $recipient.")
|
||||
Log.d("Loki", "Failed to send background message to: ${message.recipient}.")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
@ -82,10 +103,8 @@ class PushBackgroundMessageSendJob private constructor(
|
||||
class Factory : Job.Factory<PushBackgroundMessageSendJob> {
|
||||
override fun create(parameters: Parameters, data: Data): PushBackgroundMessageSendJob {
|
||||
try {
|
||||
val recipient = data.getString(KEY_RECIPIENT)
|
||||
val messageBody = if (data.hasString(KEY_MESSAGE_BODY)) data.getString(KEY_MESSAGE_BODY) else null
|
||||
val friendRequest = data.getBooleanOrDefault(KEY_FRIEND_REQUEST, false)
|
||||
return PushBackgroundMessageSendJob(parameters, recipient, messageBody, friendRequest)
|
||||
val messageJSON = data.getString(KEY_MESSAGE)
|
||||
return PushBackgroundMessageSendJob(parameters, BackgroundMessage.parse(messageJSON))
|
||||
} catch (e: IOException) {
|
||||
throw AssertionError(e)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
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.LinkPreviewUtil;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.BackgroundMessage;
|
||||
import org.thoughtcrime.securesms.loki.FriendRequestHandler;
|
||||
import org.thoughtcrime.securesms.loki.GeneralUtilitiesKt;
|
||||
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
|
||||
@ -58,7 +60,11 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
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.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.loki.api.LokiStorageAPI;
|
||||
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
|
||||
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
|
||||
// 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) {
|
||||
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) {
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user