-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Expand file tree
/
Copy pathMessageConstraintsUtil.kt
More file actions
130 lines (109 loc) · 5.36 KB
/
MessageConstraintsUtil.kt
File metadata and controls
130 lines (109 loc) · 5.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package org.thoughtcrime.securesms.util
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.model.GroupRecord
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
/**
* Helpers for determining if a message send/receive is valid for those that
* have strict time limits.
*/
object MessageConstraintsUtil {
private val SEND_THRESHOLD = RemoteConfig.regularDeleteThreshold.seconds.inWholeMilliseconds
private val RECEIVE_THRESHOLD = SEND_THRESHOLD + 1.days.inWholeMilliseconds
private val ADMIN_SEND_THRESHOLD = RemoteConfig.adminDeleteThreshold.seconds.inWholeMilliseconds
private val ADMIN_RECEIVE_THRESHOLD = ADMIN_SEND_THRESHOLD + 1.days.inWholeMilliseconds
const val MAX_EDIT_COUNT = 10
@JvmStatic
fun isValidRemoteDeleteReceive(targetMessage: MessageRecord, deleteSenderId: RecipientId, deleteServerTimestamp: Long): Boolean {
val selfIsDeleteSender = isSelf(deleteSenderId)
val isValidIncomingOutgoing = selfIsDeleteSender && targetMessage.isOutgoing || !selfIsDeleteSender && !targetMessage.isOutgoing
val isValidSender = targetMessage.fromRecipient.id == deleteSenderId || selfIsDeleteSender && targetMessage.isOutgoing
val messageTimestamp = if (selfIsDeleteSender && targetMessage.isOutgoing) targetMessage.dateSent else targetMessage.serverTimestamp
return isValidIncomingOutgoing &&
isValidSender &&
((deleteServerTimestamp - messageTimestamp < RECEIVE_THRESHOLD) || (selfIsDeleteSender && targetMessage.isOutgoing))
}
@JvmStatic
fun isValidAdminDeleteReceive(targetMessage: MessageRecord, deleteSender: Recipient, deleteServerTimestamp: Long, groupRecord: GroupRecord): Boolean {
val isValidSender = groupRecord.isAdmin(deleteSender)
val messageTimestamp = targetMessage.dateSent
return isValidSender && (deleteServerTimestamp - messageTimestamp < ADMIN_RECEIVE_THRESHOLD)
}
@JvmStatic
fun isValidEditMessageReceive(targetMessage: MessageRecord, editSender: Recipient, editServerTimestamp: Long): Boolean {
return isValidRemoteDeleteReceive(targetMessage, editSender.id, editServerTimestamp)
}
@JvmStatic
fun isValidRemoteDeleteSend(targetMessages: Collection<MessageRecord>, currentTime: Long): Boolean {
// TODO [greyson] [remote-delete] Update with server timestamp when available for outgoing messages
return targetMessages.all { isValidRemoteDeleteSend(it, currentTime) }
}
@JvmStatic
fun isValidAdminDeleteSend(targetMessages: Collection<MessageRecord>, currentTime: Long, isAdmin: Boolean): Boolean {
return targetMessages.all { isValidAdminDeleteSend(message = it, currentTime = currentTime, isAdmin = isAdmin, isResend = false) }
}
@JvmStatic
fun isWithinMaxEdits(targetMessage: MessageRecord): Boolean {
return targetMessage.revisionNumber < MAX_EDIT_COUNT
}
@JvmStatic
fun getEditMessageThresholdHours(): Int {
return SEND_THRESHOLD.milliseconds.inWholeHours.toInt()
}
/**
* Check if at the current time a target message can be edited
*/
@JvmStatic
fun isValidEditMessageSend(targetMessage: MessageRecord, currentTime: Long): Boolean {
val originalMessage = if (targetMessage.isEditMessage && targetMessage.id != targetMessage.originalMessageId?.id) {
SignalDatabase.messages.getMessageRecord(targetMessage.originalMessageId!!.id)
} else {
targetMessage
}
val isNoteToSelf = targetMessage.toRecipient.isSelf && targetMessage.fromRecipient.isSelf
return isValidRemoteDeleteSend(originalMessage, currentTime) &&
(isNoteToSelf || targetMessage.revisionNumber < MAX_EDIT_COUNT) &&
!targetMessage.isViewOnceMessage() &&
!targetMessage.hasAudio() &&
!targetMessage.hasSharedContact() &&
!targetMessage.hasSticker() &&
!targetMessage.hasPoll()
}
/**
* Check regardless of timing, whether a target message can be edited
*/
@JvmStatic
fun isValidEditMessageSend(targetMessage: MessageRecord): Boolean {
return isValidEditMessageSend(targetMessage, targetMessage.dateSent)
}
fun isValidRemoteDeleteSend(message: MessageRecord, currentTime: Long): Boolean {
return !message.isUpdate &&
message.isOutgoing &&
message.isPush &&
(!message.toRecipient.isGroup || message.toRecipient.isActiveGroup) &&
!message.isRemoteDelete &&
!message.hasGiftBadge() &&
!message.isPaymentNotification &&
!message.isPaymentTombstone &&
(currentTime - message.dateSent < SEND_THRESHOLD || message.toRecipient.isSelf)
}
fun isValidAdminDeleteSend(message: MessageRecord, currentTime: Long, isAdmin: Boolean, isResend: Boolean): Boolean {
return RemoteConfig.sendAdminDelete &&
isAdmin &&
!message.isUpdate &&
message.isPush &&
(!message.toRecipient.isGroup || message.toRecipient.isActiveGroup) &&
(!message.isRemoteDelete || isResend) &&
!message.hasGiftBadge() &&
!message.isPaymentNotification &&
!message.isPaymentTombstone &&
(currentTime - message.dateSent < ADMIN_SEND_THRESHOLD)
}
private fun isSelf(recipientId: RecipientId): Boolean {
return Recipient.isSelfSet && Recipient.self().id == recipientId
}
}