Skip to content

Commit

Permalink
Group Admin Permissions (#182)
Browse files Browse the repository at this point in the history
  • Loading branch information
nplasterer authored Feb 20, 2024
1 parent a59fe92 commit 78c26eb
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 14 deletions.
74 changes: 66 additions & 8 deletions library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.xmtp.android.library.codecs.ReactionSchema
import org.xmtp.android.library.messages.PrivateKey
import org.xmtp.android.library.messages.PrivateKeyBuilder
import org.xmtp.android.library.messages.walletAddress
import uniffi.xmtpv3.GroupPermissions

@RunWith(AndroidJUnit4::class)
class GroupTest {
Expand Down Expand Up @@ -57,9 +58,63 @@ class GroupTest {
}

@Test
fun testCanCreateAGroup() {
val group = boClient.conversations.newGroup(listOf(alix.walletAddress))
assert(group.id.isNotEmpty())
fun testCanCreateAGroupWithDefaultPermissions() {
val boGroup = boClient.conversations.newGroup(listOf(alix.walletAddress))
runBlocking { alixClient.conversations.syncGroups() }
val alixGroup = alixClient.conversations.listGroups().first()
assert(boGroup.id.isNotEmpty())
assert(alixGroup.id.isNotEmpty())

alixGroup.addMembers(listOf(caro.walletAddress))
runBlocking { boGroup.sync() }
assertEquals(alixGroup.memberAddresses().size, 3)
assertEquals(boGroup.memberAddresses().size, 3)

alixGroup.removeMembers(listOf(caro.walletAddress))
runBlocking { boGroup.sync() }
assertEquals(alixGroup.memberAddresses().size, 2)
assertEquals(boGroup.memberAddresses().size, 2)

boGroup.addMembers(listOf(caro.walletAddress))
runBlocking { alixGroup.sync() }
assertEquals(alixGroup.memberAddresses().size, 3)
assertEquals(boGroup.memberAddresses().size, 3)
}

@Test
fun testCanCreateAGroupWithAdminPermissions() {
val boGroup = boClient.conversations.newGroup(
listOf(alix.walletAddress),
permissions = GroupPermissions.GROUP_CREATOR_IS_ADMIN
)
runBlocking { alixClient.conversations.syncGroups() }
val alixGroup = alixClient.conversations.listGroups().first()
assert(boGroup.id.isNotEmpty())
assert(alixGroup.id.isNotEmpty())

boGroup.addMembers(listOf(caro.walletAddress))
runBlocking { alixGroup.sync() }
assertEquals(alixGroup.memberAddresses().size, 3)
assertEquals(boGroup.memberAddresses().size, 3)

assertThrows(XMTPException::class.java) {
alixGroup.removeMembers(listOf(caro.walletAddress))
}
runBlocking { boGroup.sync() }
assertEquals(alixGroup.memberAddresses().size, 3)
assertEquals(boGroup.memberAddresses().size, 3)

boGroup.removeMembers(listOf(caro.walletAddress))
runBlocking { alixGroup.sync() }
assertEquals(alixGroup.memberAddresses().size, 2)
assertEquals(boGroup.memberAddresses().size, 2)

assertThrows(XMTPException::class.java) {
alixGroup.addMembers(listOf(caro.walletAddress))
}
runBlocking { boGroup.sync() }
assertEquals(alixGroup.memberAddresses().size, 2)
assertEquals(boGroup.memberAddresses().size, 2)
}

@Test
Expand Down Expand Up @@ -241,22 +296,25 @@ class GroupTest {
@Test
fun testCanStreamGroupMessages() = kotlinx.coroutines.test.runTest {
val group = boClient.conversations.newGroup(listOf(alix.walletAddress.lowercase()))
alixClient.conversations.syncGroups()
val alixGroup = alixClient.conversations.listGroups().first()
group.streamMessages().test {
group.send("hi")
alixGroup.send("hi")
assertEquals("hi", awaitItem().body)
group.send("hi again")
alixGroup.send("hi again")
assertEquals("hi again", awaitItem().body)
}
}

@Test
fun testCanStreamDecryptedGroupMessages() = kotlinx.coroutines.test.runTest {
val group = boClient.conversations.newGroup(listOf(alix.walletAddress))

alixClient.conversations.syncGroups()
val alixGroup = alixClient.conversations.listGroups().first()
group.streamDecryptedMessages().test {
group.send("hi")
alixGroup.send("hi")
assertEquals("hi", awaitItem().encodedContent.content.toStringUtf8())
group.send("hi again")
alixGroup.send("hi again")
assertEquals("hi again", awaitItem().encodedContent.content.toStringUtf8())
}
}
Expand Down
3 changes: 1 addition & 2 deletions library/src/main/java/org/xmtp/android/library/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -566,8 +566,7 @@ class Client() {

fun canMessage(addresses: List<String>): Boolean {
return runBlocking {
libXMTPClient != null && !libXMTPClient!!.canMessage(addresses.map { it })
.contains(false)
libXMTPClient != null && !libXMTPClient!!.canMessage(addresses).contains(false)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import uniffi.xmtpv3.FfiConversationCallback
import uniffi.xmtpv3.FfiConversations
import uniffi.xmtpv3.FfiGroup
import uniffi.xmtpv3.FfiListConversationsOptions
import uniffi.xmtpv3.GroupPermissions
import java.util.Date
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.DurationUnit
Expand Down Expand Up @@ -91,7 +92,10 @@ data class Conversations(
)
}

fun newGroup(accountAddresses: List<String>): Group {
fun newGroup(
accountAddresses: List<String>,
permissions: GroupPermissions = GroupPermissions.EVERYONE_IS_ADMIN,
): Group {
if (accountAddresses.isEmpty()) {
throw XMTPException("Cannot start an empty group chat.")
}
Expand All @@ -105,7 +109,7 @@ data class Conversations(
}

val group = runBlocking {
libXMTPConversations?.createGroup(accountAddresses, permissions = null)
libXMTPConversations?.createGroup(accountAddresses, permissions = permissions)
?: throw XMTPException("Client does not support Groups")
}
return Group(client, group)
Expand Down
13 changes: 11 additions & 2 deletions library/src/main/java/org/xmtp/android/library/Group.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import uniffi.xmtpv3.FfiGroup
import uniffi.xmtpv3.FfiListMessagesOptions
import uniffi.xmtpv3.FfiMessage
import uniffi.xmtpv3.FfiMessageCallback
import java.lang.Exception
import java.util.Date
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.DurationUnit
Expand Down Expand Up @@ -133,11 +134,19 @@ class Group(val client: Client, private val libXMTPGroup: FfiGroup) {
}

fun addMembers(addresses: List<String>) {
runBlocking { libXMTPGroup.addMembers(addresses) }
try {
runBlocking { libXMTPGroup.addMembers(addresses) }
} catch (e: Exception) {
throw XMTPException("User does not have permissions", e)
}
}

fun removeMembers(addresses: List<String>) {
runBlocking { libXMTPGroup.removeMembers(addresses) }
try {
runBlocking { libXMTPGroup.removeMembers(addresses) }
} catch (e: Exception) {
throw XMTPException("User does not have permissions", e)
}
}

fun memberAddresses(): List<String> {
Expand Down

0 comments on commit 78c26eb

Please sign in to comment.