Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow custom permissions on group creation #371

Merged
merged 2 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/xmtp/libxmtp-swift.git",
"state" : {
"revision" : "b19830dc02d03deea89e9fad3b3ed22e102f86f2",
"version" : "0.5.4-beta3"
"revision" : "1b4900330822a7fbb143cdf67fcede557e57dbe8",
"version" : "0.5.6-beta1"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let package = Package(
.package(url: "https://github.com/1024jp/GzipSwift", from: "5.2.0"),
.package(url: "https://github.com/bufbuild/connect-swift", exact: "0.12.0"),
.package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.0.0"),
.package(url: "https://github.com/xmtp/libxmtp-swift.git", exact: "0.5.6-beta0"),
.package(url: "https://github.com/xmtp/libxmtp-swift.git", exact: "0.5.6-beta1"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand Down
50 changes: 44 additions & 6 deletions Sources/XMTPiOS/Conversations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,50 @@ public actor Conversations {
}
}
}

public func newGroup(with addresses: [String],
permissions: GroupPermissionPreconfiguration = .allMembers,

public func newGroup(with addresses: [String],
permissions: GroupPermissionPreconfiguration = .allMembers,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = ""
) async throws -> Group {
return try await newGroupInternal(
with: addresses,
permissions: GroupPermissionPreconfiguration.toFfiGroupPermissionOptions(option: permissions),
name: name,
imageUrlSquare: imageUrlSquare,
description: description,
pinnedFrameUrl: pinnedFrameUrl,
permissionPolicySet: nil
)
}

public func newGroupCustomPermissions(with addresses: [String],
permissionPolicySet: PermissionPolicySet,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = ""
) async throws -> Group {
return try await newGroupInternal(
with: addresses,
permissions: FfiGroupPermissionsOptions.customPolicy,
name: name,
imageUrlSquare: imageUrlSquare,
description: description,
pinnedFrameUrl: pinnedFrameUrl,
permissionPolicySet: PermissionPolicySet.toFfiPermissionPolicySet(permissionPolicySet)
)
}

private func newGroupInternal(with addresses: [String],
permissions: FfiGroupPermissionsOptions = .allMembers,
name: String = "",
imageUrlSquare: String = "",
description: String = "",
pinnedFrameUrl: String = ""
pinnedFrameUrl: String = "",
permissionPolicySet: FfiPermissionPolicySet? = nil
) async throws -> Group {
guard let v3Client = client.v3Client else {
throw GroupError.alphaMLSNotEnabled
Expand Down Expand Up @@ -177,11 +214,12 @@ public actor Conversations {
throw GroupError.memberNotRegistered(erroredAddresses)
}
let group = try await v3Client.conversations().createGroup(accountAddresses: addresses,
opts: FfiCreateGroupOptions(permissions: GroupPermissionPreconfiguration.toFfiGroupPermissionOptions(option: permissions),
opts: FfiCreateGroupOptions(permissions: permissions,
groupName: name,
groupImageUrlSquare: imageUrlSquare,
groupDescription: description,
groupPinnedFrameUrl: pinnedFrameUrl
groupPinnedFrameUrl: pinnedFrameUrl,
customPermissionPolicySet: permissionPolicySet
)).fromFFI(client: client)
try await client.contacts.allowGroups(groupIds: [group.id])
return group
Expand Down
2 changes: 1 addition & 1 deletion Sources/XMTPiOS/Group.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public struct Group: Identifiable, Equatable, Hashable {
}

public func permissionPolicySet() throws -> PermissionPolicySet {
return PermissionPolicySet(ffiPermissionPolicySet: try permissions().policySet())
return PermissionPolicySet.fromFfiPermissionPolicySet(try permissions().policySet())
}

public func creatorInboxId() throws -> String {
Expand Down
75 changes: 42 additions & 33 deletions Sources/XMTPiOS/Mls/PermissionPolicySet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,41 +54,50 @@ public enum GroupPermissionPreconfiguration {
}

public class PermissionPolicySet {
let ffiPermissionPolicySet: FfiPermissionPolicySet

init(ffiPermissionPolicySet: FfiPermissionPolicySet) {
self.ffiPermissionPolicySet = ffiPermissionPolicySet
}

public var addMemberPolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.addMemberPolicy)
}

public var removeMemberPolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.removeMemberPolicy)
}

public var addAdminPolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.addAdminPolicy)
}

public var removeAdminPolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.removeAdminPolicy)
}

public var updateGroupNamePolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupNamePolicy)
}

public var updateGroupDescriptionPolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupDescriptionPolicy)
var addMemberPolicy: PermissionOption
var removeMemberPolicy: PermissionOption
var addAdminPolicy: PermissionOption
var removeAdminPolicy: PermissionOption
var updateGroupNamePolicy: PermissionOption
var updateGroupDescriptionPolicy: PermissionOption
var updateGroupImagePolicy: PermissionOption
var updateGroupPinnedFrameUrlPolicy: PermissionOption

init(addMemberPolicy: PermissionOption, removeMemberPolicy: PermissionOption, addAdminPolicy: PermissionOption, removeAdminPolicy: PermissionOption, updateGroupNamePolicy: PermissionOption, updateGroupDescriptionPolicy: PermissionOption, updateGroupImagePolicy: PermissionOption, updateGroupPinnedFrameUrlPolicy: PermissionOption) {
self.addMemberPolicy = addMemberPolicy
self.removeMemberPolicy = removeMemberPolicy
self.addAdminPolicy = addAdminPolicy
self.removeAdminPolicy = removeAdminPolicy
self.updateGroupNamePolicy = updateGroupNamePolicy
self.updateGroupDescriptionPolicy = updateGroupDescriptionPolicy
self.updateGroupImagePolicy = updateGroupImagePolicy
self.updateGroupPinnedFrameUrlPolicy = updateGroupPinnedFrameUrlPolicy
}

public var updateGroupImagePolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupImageUrlSquarePolicy)

static func toFfiPermissionPolicySet(_ permissionPolicySet: PermissionPolicySet) -> FfiPermissionPolicySet {
return FfiPermissionPolicySet(
addMemberPolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.addMemberPolicy),
removeMemberPolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.removeMemberPolicy),
addAdminPolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.addAdminPolicy),
removeAdminPolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.removeAdminPolicy),
updateGroupNamePolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.updateGroupNamePolicy),
updateGroupDescriptionPolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.updateGroupDescriptionPolicy),
updateGroupImageUrlSquarePolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.updateGroupImagePolicy),
updateGroupPinnedFrameUrlPolicy: PermissionOption.toFfiPermissionPolicy(option: permissionPolicySet.updateGroupPinnedFrameUrlPolicy)
)
}

public var updateGroupPinnedFrameUrlPolicy: PermissionOption {
return PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupPinnedFrameUrlPolicy)
static func fromFfiPermissionPolicySet(_ ffiPermissionPolicySet: FfiPermissionPolicySet) -> PermissionPolicySet {
return PermissionPolicySet(
addMemberPolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.addMemberPolicy),
removeMemberPolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.removeMemberPolicy),
addAdminPolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.addAdminPolicy),
removeAdminPolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.removeAdminPolicy),
updateGroupNamePolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupNamePolicy),
updateGroupDescriptionPolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupDescriptionPolicy),
updateGroupImagePolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupImageUrlSquarePolicy),
updateGroupPinnedFrameUrlPolicy: PermissionOption.fromFfiPermissionPolicy(ffiPolicy: ffiPermissionPolicySet.updateGroupPinnedFrameUrlPolicy)
)
}
}

54 changes: 54 additions & 0 deletions Tests/XMTPTests/GroupPermissionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,58 @@ class GroupPermissionTests: XCTestCase {
XCTAssertEqual(try bobGroup.groupPinnedFrameUrl(), "https://foo/barz.com")
XCTAssertEqual(try aliceGroup.groupPinnedFrameUrl(), "https://foo/barz.com")
}

func testCanCreateGroupWithCustomPermissions() async throws {
let fixtures = try await localFixtures()
let permissionPolicySet = PermissionPolicySet(
addMemberPolicy: PermissionOption.admin,
removeMemberPolicy: PermissionOption.deny,
addAdminPolicy: PermissionOption.admin,
removeAdminPolicy: PermissionOption.superAdmin,
updateGroupNamePolicy: PermissionOption.admin,
updateGroupDescriptionPolicy: PermissionOption.allow,
updateGroupImagePolicy: PermissionOption.admin,
updateGroupPinnedFrameUrlPolicy: PermissionOption.deny
)
let bobGroup = try await fixtures.bobClient.conversations.newGroupCustomPermissions(
with: [fixtures.alice.walletAddress, fixtures.caro.walletAddress],
permissionPolicySet: permissionPolicySet,
pinnedFrameUrl: "initial url"
)

try await fixtures.aliceClient.conversations.sync()
let aliceGroup = try await fixtures.aliceClient.conversations.groups().first!

let alicePermissionSet = try aliceGroup.permissionPolicySet()
XCTAssert(alicePermissionSet.addMemberPolicy == PermissionOption.admin)
XCTAssert(alicePermissionSet.removeMemberPolicy == PermissionOption.deny)
XCTAssert(alicePermissionSet.addAdminPolicy == PermissionOption.admin)
XCTAssert(alicePermissionSet.removeAdminPolicy == PermissionOption.superAdmin)
XCTAssert(alicePermissionSet.updateGroupNamePolicy == PermissionOption.admin)
XCTAssert(alicePermissionSet.updateGroupDescriptionPolicy == PermissionOption.allow)
XCTAssert(alicePermissionSet.updateGroupImagePolicy == PermissionOption.admin)
XCTAssert(alicePermissionSet.updateGroupPinnedFrameUrlPolicy == PermissionOption.deny)
}

func testCreateGroupWithInvalidPermissionsFails() async throws {
let fixtures = try await localFixtures()
// Add / remove admin can not be set to "allow"
let permissionPolicySetInvalid = PermissionPolicySet(
addMemberPolicy: PermissionOption.admin,
removeMemberPolicy: PermissionOption.deny,
addAdminPolicy: PermissionOption.allow,
removeAdminPolicy: PermissionOption.superAdmin,
updateGroupNamePolicy: PermissionOption.admin,
updateGroupDescriptionPolicy: PermissionOption.allow,
updateGroupImagePolicy: PermissionOption.admin,
updateGroupPinnedFrameUrlPolicy: PermissionOption.deny
)
await assertThrowsAsyncError(
try await fixtures.bobClient.conversations.newGroupCustomPermissions(
with: [fixtures.alice.walletAddress, fixtures.caro.walletAddress],
permissionPolicySet: permissionPolicySetInvalid,
pinnedFrameUrl: "initial url"
)
)
}
}
4 changes: 2 additions & 2 deletions XMTP.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pod::Spec.new do |spec|
#

spec.name = "XMTP"
spec.version = "0.13.8"
spec.version = "0.13.9"
spec.summary = "XMTP SDK Cocoapod"

# This description is used to generate tags and improve search results.
Expand Down Expand Up @@ -44,5 +44,5 @@ Pod::Spec.new do |spec|
spec.dependency "web3.swift"
spec.dependency "GzipSwift"
spec.dependency "Connect-Swift", "= 0.12.0"
spec.dependency 'LibXMTP', '= 0.5.6-beta0'
spec.dependency 'LibXMTP', '= 0.5.6-beta1'
end
Loading