Auto-leave group if added by blocked user.

fork-5.53.8
Cody Henthorne 2022-04-20 09:48:44 -04:00 zatwierdzone przez Alex Hart
rodzic 820c016aad
commit 55acd0f048
6 zmienionych plików z 168 dodań i 7 usunięć

Wyświetl plik

@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.groups.GroupsV2Authorization;
import org.thoughtcrime.securesms.groups.v2.ProfileKeySet;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobs.AvatarGroupsV2DownloadJob;
import org.thoughtcrime.securesms.jobs.LeaveGroupV2Job;
import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob;
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
@ -111,11 +112,6 @@ public class GroupsV2StateProcessor {
}
public enum GroupState {
/**
* The message revision was inconsistent with server revision, should ignore
*/
INCONSISTENT,
/**
* The local group was successfully updated to be consistent with the message revision
*/
@ -590,7 +586,12 @@ public class GroupsV2StateProcessor {
Log.i(TAG, String.format("Added as a full member of %s by %s", groupId, addedBy.getId()));
if (addedBy.isSystemContact() || addedBy.isProfileSharing()) {
if (addedBy.isBlocked()) {
Log.i(TAG, "Added by a blocked user. Leaving group.");
ApplicationDependencies.getJobManager().add(new LeaveGroupV2Job(groupId));
//noinspection UnnecessaryReturnStatement
return;
} else if (addedBy.isSystemContact() || addedBy.isProfileSharing()) {
Log.i(TAG, "Group 'adder' is trusted. contact: " + addedBy.isSystemContact() + ", profileSharing: " + addedBy.isProfileSharing());
Log.i(TAG, "Added to a group and auto-enabling profile sharing");
recipientDatabase.setProfileSharing(Recipient.externalGroupExact(context, groupId).getId(), true);

Wyświetl plik

@ -100,6 +100,8 @@ public final class JobManagerFactories {
put(GroupCallPeekWorkerJob.KEY, new GroupCallPeekWorkerJob.Factory());
put(GroupV2UpdateSelfProfileKeyJob.KEY, new GroupV2UpdateSelfProfileKeyJob.Factory());
put(KbsEnclaveMigrationWorkerJob.KEY, new KbsEnclaveMigrationWorkerJob.Factory());
put(LeaveGroupV2Job.KEY, new LeaveGroupV2Job.Factory());
put(LeaveGroupV2WorkerJob.KEY, new LeaveGroupV2WorkerJob.Factory());
put(LocalBackupJob.KEY, new LocalBackupJob.Factory());
put(LocalBackupJobApi29.KEY, new LocalBackupJobApi29.Factory());
put(MarkerJob.KEY, new MarkerJob.Factory());

Wyświetl plik

@ -0,0 +1,55 @@
package org.thoughtcrime.securesms.jobs
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.jobmanager.Data
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraint
/**
* During group state processing we sometimes detect situations where we should auto-leave. For example,
* being added to a group by someone we've blocked. This job functions similarly to other GV2 related
* jobs in that it waits for all decryptions to occur and then enqueues the actual [LeaveGroupV2Job] as
* part of the group's message processing queue.
*/
class LeaveGroupV2Job(parameters: Parameters, private val groupId: GroupId.V2) : BaseJob(parameters) {
constructor(groupId: GroupId.V2) : this(
parameters = Parameters.Builder()
.setQueue("LeaveGroupV2Job")
.addConstraint(DecryptionsDrainedConstraint.KEY)
.setMaxAttempts(Parameters.UNLIMITED)
.build(),
groupId = groupId
)
override fun serialize(): Data {
return Data.Builder()
.putString(KEY_GROUP_ID, groupId.toString())
.build()
}
override fun getFactoryKey(): String {
return KEY
}
override fun onRun() {
ApplicationDependencies.getJobManager().add(LeaveGroupV2WorkerJob(groupId))
}
override fun onShouldRetry(e: Exception): Boolean = false
override fun onFailure() = Unit
class Factory : Job.Factory<LeaveGroupV2Job> {
override fun create(parameters: Parameters, data: Data): LeaveGroupV2Job {
return LeaveGroupV2Job(parameters, GroupId.parseOrThrow(data.getString(KEY_GROUP_ID)).requireV2())
}
}
companion object {
const val KEY = "LeaveGroupV2Job"
private const val KEY_GROUP_ID = "group_id"
}
}

Wyświetl plik

@ -0,0 +1,76 @@
package org.thoughtcrime.securesms.jobs
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.groups.GroupChangeBusyException
import org.thoughtcrime.securesms.groups.GroupChangeFailedException
import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.jobmanager.Data
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.recipients.Recipient
import java.io.IOException
/**
* Leave a group. See [LeaveGroupV2Job] for more details on how this job should be enqueued.
*/
class LeaveGroupV2WorkerJob(parameters: Parameters, private val groupId: GroupId.V2) : BaseJob(parameters) {
constructor(groupId: GroupId.V2) : this(
parameters = Parameters.Builder()
.setQueue(PushProcessMessageJob.getQueueName(Recipient.externalGroupExact(ApplicationDependencies.getApplication(), groupId).id))
.addConstraint(NetworkConstraint.KEY)
.setMaxAttempts(Parameters.UNLIMITED)
.setMaxInstancesForQueue(2)
.build(),
groupId = groupId
)
override fun serialize(): Data {
return Data.Builder()
.putString(KEY_GROUP_ID, groupId.toString())
.build()
}
override fun getFactoryKey(): String {
return KEY
}
override fun onRun() {
Log.i(TAG, "Attempting to leave group $groupId")
val groupRecipient = Recipient.externalGroupExact(ApplicationDependencies.getApplication(), groupId)
GroupManager.leaveGroup(context, groupId)
val threadId = SignalDatabase.threads.getThreadIdIfExistsFor(groupRecipient.id)
if (threadId != -1L) {
SignalDatabase.recipients.setProfileSharing(groupRecipient.id, true)
SignalDatabase.threads.setEntireThreadRead(threadId)
SignalDatabase.threads.update(threadId, false, false)
ApplicationDependencies.getMessageNotifier().updateNotification(context)
}
}
override fun onShouldRetry(e: Exception): Boolean {
return e is GroupChangeBusyException || e is GroupChangeFailedException || e is IOException
}
override fun onFailure() = Unit
class Factory : Job.Factory<LeaveGroupV2WorkerJob> {
override fun create(parameters: Parameters, data: Data): LeaveGroupV2WorkerJob {
return LeaveGroupV2WorkerJob(parameters, GroupId.parseOrThrow(data.getString(KEY_GROUP_ID)).requireV2())
}
}
companion object {
const val KEY = "LeaveGroupWorkerJob"
private val TAG = Log.tag(LeaveGroupV2WorkerJob::class.java)
private const val KEY_GROUP_ID = "group_id"
}
}

Wyświetl plik

@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.database.MegaphoneDatabase
import org.thoughtcrime.securesms.database.MessageBitmaskColumnTransformer
import org.thoughtcrime.securesms.database.QueryMonitor
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.database.TimestampTransformer
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.AppSignatureUtil
@ -40,7 +41,7 @@ class SpinnerApplicationContext : ApplicationContext() {
linkedMapOf(
"signal" to DatabaseConfig(
db = SignalDatabase.rawDatabase,
columnTransformers = listOf(MessageBitmaskColumnTransformer, GV2Transformer, GV2UpdateTransformer, IsStoryTransformer)
columnTransformers = listOf(MessageBitmaskColumnTransformer, GV2Transformer, GV2UpdateTransformer, IsStoryTransformer, TimestampTransformer)
),
"jobmanager" to DatabaseConfig(db = JobDatabase.getInstance(this).sqlCipherDatabase),
"keyvalue" to DatabaseConfig(db = KeyValueDatabase.getInstance(this).sqlCipherDatabase),

Wyświetl plik

@ -0,0 +1,26 @@
package org.thoughtcrime.securesms.database
import android.database.Cursor
import org.signal.core.util.requireLong
import org.signal.spinner.ColumnTransformer
import org.signal.spinner.DefaultColumnTransformer
import org.thoughtcrime.securesms.util.toLocalDateTime
import org.thoughtcrime.securesms.util.toMillis
import java.time.LocalDateTime
object TimestampTransformer : ColumnTransformer {
override fun matches(tableName: String?, columnName: String): Boolean {
return columnName.contains("date", true) ||
columnName.contains("timestamp", true)
}
override fun transform(tableName: String?, columnName: String, cursor: Cursor): String {
val timestamp: Long = cursor.requireLong(columnName)
return if (timestamp > LocalDateTime.of(2000, 1, 1, 0, 0, 0, 0).toMillis()) {
"$timestamp<br><br>${timestamp.toLocalDateTime()}"
} else {
DefaultColumnTransformer.transform(tableName, columnName, cursor)
}
}
}