mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-21 10:48:26 +00:00
fix: look at early expiring incoming messages for delete after read
This commit is contained in:
parent
2048e08c86
commit
f0aba3a973
@ -572,7 +572,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
|
|
||||||
private fun setUpOutdatedClientBanner() {
|
private fun setUpOutdatedClientBanner() {
|
||||||
val recipient = viewModel.recipient ?: return
|
val recipient = viewModel.recipient ?: return
|
||||||
if (!ExpirationConfiguration.isNewConfigEnabled && recipient.isContactRecipient &&
|
if (ExpirationConfiguration.isNewConfigEnabled && recipient.isContactRecipient &&
|
||||||
recipient.disappearingState == DisappearingState.LEGACY &&
|
recipient.disappearingState == DisappearingState.LEGACY &&
|
||||||
viewModel.expirationConfiguration?.isEnabled == true
|
viewModel.expirationConfiguration?.isEnabled == true
|
||||||
) {
|
) {
|
||||||
|
@ -84,9 +84,6 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
|||||||
if (expiryType == ExpirationType.DELETE_AFTER_SEND_VALUE && message.getSentTimestamp() != null && senderPublicKey != null) {
|
if (expiryType == ExpirationType.DELETE_AFTER_SEND_VALUE && message.getSentTimestamp() != null && senderPublicKey != null) {
|
||||||
startAnyExpiration(message.getSentTimestamp(), senderPublicKey, expireStartedAt);
|
startAnyExpiration(message.getSentTimestamp(), senderPublicKey, expireStartedAt);
|
||||||
}
|
}
|
||||||
if (message.getId() != null) {
|
|
||||||
DatabaseComponent.get(context).smsDatabase().deleteMessage(message.getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertIncomingExpirationTimerMessage(ExpirationTimerUpdate message, long expireStartedAt) {
|
private void insertIncomingExpirationTimerMessage(ExpirationTimerUpdate message, long expireStartedAt) {
|
||||||
|
@ -18,7 +18,7 @@ import org.session.libsession.messaging.sending_receiving.MessageReceiver
|
|||||||
import org.session.libsession.messaging.sending_receiving.handle
|
import org.session.libsession.messaging.sending_receiving.handle
|
||||||
import org.session.libsession.messaging.sending_receiving.handleOpenGroupReactions
|
import org.session.libsession.messaging.sending_receiving.handleOpenGroupReactions
|
||||||
import org.session.libsession.messaging.sending_receiving.handleVisibleMessage
|
import org.session.libsession.messaging.sending_receiving.handleVisibleMessage
|
||||||
import org.session.libsession.messaging.sending_receiving.updateExpirationConfigurationIfNeeded
|
import org.session.libsession.messaging.sending_receiving.updateExpiryIfNeeded
|
||||||
import org.session.libsession.messaging.utilities.Data
|
import org.session.libsession.messaging.utilities.Data
|
||||||
import org.session.libsession.messaging.utilities.SessionId
|
import org.session.libsession.messaging.utilities.SessionId
|
||||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||||
@ -113,7 +113,7 @@ class BatchMessageReceiveJob(
|
|||||||
messages.forEach { (parameters, message, proto) ->
|
messages.forEach { (parameters, message, proto) ->
|
||||||
try {
|
try {
|
||||||
if (message is VisibleMessage) {
|
if (message is VisibleMessage) {
|
||||||
MessageReceiver.updateExpirationConfigurationIfNeeded(message, proto, openGroupID)
|
MessageReceiver.updateExpiryIfNeeded(message, proto, openGroupID)
|
||||||
val messageId = MessageReceiver.handleVisibleMessage(message, proto, openGroupID,
|
val messageId = MessageReceiver.handleVisibleMessage(message, proto, openGroupID,
|
||||||
runIncrement = false,
|
runIncrement = false,
|
||||||
runThreadUpdate = false,
|
runThreadUpdate = false,
|
||||||
|
@ -13,5 +13,6 @@ class ExpirationConfiguration(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val isNewConfigEnabled = false /* TODO: System.currentTimeMillis() > 1_676_851_200_000 // 13/02/2023 */
|
val isNewConfigEnabled = false /* TODO: System.currentTimeMillis() > 1_676_851_200_000 // 13/02/2023 */
|
||||||
|
const val LAST_READ_TEST = 1673587663000L
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -35,11 +35,12 @@ object MessageReceiver {
|
|||||||
object InvalidGroupPublicKey: Error("Invalid group public key.")
|
object InvalidGroupPublicKey: Error("Invalid group public key.")
|
||||||
object NoGroupKeyPair: Error("Missing group key pair.")
|
object NoGroupKeyPair: Error("Missing group key pair.")
|
||||||
object NoUserED25519KeyPair : Error("Couldn't find user ED25519 key pair.")
|
object NoUserED25519KeyPair : Error("Couldn't find user ED25519 key pair.")
|
||||||
|
object ExpiredMessage: Error("Message has already expired, prevent adding")
|
||||||
|
|
||||||
internal val isRetryable: Boolean = when (this) {
|
internal val isRetryable: Boolean = when (this) {
|
||||||
is DuplicateMessage, is InvalidMessage, is UnknownMessage,
|
is DuplicateMessage, is InvalidMessage, is UnknownMessage,
|
||||||
is UnknownEnvelopeType, is InvalidSignature, is NoData,
|
is UnknownEnvelopeType, is InvalidSignature, is NoData,
|
||||||
is SenderBlocked, is SelfSend -> false
|
is SenderBlocked, is SelfSend, is ExpiredMessage -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,7 +50,7 @@ object MessageReceiver {
|
|||||||
openGroupServerID: Long?,
|
openGroupServerID: Long?,
|
||||||
isOutgoing: Boolean? = null,
|
isOutgoing: Boolean? = null,
|
||||||
otherBlindedPublicKey: String? = null,
|
otherBlindedPublicKey: String? = null,
|
||||||
openGroupPublicKey: String? = null,
|
openGroupPublicKey: String? = null
|
||||||
): Pair<Message, SignalServiceProtos.Content> {
|
): Pair<Message, SignalServiceProtos.Content> {
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
val userPublicKey = storage.getUserPublicKey()
|
val userPublicKey = storage.getUserPublicKey()
|
||||||
@ -179,4 +180,5 @@ object MessageReceiver {
|
|||||||
// Return
|
// Return
|
||||||
return Pair(message, proto)
|
return Pair(message, proto)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -39,7 +39,6 @@ import org.session.libsession.utilities.ProfileKeyUtil
|
|||||||
import org.session.libsession.utilities.SSKEnvironment
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.recipients.Recipient.DisappearingState
|
|
||||||
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
|
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
|
||||||
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
||||||
import org.session.libsignal.crypto.ecc.ECKeyPair
|
import org.session.libsignal.crypto.ecc.ECKeyPair
|
||||||
@ -63,7 +62,7 @@ internal fun MessageReceiver.isBlocked(publicKey: String): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) {
|
fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) {
|
||||||
updateExpirationConfigurationIfNeeded(message, proto, openGroupID)
|
MessageReceiver.updateExpiryIfNeeded(message, proto, openGroupID)
|
||||||
when (message) {
|
when (message) {
|
||||||
is ReadReceipt -> handleReadReceipt(message)
|
is ReadReceipt -> handleReadReceipt(message)
|
||||||
is TypingIndicator -> handleTypingIndicator(message)
|
is TypingIndicator -> handleTypingIndicator(message)
|
||||||
@ -82,29 +81,6 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MessageReceiver.updateExpirationConfigurationIfNeeded(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) {
|
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
|
||||||
val disappearingState = if (proto.hasExpirationTimer()) DisappearingState.UPDATED else DisappearingState.LEGACY
|
|
||||||
if (!proto.hasLastDisappearingMessageChangeTimestamp() || !ExpirationConfiguration.isNewConfigEnabled) return
|
|
||||||
val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID)
|
|
||||||
if (threadID <= 0) return
|
|
||||||
storage.updateDisappearingState(threadID, disappearingState)
|
|
||||||
val localConfig = storage.getExpirationConfiguration(threadID)
|
|
||||||
if (localConfig != null && localConfig.updatedTimestampMs > proto.lastDisappearingMessageChangeTimestamp) return
|
|
||||||
val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0
|
|
||||||
val type = if (proto.hasExpirationType()) proto.expirationType else null
|
|
||||||
val remoteConfig = ExpirationConfiguration(
|
|
||||||
threadID,
|
|
||||||
durationSeconds,
|
|
||||||
type?.number ?: -1,
|
|
||||||
proto.lastDisappearingMessageChangeTimestamp
|
|
||||||
)
|
|
||||||
storage.setExpirationConfiguration(remoteConfig)
|
|
||||||
if (message is ExpirationTimerUpdate) {
|
|
||||||
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type?.number ?: -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// region Control Messages
|
// region Control Messages
|
||||||
private fun MessageReceiver.handleReadReceipt(message: ReadReceipt) {
|
private fun MessageReceiver.handleReadReceipt(message: ReadReceipt) {
|
||||||
val context = MessagingModuleConfiguration.shared.context
|
val context = MessagingModuleConfiguration.shared.context
|
||||||
@ -256,6 +232,63 @@ fun handleMessageRequestResponse(message: MessageRequestResponse) {
|
|||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
fun MessageReceiver.updateExpiryIfNeeded(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) {
|
||||||
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
|
val sentTime = message.sentTimestamp ?: throw MessageReceiver.Error.InvalidMessage
|
||||||
|
if (!proto.hasLastDisappearingMessageChangeTimestamp()) return
|
||||||
|
val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID)
|
||||||
|
if (threadID <= 0) throw MessageReceiver.Error.NoThread
|
||||||
|
|
||||||
|
val localConfig = storage.getExpirationConfiguration(threadID)
|
||||||
|
|
||||||
|
val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0
|
||||||
|
val type = if (proto.hasExpirationType()) proto.expirationType else null
|
||||||
|
val remoteConfig = ExpirationConfiguration(
|
||||||
|
threadID,
|
||||||
|
durationSeconds,
|
||||||
|
type?.number ?: -1,
|
||||||
|
proto.lastDisappearingMessageChangeTimestamp
|
||||||
|
)
|
||||||
|
|
||||||
|
val (shouldUpdateConfig, configToUse) =
|
||||||
|
if (localConfig != null && localConfig.updatedTimestampMs > proto.lastDisappearingMessageChangeTimestamp) {
|
||||||
|
false to localConfig
|
||||||
|
} else {
|
||||||
|
true to remoteConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
val recipient = storage.getRecipientForThread(threadID) ?: throw MessageReceiver.Error.NoThread
|
||||||
|
|
||||||
|
// don't update any values for open groups
|
||||||
|
if (recipient.isOpenGroupRecipient && type != null) throw MessageReceiver.Error.InvalidMessage
|
||||||
|
if ((recipient.isGroupRecipient || recipient.isLocalNumber)
|
||||||
|
&& type == ExpirationType.DELETE_AFTER_READ) {
|
||||||
|
// don't allow deleteAfterRead if we are sending to note to self or a group, treat the entire message as invalid
|
||||||
|
throw MessageReceiver.Error.InvalidMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle a delete after send expired fetch
|
||||||
|
if (type == ExpirationType.DELETE_AFTER_SEND
|
||||||
|
&& sentTime + configToUse.durationSeconds <= SnodeAPI.nowWithClockOffset) {
|
||||||
|
throw MessageReceiver.Error.ExpiredMessage
|
||||||
|
}
|
||||||
|
// handle a delete after read last known config value (test) TODO: actually implement this with shared config library
|
||||||
|
if (type == ExpirationType.DELETE_AFTER_READ
|
||||||
|
&& sentTime + configToUse.durationSeconds <= ExpirationConfiguration.LAST_READ_TEST) {
|
||||||
|
throw MessageReceiver.Error.ExpiredMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldUpdateConfig) {
|
||||||
|
val disappearingState = if (proto.hasExpirationType()) Recipient.DisappearingState.UPDATED else Recipient.DisappearingState.LEGACY
|
||||||
|
storage.updateDisappearingState(threadID, disappearingState)
|
||||||
|
storage.setExpirationConfiguration(configToUse)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message is ExpirationTimerUpdate) {
|
||||||
|
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type?.number ?: -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun MessageReceiver.handleVisibleMessage(message: VisibleMessage,
|
fun MessageReceiver.handleVisibleMessage(message: VisibleMessage,
|
||||||
proto: SignalServiceProtos.Content,
|
proto: SignalServiceProtos.Content,
|
||||||
openGroupID: String?,
|
openGroupID: String?,
|
||||||
|
@ -25,7 +25,6 @@ import org.session.libsignal.utilities.Snode
|
|||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
import org.session.libsignal.utilities.recover
|
import org.session.libsignal.utilities.recover
|
||||||
import org.session.libsignal.utilities.toHexString
|
import org.session.libsignal.utilities.toHexString
|
||||||
import java.util.Date
|
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
|
||||||
private typealias Path = List<Snode>
|
private typealias Path = List<Snode>
|
||||||
@ -594,7 +593,7 @@ object OnionRequestAPI {
|
|||||||
}
|
}
|
||||||
if (body["t"] != null) {
|
if (body["t"] != null) {
|
||||||
val timestamp = body["t"] as Long
|
val timestamp = body["t"] as Long
|
||||||
val offset = timestamp - Date().time
|
val offset = timestamp - System.currentTimeMillis()
|
||||||
SnodeAPI.clockOffset = offset
|
SnodeAPI.clockOffset = offset
|
||||||
}
|
}
|
||||||
if (body.containsKey("hf")) {
|
if (body.containsKey("hf")) {
|
||||||
|
@ -56,6 +56,10 @@ object SnodeAPI {
|
|||||||
* user's clock is incorrect.
|
* user's clock is incorrect.
|
||||||
*/
|
*/
|
||||||
var clockOffset = 0L
|
var clockOffset = 0L
|
||||||
|
|
||||||
|
val nowWithClockOffset
|
||||||
|
get() = System.currentTimeMillis() + clockOffset
|
||||||
|
|
||||||
internal var forkInfo by observable(database.getForkInfo()) { _, oldValue, newValue ->
|
internal var forkInfo by observable(database.getForkInfo()) { _, oldValue, newValue ->
|
||||||
if (newValue > oldValue) {
|
if (newValue > oldValue) {
|
||||||
Log.d("Loki", "Setting new fork info new: $newValue, old: $oldValue")
|
Log.d("Loki", "Setting new fork info new: $newValue, old: $oldValue")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user