diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt
index 4a8ec3b69..3055e5af9 100644
--- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt
+++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt
@@ -25,6 +25,7 @@ import expo.modules.xmtpreactnativesdk.wrappers.DecryptedLocalAttachment
import expo.modules.xmtpreactnativesdk.wrappers.EncryptedLocalAttachment
import expo.modules.xmtpreactnativesdk.wrappers.GroupWrapper
import expo.modules.xmtpreactnativesdk.wrappers.MemberWrapper
+import expo.modules.xmtpreactnativesdk.wrappers.PermissionPolicySetWrapper
import expo.modules.xmtpreactnativesdk.wrappers.PreparedLocalMessage
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
@@ -1165,6 +1166,21 @@ class XMTPModule : Module() {
}
}
+ AsyncFunction("permissionPolicySet") Coroutine { inboxId: String, id: String ->
+ withContext(Dispatchers.IO) {
+ logV("groupImageUrlSquare")
+ val client = clients[inboxId] ?: throw XMTPException("No client")
+ val group = findGroup(inboxId, id)
+
+ val permissionPolicySet = group?.permissionPolicySet()
+ if (permissionPolicySet != null) {
+ PermissionPolicySetWrapper.encodeToJsonString(permissionPolicySet)
+ } else {
+ throw XMTPException("Permission policy set not found for group: $id")
+ }
+ }
+ }
+
AsyncFunction("processGroupMessage") Coroutine { inboxId: String, id: String, encryptedMessage: String ->
withContext(Dispatchers.IO) {
logV("processGroupMessage")
diff --git a/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj b/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj
index 311bc6e1e..b0d31c117 100644
--- a/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj
+++ b/example/ios/xmtpreactnativesdkexample.xcodeproj/project.pbxproj
@@ -221,7 +221,7 @@
LastUpgradeCheck = 1130;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
- DevelopmentTeam = FY4NZR34Z3;
+ DevelopmentTeam = 65GVVS9K6W;
LastSwiftMigration = 1250;
};
A6A5DB842A00551E001DF8C2 = {
@@ -408,7 +408,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = xmtpreactnativesdkexample/xmtpreactnativesdkexample.entitlements;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = FY4NZR34Z3;
+ DEVELOPMENT_TEAM = 65GVVS9K6W;
ENABLE_BITCODE = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
@@ -424,7 +424,7 @@
"-lc++",
);
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
- PRODUCT_BUNDLE_IDENTIFIER = expo.modules.xmtpreactnativesdk.example;
+ PRODUCT_BUNDLE_IDENTIFIER = cvoell.modules.xmtpreactnativesdk.example;
PRODUCT_NAME = xmtpreactnativesdkexample;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -441,7 +441,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = xmtpreactnativesdkexample/xmtpreactnativesdkexample.entitlements;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = FY4NZR34Z3;
+ DEVELOPMENT_TEAM = 65GVVS9K6W;
INFOPLIST_FILE = xmtpreactnativesdkexample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -452,7 +452,7 @@
"-lc++",
);
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
- PRODUCT_BUNDLE_IDENTIFIER = expo.modules.xmtpreactnativesdk.example;
+ PRODUCT_BUNDLE_IDENTIFIER = cvoell.modules.xmtpreactnativesdk.example;
PRODUCT_NAME = xmtpreactnativesdkexample;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
diff --git a/example/ios/xmtpreactnativesdkexample/Info.plist b/example/ios/xmtpreactnativesdkexample/Info.plist
index ce646d17c..bd85f227a 100644
--- a/example/ios/xmtpreactnativesdkexample/Info.plist
+++ b/example/ios/xmtpreactnativesdkexample/Info.plist
@@ -1,82 +1,82 @@
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- xmtp-react-native-sdk-example
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- 1.0.0
- CFBundleSignature
- ????
- CFBundleURLTypes
-
-
- CFBundleURLSchemes
-
- expo.modules.xmtpreactnativesdk.example
-
-
-
- CFBundleVersion
- 1
- LSRequiresIPhoneOS
-
- NSAppTransportSecurity
-
- NSAllowsArbitraryLoads
-
- NSExceptionDomains
-
- localhost
-
- NSExceptionAllowsInsecureHTTPLoads
-
-
-
-
- NSCameraUsageDescription
- The app accesses your camera to let you attach photos as messages.
- NSMicrophoneUsageDescription
- Allow $(PRODUCT_NAME) to access your microphone
- NSPhotoLibraryUsageDescription
- The app accesses your photos to let you attach them as messages.
- UILaunchStoryboardName
- SplashScreen
- UIRequiredDeviceCapabilities
-
- armv7
-
- UIRequiresFullScreen
-
- UIStatusBarStyle
- UIStatusBarStyleDefault
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UIUserInterfaceStyle
- Light
- UIViewControllerBasedStatusBarAppearance
-
-
-
\ No newline at end of file
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ xmtp-react-native-sdk-example
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0.0
+ CFBundleSignature
+ ????
+ CFBundleURLTypes
+
+
+ CFBundleURLSchemes
+
+ expo.modules.xmtpreactnativesdk.example
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+ NSExceptionDomains
+
+ localhost
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+
+
+
+ NSCameraUsageDescription
+ The app accesses your camera to let you attach photos as messages.
+ NSMicrophoneUsageDescription
+ Allow $(PRODUCT_NAME) to access your microphone
+ NSPhotoLibraryUsageDescription
+ The app accesses your photos to let you attach them as messages.
+ UILaunchStoryboardName
+ SplashScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UIRequiresFullScreen
+
+ UIStatusBarStyle
+ UIStatusBarStyleDefault
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIUserInterfaceStyle
+ Light
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/example/src/tests/groupPermissionsTests.ts b/example/src/tests/groupPermissionsTests.ts
index 38abed82b..bd6ff470b 100644
--- a/example/src/tests/groupPermissionsTests.ts
+++ b/example/src/tests/groupPermissionsTests.ts
@@ -21,12 +21,8 @@ test('new group has expected admin list and super admin list', async () => {
const superAdminList = await alixGroup.listSuperAdmins()
assert(
- adminList.length === 1,
- `adminList.length should be 1 but was ${adminList.length}`
- )
- assert(
- adminList[0] === alix.inboxId,
- `adminList[0] should be ${alix.address} but was ${adminList[0]}`
+ adminList.length === 0,
+ `adminList.length should be 0 but was ${adminList.length}`
)
assert(
superAdminList.length === 1,
@@ -88,9 +84,9 @@ test('in admin only group, members can not update group name unless they are an
{ permissionLevel: 'admin_only' }
)
- if (alixGroup.permissionLevel !== 'admin_only') {
+ if ((await alixGroup.permissionPolicySet()).addMemberPolicy !== 'admin') {
throw Error(
- `Group permission level should be admin_only but was ${alixGroup.permissionLevel}`
+ `Group add member policy should be admin but was ${(await alixGroup.permissionPolicySet()).addMemberPolicy}`
)
}
@@ -123,9 +119,11 @@ test('in admin only group, members can update group name once they are an admin'
{ permissionLevel: 'admin_only' }
)
- if (alixGroup.permissionLevel !== 'admin_only') {
+ if (
+ (await alixGroup.permissionPolicySet()).updateGroupNamePolicy !== 'admin'
+ ) {
throw Error(
- `Group permission level should be admin_only but was ${alixGroup.permissionLevel}`
+ `Group update name policy should be admin but was ${(await alixGroup.permissionPolicySet()).updateGroupNamePolicy}`
)
}
@@ -174,9 +172,11 @@ test('in admin only group, members can not update group name after admin status
{ permissionLevel: 'admin_only' }
)
- if (alixGroup.permissionLevel !== 'admin_only') {
+ if (
+ (await alixGroup.permissionPolicySet()).updateGroupNamePolicy !== 'admin'
+ ) {
throw Error(
- `Group permission level should be admin_only but was ${alixGroup.permissionLevel}`
+ `Group update name policy should be admin but was ${(await alixGroup.permissionPolicySet()).updateGroupNamePolicy}`
)
}
@@ -392,3 +392,74 @@ test('group with All Members policy has remove function that is admin only', asy
return true
})
+
+test('can update group permissions', async () => {
+ // Create clients
+ const [alix, bo, caro] = await createClients(3)
+
+ // Bo creates a group with Alix and Caro
+ const boGroup = await bo.conversations.newGroup(
+ [alix.address, caro.address],
+ { permissionLevel: 'admin_only' }
+ )
+
+ // Verify that bo is a super admin
+ assert(
+ (await boGroup.isSuperAdmin(bo.inboxId)) === true,
+ `bo should be a super admin`
+ )
+
+ // Verify that group has the expected group description permission
+ assert(
+ (await boGroup.permissionPolicySet()).updateGroupDescriptionPolicy ===
+ 'admin',
+ `boGroup.permissionPolicySet.updateGroupDescriptionPolicy should be admin but was ${(await boGroup.permissionPolicySet()).updateGroupDescriptionPolicy}`
+ )
+
+ // Verify that Bo can update the group description
+ await boGroup.updateGroupDescription('new description')
+ await boGroup.sync()
+ assert(
+ (await boGroup.groupDescription()) === 'new description',
+ `boGroup.groupDescription should be "new description" but was ${boGroup.groupDescription}`
+ )
+
+ // Verify that alix can not update the group description
+ await alix.conversations.syncGroups()
+ const alixGroup = (await alix.conversations.listGroups())[0]
+ try {
+ await alixGroup.updateGroupDescription('new description')
+ assert(false, 'Alix should not be able to update the group description')
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ } catch (error) {
+ // expected
+ }
+
+ // Verify that alix can not update permissions
+ try {
+ await alixGroup.updateGroupDescriptionPermission('allow')
+ assert(false, 'Alix should not be able to update the group name permission')
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ } catch (error) {
+ // expected
+ }
+
+ // Verify that bo can update permissions
+ await boGroup.updateGroupDescriptionPermission('allow')
+ await boGroup.sync()
+ assert(
+ (await boGroup.permissionPolicySet()).updateGroupDescriptionPolicy ===
+ 'allow',
+ `boGroup.permissionPolicySet.updateGroupDescriptionPolicy should be allow but was ${(await boGroup.permissionPolicySet()).updateGroupDescriptionPolicy}`
+ )
+
+ // Verify that alix can now update the group description
+ await alixGroup.updateGroupDescription('new description 2')
+ await alixGroup.sync()
+ assert(
+ (await alixGroup.groupDescription()) === 'new description 2',
+ `alixGroup.groupDescription should be "new description 2" but was ${alixGroup.groupDescription}`
+ )
+
+ return true
+})
diff --git a/example/src/tests/groupTests.ts b/example/src/tests/groupTests.ts
index 5aa2a2ad1..4a6dfbfa0 100644
--- a/example/src/tests/groupTests.ts
+++ b/example/src/tests/groupTests.ts
@@ -1137,9 +1137,9 @@ test('can make a group with admin permissions', async () => {
{ permissionLevel: 'admin_only' }
)
- if (group.permissionPolicySet.addMemberPolicy !== 'admin') {
+ if ((await group.permissionPolicySet()).addMemberPolicy !== 'admin') {
throw Error(
- `Group permission level should be admin but was ${group.permissionPolicySet.addMemberPolicy}`
+ `Group permission level should be admin but was ${(await group.permissionPolicySet()).addMemberPolicy}`
)
}
diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift
index 28ee6b12d..18c367819 100644
--- a/ios/XMTPModule.swift
+++ b/ios/XMTPModule.swift
@@ -59,7 +59,7 @@ public class XMTPModule: Module {
}
enum Error: Swift.Error {
- case noClient, conversationNotFound(String), noMessage, invalidKeyBundle, invalidDigest, badPreparation(String), mlsNotEnabled(String), invalidString
+ case noClient, conversationNotFound(String), noMessage, invalidKeyBundle, invalidDigest, badPreparation(String), mlsNotEnabled(String), invalidString, invalidPermissionOption
}
public func definition() -> ModuleDefinition {
@@ -987,13 +987,100 @@ public class XMTPModule: Module {
}
try await group.removeSuperAdmin(inboxId: inboxId)
}
-
- AsyncFunction("processGroupMessage") { (inboxId: String, id: String, encryptedMessage: String) -> String in
- guard let client = await clientsManager.getClient(key: inboxId) else {
- throw Error.noClient
- }
-
- guard let group = try await findGroup(inboxId: inboxId, id: id) else {
+
+ AsyncFunction("updateAddMemberPermission") { (clientInboxId: String, id: String, newPermission: String) in
+ guard let client = await clientsManager.getClient(key: clientInboxId) else {
+ throw Error.noClient
+ }
+ guard let group = try await findGroup(inboxId: clientInboxId, id: id) else {
+ throw Error.conversationNotFound("no group found for \(id)")
+ }
+ try await group.updateAddMemberPermission(newPermissionOption: getPermissionOption(permission: newPermission))
+ }
+
+ AsyncFunction("updateRemoveMemberPermission") { (clientInboxId: String, id: String, newPermission: String) in
+ guard let client = await clientsManager.getClient(key: clientInboxId) else {
+ throw Error.noClient
+ }
+ guard let group = try await findGroup(inboxId: clientInboxId, id: id) else {
+ throw Error.conversationNotFound("no group found for \(id)")
+ }
+ try await group.updateRemoveMemberPermission(newPermissionOption: getPermissionOption(permission: newPermission))
+ }
+
+ AsyncFunction("updateAddAdminPermission") { (clientInboxId: String, id: String, newPermission: String) in
+ guard let client = await clientsManager.getClient(key: clientInboxId) else {
+ throw Error.noClient
+ }
+ guard let group = try await findGroup(inboxId: clientInboxId, id: id) else {
+ throw Error.conversationNotFound("no group found for \(id)")
+ }
+ try await group.updateAddAdminPermission(newPermissionOption: getPermissionOption(permission: newPermission))
+ }
+
+ AsyncFunction("updateRemoveAdminPermission") { (clientInboxId: String, id: String, newPermission: String) in
+ guard let client = await clientsManager.getClient(key: clientInboxId) else {
+ throw Error.noClient
+ }
+ guard let group = try await findGroup(inboxId: clientInboxId, id: id) else {
+ throw Error.conversationNotFound("no group found for \(id)")
+ }
+ try await group.updateRemoveAdminPermission(newPermissionOption: getPermissionOption(permission: newPermission))
+ }
+
+ AsyncFunction("updateGroupNamePermission") { (clientInboxId: String, id: String, newPermission: String) in
+ guard let client = await clientsManager.getClient(key: clientInboxId) else {
+ throw Error.noClient
+ }
+ guard let group = try await findGroup(inboxId: clientInboxId, id: id) else {
+ throw Error.conversationNotFound("no group found for \(id)")
+ }
+ try await group.updateGroupNamePermission(newPermissionOption: getPermissionOption(permission: newPermission))
+ }
+
+ AsyncFunction("updateGroupImageUrlSquarePermission") { (clientInboxId: String, id: String, newPermission: String) in
+ guard let client = await clientsManager.getClient(key: clientInboxId) else {
+ throw Error.noClient
+ }
+ guard let group = try await findGroup(inboxId: clientInboxId, id: id) else {
+ throw Error.conversationNotFound("no group found for \(id)")
+ }
+ try await group.updateGroupImageUrlSquarePermission(newPermissionOption: getPermissionOption(permission: newPermission))
+ }
+
+ AsyncFunction("updateGroupDescriptionPermission") { (clientInboxId: String, id: String, newPermission: String) in
+ guard let client = await clientsManager.getClient(key: clientInboxId) else {
+ throw Error.noClient
+ }
+ guard let group = try await findGroup(inboxId: clientInboxId, id: id) else {
+ throw Error.conversationNotFound("no group found for \(id)")
+ }
+ try await group.updateGroupDescriptionPermission(newPermissionOption: getPermissionOption(permission: newPermission))
+ }
+
+ AsyncFunction("permissionPolicySet") { (inboxId: String, id: String) async throws -> String in
+
+ guard let client = await clientsManager.getClient(key: inboxId) else {
+ throw Error.noClient
+ }
+
+ guard let group = try await findGroup(inboxId: inboxId, id: id) else {
+ throw Error.conversationNotFound("Permission policy set not found for group: \(id)")
+ }
+
+ let permissionPolicySet = try group.permissionPolicySet()
+
+ return try PermissionPolicySetWrapper.encodeToJsonString(permissionPolicySet)
+ }
+
+
+
+ AsyncFunction("processGroupMessage") { (inboxId: String, id: String, encryptedMessage: String) -> String in
+ guard let client = await clientsManager.getClient(key: inboxId) else {
+ throw Error.noClient
+ }
+
+ guard let group = try await findGroup(inboxId: inboxId, id: id) else {
throw Error.conversationNotFound("no group found for \(id)")
}
@@ -1275,6 +1362,21 @@ public class XMTPModule: Module {
//
// Helpers
//
+
+ private func getPermissionOption(permission: String) async throws -> PermissionOption {
+ switch permission {
+ case "allow":
+ return .allow
+ case "deny":
+ return .deny
+ case "admin":
+ return .admin
+ case "super_admin":
+ return .superAdmin
+ default:
+ throw Error.invalidPermissionOption
+ }
+ }
func createClientConfig(env: String, appVersion: String?, preEnableIdentityCallback: PreEventCallback? = nil, preCreateIdentityCallback: PreEventCallback? = nil, enableV3: Bool = false, dbEncryptionKey: Data? = nil, dbDirectory: String? = nil, historySyncUrl: String? = nil) -> XMTP.ClientOptions {
// Ensure that all codecs have been registered.
diff --git a/src/index.ts b/src/index.ts
index 2c1052d22..97f21dd15 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -18,11 +18,12 @@ import {
ConversationVersion,
} from './lib/ConversationContainer'
import { DecodedMessage, MessageDeliveryStatus } from './lib/DecodedMessage'
-import { Group } from './lib/Group'
+import { Group, PermissionUpdateOption } from './lib/Group'
import { Member } from './lib/Member'
import type { Query } from './lib/Query'
import { ConversationSendPayload } from './lib/types'
import { DefaultContentTypes } from './lib/types/DefaultContentType'
+import { PermissionPolicySet } from './lib/types/PermissionPolicySet'
import { getAddress } from './utils/address'
export * from './context'
@@ -170,17 +171,19 @@ export async function createGroup<
imageUrlSquare: string = '',
description: string = ''
): Promise> {
- const groupString = await XMTPModule.createGroup(
- client.inboxId,
- peerAddresses,
- permissionLevel,
- name,
- imageUrlSquare,
- description
+ return new Group(
+ client,
+ JSON.parse(
+ await XMTPModule.createGroup(
+ client.inboxId,
+ peerAddresses,
+ permissionLevel,
+ name,
+ imageUrlSquare,
+ description
+ )
+ )
)
- const groupObj = JSON.parse(groupString)
- groupObj.permissionPolicySet = JSON.parse(groupObj.permissionPolicySet)
- return new Group(client, groupObj)
}
export async function listGroups<
@@ -877,6 +880,98 @@ export async function removeSuperAdmin(
return XMTPModule.removeSuperAdmin(clientInboxId, id, inboxId)
}
+export async function updateAddMemberPermission(
+ clientInboxId: string,
+ id: string,
+ permissionOption: PermissionUpdateOption
+): Promise {
+ return XMTPModule.updateAddMemberPermission(
+ clientInboxId,
+ id,
+ permissionOption
+ )
+}
+
+export async function updateRemoveMemberPermission(
+ clientInboxId: string,
+ id: string,
+ permissionOption: PermissionUpdateOption
+): Promise {
+ return XMTPModule.updateRemoveMemberPermission(
+ clientInboxId,
+ id,
+ permissionOption
+ )
+}
+
+export async function updateAddAdminPermission(
+ clientInboxId: string,
+ id: string,
+ permissionOption: PermissionUpdateOption
+): Promise {
+ return XMTPModule.updateAddAdminPermission(
+ clientInboxId,
+ id,
+ permissionOption
+ )
+}
+
+export async function updateRemoveAdminPermission(
+ clientInboxId: string,
+ id: string,
+ permissionOption: PermissionUpdateOption
+): Promise {
+ return XMTPModule.updateRemoveAdminPermission(
+ clientInboxId,
+ id,
+ permissionOption
+ )
+}
+
+export async function updateGroupNamePermission(
+ clientInboxId: string,
+ id: string,
+ permissionOption: PermissionUpdateOption
+): Promise {
+ return XMTPModule.updateGroupNamePermission(
+ clientInboxId,
+ id,
+ permissionOption
+ )
+}
+
+export async function updateGroupImageUrlSquarePermission(
+ clientInboxId: string,
+ id: string,
+ permissionOption: PermissionUpdateOption
+): Promise {
+ return XMTPModule.updateGroupImageUrlSquarePermission(
+ clientInboxId,
+ id,
+ permissionOption
+ )
+}
+
+export async function updateGroupDescriptionPermission(
+ clientInboxId: string,
+ id: string,
+ permissionOption: PermissionUpdateOption
+): Promise {
+ return XMTPModule.updateGroupDescriptionPermission(
+ clientInboxId,
+ id,
+ permissionOption
+ )
+}
+
+export async function permissionPolicySet(
+ clientInboxId: string,
+ id: string
+): Promise {
+ const json = await XMTPModule.permissionPolicySet(clientInboxId, id)
+ return JSON.parse(json)
+}
+
export async function allowGroups(
inboxId: string,
groupIds: string[]
diff --git a/src/lib/Group.ts b/src/lib/Group.ts
index c915e728a..8174e258a 100644
--- a/src/lib/Group.ts
+++ b/src/lib/Group.ts
@@ -13,6 +13,8 @@ import { PermissionPolicySet } from './types/PermissionPolicySet'
import { SendOptions } from './types/SendOptions'
import * as XMTP from '../index'
+export type PermissionUpdateOption = 'allow' | 'deny' | 'admin' | 'super_admin'
+
export class Group<
ContentTypes extends DefaultContentTypes = DefaultContentTypes,
> implements ConversationContainer
@@ -24,7 +26,6 @@ export class Group<
version = ConversationVersion.GROUP
topic: string
creatorInboxId: InboxId
- permissionPolicySet: PermissionPolicySet
name: string
isGroupActive: boolean
imageUrlSquare: string
@@ -36,7 +37,6 @@ export class Group<
createdAt: number
peerInboxIds: InboxId[]
creatorInboxId: InboxId
- permissionPolicySet: PermissionPolicySet
topic: string
name: string
isGroupActive: boolean
@@ -49,7 +49,6 @@ export class Group<
this.peerInboxIds = params.peerInboxIds
this.topic = params.topic
this.creatorInboxId = params.creatorInboxId
- this.permissionPolicySet = params.permissionPolicySet
this.name = params.name
this.isGroupActive = params.isGroupActive
this.imageUrlSquare = params.imageUrlSquare
@@ -384,6 +383,126 @@ export class Group<
return XMTP.removeSuperAdmin(this.client.inboxId, this.id, inboxId)
}
+ /**
+ *
+ * @param {PermissionOption} permissionOption
+ * @returns {Promise} A Promise that resolves when the addMember permission is updated for the group.
+ * Will throw if the user does not have the required permissions.
+ */
+ async updateAddMemberPermission(
+ permissionOption: PermissionUpdateOption
+ ): Promise {
+ return XMTP.updateAddMemberPermission(
+ this.client.inboxId,
+ this.id,
+ permissionOption
+ )
+ }
+
+ /**
+ *
+ * @param {PermissionOption} permissionOption
+ * @returns {Promise} A Promise that resolves when the removeMember permission is updated for the group.
+ * Will throw if the user does not have the required permissions.
+ */
+ async updateRemoveMemberPermission(
+ permissionOption: PermissionUpdateOption
+ ): Promise {
+ return XMTP.updateRemoveMemberPermission(
+ this.client.inboxId,
+ this.id,
+ permissionOption
+ )
+ }
+
+ /**
+ *
+ * @param {PermissionOption} permissionOption
+ * @returns {Promise} A Promise that resolves when the addAdmin permission is updated for the group.
+ * Will throw if the user does not have the required permissions.
+ */
+ async updateAddAdminPermission(
+ permissionOption: PermissionUpdateOption
+ ): Promise {
+ return XMTP.updateAddAdminPermission(
+ this.client.inboxId,
+ this.id,
+ permissionOption
+ )
+ }
+
+ /**
+ *
+ * @param {PermissionOption} permissionOption
+ * @returns {Promise} A Promise that resolves when the removeAdmin permission is updated for the group.
+ * Will throw if the user does not have the required permissions.
+ */
+ async updateRemoveAdminPermission(
+ permissionOption: PermissionUpdateOption
+ ): Promise {
+ return XMTP.updateRemoveAdminPermission(
+ this.client.inboxId,
+ this.id,
+ permissionOption
+ )
+ }
+
+ /**
+ *
+ * @param {PermissionOption} permissionOption
+ * @returns {Promise} A Promise that resolves when the groupName permission is updated for the group.
+ * Will throw if the user does not have the required permissions.
+ */
+ async updateGroupNamePermission(
+ permissionOption: PermissionUpdateOption
+ ): Promise {
+ return XMTP.updateGroupNamePermission(
+ this.client.inboxId,
+ this.id,
+ permissionOption
+ )
+ }
+
+ /**
+ *
+ * @param {PermissionOption} permissionOption
+ * @returns {Promise} A Promise that resolves when the groupImageUrlSquare permission is updated for the group.
+ * Will throw if the user does not have the required permissions.
+ */
+ async updateGroupImageUrlSquarePermission(
+ permissionOption: PermissionUpdateOption
+ ): Promise {
+ return XMTP.updateGroupImageUrlSquarePermission(
+ this.client.inboxId,
+ this.id,
+ permissionOption
+ )
+ }
+
+ /**
+ *
+ * @param {PermissionOption} permissionOption
+ * @returns {Promise} A Promise that resolves when the groupDescription permission is updated for the group.
+ * Will throw if the user does not have the required permissions.
+ */
+ async updateGroupDescriptionPermission(
+ permissionOption: PermissionUpdateOption
+ ): Promise {
+ return XMTP.updateGroupDescriptionPermission(
+ this.client.inboxId,
+ this.id,
+ permissionOption
+ )
+ }
+
+ /**
+ *
+ * @returns {Promise} A {PermissionPolicySet} object representing the group's permission policy set.
+ */
+ async permissionPolicySet(): Promise {
+ return XMTP.permissionPolicySet(this.client.inboxId, this.id)
+ }
+
async processMessage(
encryptedMessage: string
): Promise> {