mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-22 17:01:46 +00:00
Fix auto accept friend request logic.
This commit is contained in:
parent
be55e1bb55
commit
be9afa243c
@ -5,8 +5,6 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
@ -61,6 +59,7 @@ import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
|
|||||||
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
|
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
|
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
|
||||||
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.loki.UtilitiesKt;
|
||||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
|
||||||
@ -131,6 +130,7 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
import nl.komponents.kovenant.Promise;
|
||||||
|
|
||||||
public class PushDecryptJob extends BaseJob implements InjectableType {
|
public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||||
|
|
||||||
@ -1083,6 +1083,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
// Send out accept event
|
// Send out accept event
|
||||||
LokiDeviceLinkingSession.Companion.getShared().acceptedLinkingRequest(authorisation);
|
LokiDeviceLinkingSession.Companion.getShared().acceptedLinkingRequest(authorisation);
|
||||||
|
|
||||||
|
// Send a background message to the primary device
|
||||||
|
sendBackgroundMessage(authorisation.getPrimaryDevicePubKey());
|
||||||
|
|
||||||
// Propagate the updates to the file server
|
// Propagate the updates to the file server
|
||||||
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
|
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
|
||||||
if (storageAPI != null) { storageAPI.updateOurDeviceMappings(); }
|
if (storageAPI != null) { storageAPI.updateOurDeviceMappings(); }
|
||||||
@ -1107,36 +1110,13 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void acceptFriendRequestIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
|
private void acceptFriendRequestIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
|
||||||
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context);
|
if (envelope.isFriendRequest()) { return; }
|
||||||
if (envelope.isFriendRequest()) {
|
|
||||||
LokiStorageAPI storageAPI = LokiStorageAPI.Companion.getShared();
|
|
||||||
if (storageAPI == null) { return; }
|
|
||||||
// If we get a friend request then we need to check if the sender is a secondary device.
|
|
||||||
// If it is then we need to check if we have its primary device as our friend
|
|
||||||
// If so then we add them automatically as a friend
|
|
||||||
storageAPI.getPrimaryDevice(content.getSender()).success(primaryDevicePubKey -> {
|
|
||||||
// Make sure we have a primary device
|
|
||||||
if (primaryDevicePubKey == null) { return Unit.INSTANCE; }
|
|
||||||
|
|
||||||
// If we have a thread then the id will be >= 0
|
// If we get anything other than a friend request, we can assume that we have a session with the other user
|
||||||
Recipient primaryDevice = Recipient.from(context, Address.fromSerialized(primaryDevicePubKey), false);
|
becomeFriendsWithContact(content.getSender());
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(primaryDevice);
|
|
||||||
if (threadID < 0) { return Unit.INSTANCE; }
|
|
||||||
|
|
||||||
// Check that we're friends with the primary device, if we are then auto accept
|
|
||||||
if (lokiThreadDatabase.getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS) {
|
|
||||||
becomeFriendsWithContact(content.getSender(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Unit.INSTANCE;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// If we get anything other than a friend request, we can assume that we have a session with the other user
|
|
||||||
becomeFriendsWithContact(content.getSender(), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void becomeFriendsWithContact(String pubKey, boolean updateLastMessage) {
|
private void becomeFriendsWithContact(String pubKey) {
|
||||||
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context);
|
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context);
|
||||||
Recipient contactID = Recipient.from(context, Address.fromSerialized(pubKey), false);
|
Recipient contactID = Recipient.from(context, Address.fromSerialized(pubKey), false);
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(contactID);
|
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(contactID);
|
||||||
@ -1148,59 +1128,72 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
|||||||
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
||||||
|
|
||||||
// Update the last message if needed
|
// Update the last message if needed
|
||||||
if (updateLastMessage) {
|
SmsDatabase messageDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||||
SmsDatabase messageDatabase = DatabaseFactory.getSmsDatabase(context);
|
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
|
||||||
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
|
int messageCount = messageDatabase.getMessageCountForThread(threadID);
|
||||||
int messageCount = messageDatabase.getMessageCountForThread(threadID);
|
|
||||||
|
|
||||||
long messageID = messageDatabase.getIDForMessageAtIndex(threadID, messageCount - 1);
|
long messageID = messageDatabase.getIDForMessageAtIndex(threadID, messageCount - 1);
|
||||||
|
if (messageID > -1 && lokiMessageDatabase.getFriendRequestStatus(messageID) != LokiMessageFriendRequestStatus.REQUEST_ACCEPTED) {
|
||||||
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
|
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFriendRequestStatusIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
|
private void updateFriendRequestStatusIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
|
||||||
if (!envelope.isFriendRequest()) { return; }
|
if (!envelope.isFriendRequest()) { return; }
|
||||||
Recipient contactID = getMessageDestination(content, message);
|
|
||||||
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context);
|
// This handles the case where another user sends us a regular message without the authorisation
|
||||||
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(contactID);
|
UtilitiesKt.shouldAutomaticallyBecomeFriendsWithDevice(content.getSender(), context).success(becomeFriends -> {
|
||||||
LokiThreadFriendRequestStatus threadFriendRequestStatus = lokiThreadDatabase.getFriendRequestStatus(threadID);
|
if (becomeFriends) {
|
||||||
SmsDatabase smsMessageDatabase = DatabaseFactory.getSmsDatabase(context);
|
// Become friends AND update the message they sent
|
||||||
MmsDatabase mmsMessageDatabase = DatabaseFactory.getMmsDatabase(context);
|
becomeFriendsWithContact(content.getSender());
|
||||||
LokiMessageDatabase lokiMessageDatabase= DatabaseFactory.getLokiMessageDatabase(context);
|
|
||||||
int messageCount = smsMessageDatabase.getMessageCountForThread(threadID);
|
// Send them an accept message back
|
||||||
if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
sendBackgroundMessage(content.getSender());
|
||||||
// This can happen if Alice sent Bob a friend request, Bob declined, but then Bob changed his
|
|
||||||
// mind and sent a friend request to Alice. In this case we want Alice to auto-accept the request
|
|
||||||
// and send a friend request accepted message back to Bob. We don't check that sending the
|
|
||||||
// friend request accepted message succeeded. Even if it doesn't, the thread's current friend
|
|
||||||
// request status will be set to `FRIENDS` for Alice making it possible
|
|
||||||
// for Alice to send messages to Bob. When Bob receives a message, his thread's friend request status
|
|
||||||
// will then be set to `FRIENDS`. If we do check for a successful send
|
|
||||||
// before updating Alice's thread's friend request status to `FRIENDS`,
|
|
||||||
// we can end up in a deadlock where both users' threads' friend request statuses are
|
|
||||||
// `REQUEST_SENT`.
|
|
||||||
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
|
||||||
long messageID = smsMessageDatabase.getIDForMessageAtIndex(threadID, messageCount - 2); // The message before the one that was just received
|
|
||||||
// TODO: MMS
|
|
||||||
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
|
|
||||||
// Accept the friend request
|
|
||||||
sendBackgroundMessage(content.getSender());
|
|
||||||
} else if (threadFriendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
|
|
||||||
// Checking that the sender of the message isn't already a friend is necessary because otherwise
|
|
||||||
// the following situation can occur: Alice and Bob are friends. Bob loses his database and his
|
|
||||||
// friend request status is reset to `NONE`. Bob now sends Alice a friend
|
|
||||||
// request. Alice's thread's friend request status is reset to
|
|
||||||
// `REQUEST_RECEIVED`.
|
|
||||||
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
|
|
||||||
long messageID = smsMessageDatabase.getIDForMessageAtIndex(threadID, messageCount - 1); // The message that was just received
|
|
||||||
if (messageID != -1) {
|
|
||||||
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_PENDING);
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: The code below is ugly due to Java limitations
|
// Do regular friend request logic checks
|
||||||
lokiMessageDatabase.setFriendRequestStatus(mmsMessageDatabase.getIDForMessageAtIndex(threadID, 0), LokiMessageFriendRequestStatus.REQUEST_PENDING);
|
Recipient contactID = getMessageDestination(content, message);
|
||||||
|
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context);
|
||||||
|
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(contactID);
|
||||||
|
LokiThreadFriendRequestStatus threadFriendRequestStatus = lokiThreadDatabase.getFriendRequestStatus(threadID);
|
||||||
|
SmsDatabase smsMessageDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||||
|
MmsDatabase mmsMessageDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||||
|
LokiMessageDatabase lokiMessageDatabase= DatabaseFactory.getLokiMessageDatabase(context);
|
||||||
|
int messageCount = smsMessageDatabase.getMessageCountForThread(threadID);
|
||||||
|
if (threadFriendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
|
||||||
|
// This can happen if Alice sent Bob a friend request, Bob declined, but then Bob changed his
|
||||||
|
// mind and sent a friend request to Alice. In this case we want Alice to auto-accept the request
|
||||||
|
// and send a friend request accepted message back to Bob. We don't check that sending the
|
||||||
|
// friend request accepted message succeeded. Even if it doesn't, the thread's current friend
|
||||||
|
// request status will be set to `FRIENDS` for Alice making it possible
|
||||||
|
// for Alice to send messages to Bob. When Bob receives a message, his thread's friend request status
|
||||||
|
// will then be set to `FRIENDS`. If we do check for a successful send
|
||||||
|
// before updating Alice's thread's friend request status to `FRIENDS`,
|
||||||
|
// we can end up in a deadlock where both users' threads' friend request statuses are
|
||||||
|
// `REQUEST_SENT`.
|
||||||
|
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
|
||||||
|
long messageID = smsMessageDatabase.getIDForMessageAtIndex(threadID, messageCount - 2); // The message before the one that was just received
|
||||||
|
// TODO: MMS
|
||||||
|
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
|
||||||
|
// Accept the friend request
|
||||||
|
sendBackgroundMessage(content.getSender());
|
||||||
|
} else if (threadFriendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
|
||||||
|
// Checking that the sender of the message isn't already a friend is necessary because otherwise
|
||||||
|
// the following situation can occur: Alice and Bob are friends. Bob loses his database and his
|
||||||
|
// friend request status is reset to `NONE`. Bob now sends Alice a friend
|
||||||
|
// request. Alice's thread's friend request status is reset to
|
||||||
|
// `REQUEST_RECEIVED`.
|
||||||
|
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
|
||||||
|
long messageID = smsMessageDatabase.getIDForMessageAtIndex(threadID, messageCount - 1); // The message that was just received
|
||||||
|
if (messageID != -1) {
|
||||||
|
lokiMessageDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_PENDING);
|
||||||
|
} else {
|
||||||
|
// TODO: The code below is ugly due to Java limitations
|
||||||
|
lokiMessageDatabase.setFriendRequestStatus(mmsMessageDatabase.getIDForMessageAtIndex(threadID, 0), LokiMessageFriendRequestStatus.REQUEST_PENDING);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return Unit.INSTANCE;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendBackgroundMessage(String contactHexEncodedPublicKey) {
|
private void sendBackgroundMessage(String contactHexEncodedPublicKey) {
|
||||||
|
@ -6,13 +6,65 @@ import android.os.Looper
|
|||||||
import nl.komponents.kovenant.Promise
|
import nl.komponents.kovenant.Promise
|
||||||
import nl.komponents.kovenant.deferred
|
import nl.komponents.kovenant.deferred
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
|
import org.thoughtcrime.securesms.database.Address
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.logging.Log
|
import org.thoughtcrime.securesms.logging.Log
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
import org.whispersystems.libsignal.util.guava.Optional
|
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.SignalServiceContent
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||||
import org.whispersystems.signalservice.loki.api.LokiPairingAuthorisation
|
import org.whispersystems.signalservice.loki.api.LokiPairingAuthorisation
|
||||||
|
import org.whispersystems.signalservice.loki.api.LokiStorageAPI
|
||||||
|
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
|
||||||
|
|
||||||
|
fun shouldAutomaticallyBecomeFriendsWithDevice(pubKey: String, context: Context): Promise<Boolean, Unit> {
|
||||||
|
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||||
|
val storageAPI = LokiStorageAPI.shared ?: return Promise.ofSuccess(false)
|
||||||
|
// we need to check if the sender is a secondary device.
|
||||||
|
// If it is then we need to check if we have its primary device as our friend
|
||||||
|
// If so then we add them automatically as a friend
|
||||||
|
|
||||||
|
val deferred = deferred<Boolean, Unit>()
|
||||||
|
storageAPI.getPrimaryDevice(pubKey).success { primaryDevicePubKey ->
|
||||||
|
// Make sure we have a primary device
|
||||||
|
if (primaryDevicePubKey == null) {
|
||||||
|
deferred.resolve(false)
|
||||||
|
return@success
|
||||||
|
}
|
||||||
|
|
||||||
|
val ourPubKey = TextSecurePreferences.getLocalNumber(context)
|
||||||
|
|
||||||
|
if (primaryDevicePubKey == ourPubKey) {
|
||||||
|
// If the friend request is from our secondary device then we need to confirm and check that we have it registered.
|
||||||
|
// If we do then add it
|
||||||
|
storageAPI.getSecondaryDevices(ourPubKey).success { secondaryDevices ->
|
||||||
|
// We should become friends if the pubKey is in our secondary device list
|
||||||
|
deferred.resolve(secondaryDevices.contains(pubKey))
|
||||||
|
}.fail {
|
||||||
|
deferred.resolve(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return@success
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a thread then the id will be >= 0
|
||||||
|
val primaryDevice = Recipient.from(context, Address.fromSerialized(primaryDevicePubKey), false)
|
||||||
|
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(primaryDevice)
|
||||||
|
if (threadID < 0) {
|
||||||
|
deferred.resolve(false)
|
||||||
|
return@success
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should become friends if the primary device is our friend
|
||||||
|
deferred.resolve(lokiThreadDatabase.getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS)
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise
|
||||||
|
}
|
||||||
|
|
||||||
fun sendAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: LokiPairingAuthorisation): Promise<Unit, Exception> {
|
fun sendAuthorisationMessage(context: Context, contactHexEncodedPublicKey: String, authorisation: LokiPairingAuthorisation): Promise<Unit, Exception> {
|
||||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user