diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 89b8c9e63..f8bcd1cf3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -1219,7 +1219,12 @@ open class Storage( override fun getMembers(groupPublicKey: String): List = configFactory.getGroupMemberConfig(SessionId.from(groupPublicKey))?.use { it.all() }?.toList() ?: emptyList() - override fun acceptClosedGroupInvite(groupId: SessionId, name: String, authData: ByteArray, invitingAdmin: SessionId) { + override fun addClosedGroupInvite( + groupId: SessionId, + name: String, + authData: ByteArray, + invitingAdmin: SessionId + ) { val recipient = Recipient.from(context, fromSerialized(groupId.hexString()), false) val profileManager = SSKEnvironment.shared.profileManager val groups = configFactory.userGroups ?: return @@ -1229,17 +1234,20 @@ open class Storage( groups.set(closedGroupInfo) configFactory.persist(groups, SnodeAPI.nowWithOffset) profileManager.setName(context, recipient, name) - setRecipientApprovedMe(recipient, true) - setRecipientApproved(recipient, true) getOrCreateThreadIdFor(recipient.address) - pollerFactory.pollerFor(groupId)?.start() - val inviteResponse = GroupUpdateInviteResponseMessage.newBuilder() - .setIsApproved(true) - val responseData = DataMessage.GroupUpdateMessage.newBuilder() - .setInviteResponse(inviteResponse) - val responseMessage = GroupUpdated(responseData.build()) - // this will fail the first couple of times :) - MessageSender.send(responseMessage, fromSerialized(groupId.hexString())) + setRecipientApprovedMe(recipient, true) + val shouldAutoApprove = false //TESTING// getRecipientApproved(fromSerialized(invitingAdmin.hexString())) + setRecipientApproved(recipient, shouldAutoApprove) + if (shouldAutoApprove) { + pollerFactory.pollerFor(groupId)?.start() + val inviteResponse = GroupUpdateInviteResponseMessage.newBuilder() + .setIsApproved(true) + val responseData = GroupUpdateMessage.newBuilder() + .setInviteResponse(inviteResponse) + val responseMessage = GroupUpdated(responseData.build()) + // this will fail the first couple of times :) + MessageSender.send(responseMessage, fromSerialized(groupId.hexString())) + } } override fun setGroupInviteCompleteIfNeeded(approved: Boolean, invitee: String, closedGroup: SessionId) { @@ -1357,8 +1365,11 @@ open class Storage( } try { - response.get() - // todo: error handling here + val rawResponse = response.get() + val results = (rawResponse["results"] as ArrayList).first() as Map + if (results["code"] as Int != 200) { + throw Exception("Response wasn't successful for unrevoke and key update: ${results["body"] as? String}") + } configFactory.saveGroupConfigs(keysConfig, infoConfig, membersConfig) @@ -1604,6 +1615,12 @@ open class Storage( val infoMessage = info.messageInformation(toDelete, closedGroupHexString, adminKey) val membersMessage = members.messageInformation(toDelete, closedGroupHexString, adminKey) + val revocation = SnodeAPI.buildAuthenticatedRevokeSubKeyBatchRequest( + closedGroupHexString, + adminKey, + arrayOf(message.sender!!.let { keys.getSubAccountToken(SessionId.from(it)) }) + ) ?: return Log.e("ClosedGroup", "Failed to build revocation update") + val delete = SnodeAPI.buildAuthenticatedDeleteBatchInfo( closedGroupHexString, toDelete, @@ -1616,14 +1633,17 @@ open class Storage( SnodeAPI.getRawBatchResponse( snode, closedGroupHexString, - stores + delete, + stores + revocation + delete, sequence = true ) } try { - response.get() - // todo: error handling here + val rawResponse = response.get() + val results = (rawResponse["results"] as ArrayList).first() as Map + if (results["code"] as Int != 200) { + throw Exception("Response wasn't successful for revoke and key update: ${results["body"] as? String}") + } configFactory.saveGroupConfigs(keys, info, members) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index 7a28abe60..6bd010ec3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -503,7 +503,7 @@ public class ThreadDatabase extends Database { } public Cursor getApprovedConversationList() { - String where = "((" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+ LEGACY_CLOSED_GROUP_PREFIX +"%' OR "+RecipientDatabase.TABLE_NAME+"."+RecipientDatabase.ADDRESS+" LIKE '"+ IdPrefix.GROUP.getValue() +"%') " + + String where = "((" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+ LEGACY_CLOSED_GROUP_PREFIX +"%') " + "OR " + GroupDatabase.TABLE_NAME + "." + GROUP_ID + " LIKE '" + OPEN_GROUP_PREFIX + "%') " + "AND " + ARCHIVED + " = 0 "; return getConversationList(where); diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt index 10142cc8f..ae2d82577 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.messagerequests import android.content.Context import android.content.res.ColorStateList import android.database.Cursor +import android.os.Build import android.text.SpannableString import android.text.style.ForegroundColorSpan import android.view.ContextThemeWrapper @@ -61,10 +62,14 @@ class MessageRequestsAdapter( val item = popupMenu.menu.getItem(i) val s = SpannableString(item.title) s.setSpan(ForegroundColorSpan(context.getColor(R.color.destructive)), 0, s.length, 0) - item.iconTintList = ColorStateList.valueOf(context.getColor(R.color.destructive)) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + item.iconTintList = ColorStateList.valueOf(context.getColor(R.color.destructive)) + } item.title = s } - popupMenu.setForceShowIcon(true) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + popupMenu.setForceShowIcon(true) + } popupMenu.show() } diff --git a/gradle.properties b/gradle.properties index 4dafb9b9a..76b15e1c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ android.enableJetifier=true gradlePluginVersion=7.3.1 -org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" +org.gradle.jvmargs=-Xmx4096M -Dkotlin.daemon.jvm.options\="-Xmx4096M" org.gradle.unsafe.configuration-cache=true googleServicesVersion=4.3.12 diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index 3c5171fdd..23ee948d6 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -163,7 +163,7 @@ interface StorageProtocol { // Closed Groups fun createNewGroup(groupName: String, groupDescription: String, members: Set): Optional fun getMembers(groupPublicKey: String): List - fun acceptClosedGroupInvite(groupId: SessionId, name: String, authData: ByteArray, invitingAdmin: SessionId) + fun addClosedGroupInvite(groupId: SessionId, name: String, authData: ByteArray, invitingAdmin: SessionId) fun setGroupInviteCompleteIfNeeded(approved: Boolean, invitee: String, closedGroup: SessionId) fun getLibSessionClosedGroup(groupSessionId: String): GroupInfo.ClosedGroupInfo? fun getClosedGroupDisplayInfo(groupSessionId: String): GroupDisplayInfo? diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index 1a30845da..84d869464 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -597,10 +597,10 @@ private fun MessageReceiver.handleNewLibSessionClosedGroupMessage(message: Group val invite = message.inner.inviteMessage val groupId = SessionId.from(invite.groupSessionId) verifyAdminSignature(groupId, invite.adminSignature.toByteArray(), "INVITE"+ourUserId+message.sentTimestamp!!) - val adminId = SessionId.from(message.sender!!) - // TODO: add the pending invite logic after testing initial group signing / message adding / encryption works for members as well + val sender = message.sender!! + val adminId = SessionId.from(sender) // add the group - storage.acceptClosedGroupInvite(groupId, invite.name, invite.memberAuthData.toByteArray(), adminId) + storage.addClosedGroupInvite(groupId, invite.name, invite.memberAuthData.toByteArray(), adminId) } /**