summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2026-04-14 16:22:40 -0400
committerJosh Ferrell <josh@vector35.com>2026-05-05 14:46:15 -0400
commitaf50b06082044fcbbf730deda985d0133ca98b88 (patch)
tree6b1ae5a4678d8a39a88af4de2cd150663e1a9c8e
parente4db4f0704ea6e6b381e9322a336661dc23c3b5f (diff)
Switch collaboration permission checks to using User objects
-rw-r--r--binaryninjaapi.h17
-rw-r--r--binaryninjacore.h14
-rw-r--r--collaboration.cpp56
-rw-r--r--python/collaboration/group.py43
-rw-r--r--python/collaboration/project.py26
-rw-r--r--python/collaboration/remote.py12
-rw-r--r--rust/src/collaboration/group.rs44
-rw-r--r--rust/src/collaboration/project.rs28
-rw-r--r--rust/src/collaboration/remote.rs13
9 files changed, 125 insertions, 128 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index ac528db8..1dd3bc0f 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -5780,7 +5780,7 @@ namespace BinaryNinja {
void PerformDefineRelocation(Architecture* arch, BNRelocationInfo& info, Ref<Symbol> sym, uint64_t reloc);
/*! OnAfterSnapshotDataApplied is called when loading a view from a database, after snapshot data has been applied to it.
-
+
\note This method **may** be overridden by custom BinaryViews.
\warning This method **must not** be called directly.
@@ -22511,9 +22511,9 @@ namespace BinaryNinja::Collaboration
uint64_t GetId();
std::string GetName();
void SetName(const std::string& name);
- void SetUsernames(const std::vector<std::string>& usernames);
- bool ContainsUser(const std::string& username);
-
+ std::vector<Ref<CollabUser>> GetUsers();
+ void SetUsers(const std::vector<Ref<CollabUser>>& users);
+ bool ContainsUser(Ref<CollabUser> user);
};
/*!
@@ -22694,10 +22694,11 @@ namespace BinaryNinja::Collaboration
/*!
Create a new group on the remote (and pull it)
\param name Group name
+ \param users List of users in group
\return Reference to the created group
\throws RemoteException If there is an error in any request or if the remote is not connected
*/
- Ref<CollabGroup> CreateGroup(const std::string& name, const std::vector<std::string>& usernames);
+ Ref<CollabGroup> CreateGroup(const std::string& name, const std::vector<Ref<CollabUser>>& users = {});
/*!
@@ -23145,9 +23146,9 @@ namespace BinaryNinja::Collaboration
Ref<CollabPermission> CreateUserPermission(const std::string& userId, BNCollaborationPermissionLevel level, ProgressFunction progress = {});
void PushPermission(Ref<CollabPermission> permission, const std::vector<std::pair<std::string, std::string>>& extraFields = {});
void DeletePermission(Ref<CollabPermission> permission);
- bool CanUserView(const std::string& username);
- bool CanUserEdit(const std::string& username);
- bool CanUserAdmin(const std::string& username);
+ bool CanUserView(Ref<CollabUser> user);
+ bool CanUserEdit(Ref<CollabUser> user);
+ bool CanUserAdmin(Ref<CollabUser> user);
};
class AnalysisMergeConflict : public CoreRefCountObject<BNAnalysisMergeConflict, BNNewAnalysisMergeConflictReference, BNFreeAnalysisMergeConflict>
diff --git a/binaryninjacore.h b/binaryninjacore.h
index c5dcc7d4..f28f3c42 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -8607,7 +8607,7 @@ extern "C"
BINARYNINJACOREAPI BNCollaborationGroup* BNRemoteGetGroupByName(BNRemote* remote, const char* name);
BINARYNINJACOREAPI bool BNRemoteSearchGroups(BNRemote* remote, const char* prefix, uint64_t** groupIds, char*** groupNames, size_t* count);
BINARYNINJACOREAPI bool BNRemotePullGroups(BNRemote* remote, BNProgressFunction progress, void* progressContext);
- BINARYNINJACOREAPI BNCollaborationGroup* BNRemoteCreateGroup(BNRemote* remote, const char* name, const char** usernames, size_t usernameCount);
+ BINARYNINJACOREAPI BNCollaborationGroup* BNRemoteCreateGroup(BNRemote* remote, const char* name, BNCollaborationUser** users, size_t userCount);
BINARYNINJACOREAPI bool BNRemotePushGroup(BNRemote* remote, BNCollaborationGroup* group, const char** extraFieldKeys, const char** extraFieldValues, size_t extraFieldCount);
BINARYNINJACOREAPI bool BNRemoteDeleteGroup(BNRemote* remote, BNCollaborationGroup* group);
BINARYNINJACOREAPI BNCollaborationUser** BNRemoteGetUsers(BNRemote* remote, size_t* count);
@@ -8631,9 +8631,9 @@ extern "C"
BINARYNINJACOREAPI uint64_t BNCollaborationGroupGetId(BNCollaborationGroup* group);
BINARYNINJACOREAPI char* BNCollaborationGroupGetName(BNCollaborationGroup* group);
BINARYNINJACOREAPI void BNCollaborationGroupSetName(BNCollaborationGroup* group, const char* name);
- BINARYNINJACOREAPI bool BNCollaborationGroupGetUsers(BNCollaborationGroup* group, char*** userIds, char*** usernames, size_t* count);
- BINARYNINJACOREAPI bool BNCollaborationGroupSetUsernames(BNCollaborationGroup* group, const char** names, size_t count);
- BINARYNINJACOREAPI bool BNCollaborationGroupContainsUser(BNCollaborationGroup* group, const char* username);
+ BINARYNINJACOREAPI BNCollaborationUser** BNCollaborationGroupGetUsers(BNCollaborationGroup* group, size_t* count);
+ BINARYNINJACOREAPI bool BNCollaborationGroupSetUsers(BNCollaborationGroup* group, BNCollaborationUser** users, size_t count);
+ BINARYNINJACOREAPI bool BNCollaborationGroupContainsUser(BNCollaborationGroup* group, BNCollaborationUser* user);
// CollabUser
BINARYNINJACOREAPI BNCollaborationUser* BNNewCollaborationUserReference(BNCollaborationUser* user);
@@ -8696,9 +8696,9 @@ extern "C"
BINARYNINJACOREAPI BNCollaborationPermission* BNRemoteProjectCreateUserPermission(BNRemoteProject* project, const char* userId, BNCollaborationPermissionLevel level, BNProgressFunction progress, void* progressContext);
BINARYNINJACOREAPI bool BNRemoteProjectPushPermission(BNRemoteProject* project, BNCollaborationPermission* permission, const char** extraFieldKeys, const char** extraFieldValues, size_t extraFieldCount);
BINARYNINJACOREAPI bool BNRemoteProjectDeletePermission(BNRemoteProject* project, BNCollaborationPermission* permission);
- BINARYNINJACOREAPI bool BNRemoteProjectCanUserView(BNRemoteProject* project, const char* username);
- BINARYNINJACOREAPI bool BNRemoteProjectCanUserEdit(BNRemoteProject* project, const char* username);
- BINARYNINJACOREAPI bool BNRemoteProjectCanUserAdmin(BNRemoteProject* project, const char* username);
+ BINARYNINJACOREAPI bool BNRemoteProjectCanUserView(BNRemoteProject* project, BNCollaborationUser* user);
+ BINARYNINJACOREAPI bool BNRemoteProjectCanUserEdit(BNRemoteProject* project, BNCollaborationUser* user);
+ BINARYNINJACOREAPI bool BNRemoteProjectCanUserAdmin(BNRemoteProject* project, BNCollaborationUser* user);
// RemoteFile
BINARYNINJACOREAPI BNRemoteFile* BNNewRemoteFileReference(BNRemoteFile* file);
diff --git a/collaboration.cpp b/collaboration.cpp
index 14274164..15000cda 100644
--- a/collaboration.cpp
+++ b/collaboration.cpp
@@ -878,16 +878,16 @@ void Remote::PullGroups(ProgressFunction progress)
}
-Ref<CollabGroup> Remote::CreateGroup(const std::string& name, const std::vector<std::string>& usernames)
+Ref<CollabGroup> Remote::CreateGroup(const std::string& name, const std::vector<Ref<CollabUser>>& users)
{
- const char** cstrNames = new const char*[usernames.size()];
- for (size_t i = 0; i < usernames.size(); i++)
+ BNCollaborationUser** cUsers = new BNCollaborationUser*[users.size()];
+ for (size_t i = 0; i < users.size(); i++)
{
- cstrNames[i] = usernames[i].c_str();
+ cUsers[i] = users[i]->m_object;
}
- BNCollaborationGroup* group = BNRemoteCreateGroup(m_object, name.c_str(), cstrNames, usernames.size());
- delete[] cstrNames;
+ BNCollaborationGroup* group = BNRemoteCreateGroup(m_object, name.c_str(), cUsers, users.size());
+ delete[] cUsers;
if (!group)
return nullptr;
return new CollabGroup(group);
@@ -1076,22 +1076,38 @@ void CollabGroup::SetName(const std::string& name)
}
-void CollabGroup::SetUsernames(const std::vector<std::string>& usernames)
+std::vector<Ref<CollabUser>> CollabGroup::GetUsers()
{
- const char** cNames = new const char*[usernames.size()];
- for (size_t i = 0; i < usernames.size(); i++)
+ size_t count = 0;
+ BNCollaborationUser** users = BNCollaborationGroupGetUsers(m_object, &count);
+ std::vector<Ref<CollabUser>> out;
+ out.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ {
+ out.push_back(new CollabUser(BNNewCollaborationUserReference(users[i])));
+ }
+ BNFreeCollaborationUserList(users, count);
+ return out;
+}
+
+
+void CollabGroup::SetUsers(const std::vector<Ref<CollabUser>>& users)
+{
+ size_t count = users.size();
+ BNCollaborationUser** cUsers = new BNCollaborationUser*[count];
+ for (size_t i = 0; i < count; i++)
{
- cNames[i] = usernames[i].c_str();
+ cUsers[i] = users[i]->m_object;
}
- BNCollaborationGroupSetUsernames(m_object, cNames, usernames.size());
- delete[] cNames;
+ BNCollaborationGroupSetUsers(m_object, cUsers, count);
+ delete[] cUsers;
}
-bool CollabGroup::ContainsUser(const std::string& username)
+bool CollabGroup::ContainsUser(Ref<CollabUser> user)
{
- return BNCollaborationGroupContainsUser(m_object, username.c_str());
+ return BNCollaborationGroupContainsUser(m_object, user->m_object);
}
@@ -1566,21 +1582,21 @@ void RemoteProject::DeletePermission(Ref<CollabPermission> permission)
}
-bool RemoteProject::CanUserView(const std::string& username)
+bool RemoteProject::CanUserView(Ref<CollabUser> user)
{
- return BNRemoteProjectCanUserView(m_object, username.c_str());
+ return BNRemoteProjectCanUserView(m_object, user->m_object);
}
-bool RemoteProject::CanUserEdit(const std::string& username)
+bool RemoteProject::CanUserEdit(Ref<CollabUser> user)
{
- return BNRemoteProjectCanUserEdit(m_object, username.c_str());
+ return BNRemoteProjectCanUserEdit(m_object, user->m_object);
}
-bool RemoteProject::CanUserAdmin(const std::string& username)
+bool RemoteProject::CanUserAdmin(Ref<CollabUser> user)
{
- return BNRemoteProjectCanUserAdmin(m_object, username.c_str());
+ return BNRemoteProjectCanUserAdmin(m_object, user->m_object);
}
diff --git a/python/collaboration/group.py b/python/collaboration/group.py
index d1fbd9d0..967e52f1 100644
--- a/python/collaboration/group.py
+++ b/python/collaboration/group.py
@@ -2,7 +2,7 @@ import ctypes
from typing import List, Tuple
from .. import _binaryninjacore as core
-from . import remote, util
+from . import remote, user, util
class Group:
@@ -70,43 +70,40 @@ class Group:
core.BNCollaborationGroupSetName(self._handle, name)
@property
- def users(self) -> List[Tuple[str, str]]:
+ def users(self) -> List[user.User]:
"""
Get list of users in the group
- :return: List of (userid, username) pairs
+ :return: List of users
"""
count = ctypes.c_size_t()
- user_ids = ctypes.POINTER(ctypes.c_char_p)()
- usernames = ctypes.POINTER(ctypes.c_char_p)()
- if not core.BNCollaborationGroupGetUsers(self._handle, user_ids, usernames, count):
+ result = core.BNCollaborationGroupGetUsers(self._handle, count)
+ if not result:
raise RuntimeError(util._last_error())
- result = []
+ out = []
for i in range(count.value):
- result.append((core.pyNativeStr(user_ids[i]), core.pyNativeStr(usernames[i])))
- core.BNFreeStringList(user_ids, count.value)
- core.BNFreeStringList(usernames, count.value)
- return result
+ out.append(user.User(result[i]))
+ return out
@users.setter
- def users(self, usernames: List[str]):
+ def users(self, users: List[user.User]):
"""
- Set the list of users in a group by their usernames.
+ Set the list of users in a group.
You will need to push the group to update the Remote.
- :param usernames: Usernames of new group members
+ :param users: New group members
"""
- array = (ctypes.c_char_p * len(usernames))()
- for i in range(len(usernames)):
- array[i] = core.cstr(usernames[i])
- if not core.BNCollaborationGroupSetUsernames(self._handle, array, len(usernames)):
+ array = ctypes.POINTER(core.BNCollaborationUserHandle)()
+ for i in range(len(users)):
+ array[i] = users[i]._handle
+ if not core.BNCollaborationGroupSetUsers(self._handle, array, len(users)):
raise RuntimeError(util._last_error())
- def contains_user(self, username: str) -> bool:
+ def contains_user(self, user: user.User) -> bool:
"""
- Test if a group has a user with the given username
+ Test if a group contains a user
- :param username: Username of user to check membership
- :return: If the user is in the group
+ :param user: User to check membership of
+ :return: If the group contains the user
"""
- return core.BNCollaborationGroupContainsUser(self._handle, username)
+ return core.BNCollaborationGroupContainsUser(self._handle, user._handle)
diff --git a/python/collaboration/project.py b/python/collaboration/project.py
index a143e6d9..f78e488e 100644
--- a/python/collaboration/project.py
+++ b/python/collaboration/project.py
@@ -11,7 +11,7 @@ from ..binaryview import BinaryView, ProgressFuncType
from ..database import Database
from ..filemetadata import FileMetadata
from ..project import Project
-from . import databasesync, file, folder, permission, remote, util
+from . import databasesync, file, folder, permission, remote, user, util
def _nop(*args, **kwargs):
@@ -713,35 +713,35 @@ class RemoteProject:
if not core.BNRemoteProjectDeletePermission(self._handle, permission._handle):
raise RuntimeError(util._last_error())
- def can_user_view(self, username: str) -> bool:
+ def can_user_view(self, user: user.User) -> bool:
"""
Determine if a user is in any of the view/edit/admin groups
- :param username: Username of user to check
- :return: True if they are in any of those groups
+ :param user: User to check
+ :return: True if the user has view permission (either directly or from a group)
:raises: RuntimeError if there was an error
"""
- return core.BNRemoteProjectCanUserView(self._handle, username)
+ return core.BNRemoteProjectCanUserView(self._handle, user._handle)
- def can_user_edit(self, username: str) -> bool:
+ def can_user_edit(self, user: user.User) -> bool:
"""
Determine if a user is in any of the edit/admin groups
- :param username: Username of user to check
- :return: True if they are in any of those groups
+ :param user: User to check
+ :return: True if the user has edit permission (either directly or from a group)
:raises: RuntimeError if there was an error
"""
- return core.BNRemoteProjectCanUserEdit(self._handle, username)
+ return core.BNRemoteProjectCanUserEdit(self._handle, user._handle)
- def can_user_admin(self, username: str) -> bool:
+ def can_user_admin(self, user: user.User) -> bool:
"""
Determine if a user is in the admin group
- :param username: Username of user to check
- :return: True if they are in any of those groups
+ :param user: User to check
+ :return: True if the user has admin permission (either directly or from a group)
:raises: RuntimeError if there was an error
"""
- return core.BNRemoteProjectCanUserAdmin(self._handle, username)
+ return core.BNRemoteProjectCanUserAdmin(self._handle, user._handle)
def upload_new_file(
self,
diff --git a/python/collaboration/remote.py b/python/collaboration/remote.py
index 811fd33b..1cbdb424 100644
--- a/python/collaboration/remote.py
+++ b/python/collaboration/remote.py
@@ -520,22 +520,22 @@ class Remote:
if not core.BNRemotePullGroups(self._handle, util.wrap_progress(progress), None):
raise RuntimeError(util._last_error())
- def create_group(self, name: str, usernames: List[str]) -> 'group.Group':
+ def create_group(self, name: str, users: List[user.User]) -> 'group.Group':
"""
Create a new group on the remote (and pull it)
.. note:: This function is only available to accounts with admin status on the Remote
:param name: Group name
- :param usernames: List of usernames of users in the group
+ :param users: List of users in the group
:return: Reference to the created group
:raises: RuntimeError if there was an error
"""
- c_usernames = (ctypes.c_char_p * len(usernames))()
- for (i, username) in enumerate(usernames):
- c_usernames[i] = core.cstr(username)
+ c_users = (core.BNCollaborationUserHandle * len(users))()
+ for (i, member) in enumerate(users):
+ c_users[i] = member._handle
- value = core.BNRemoteCreateGroup(self._handle, name, c_usernames, len(usernames))
+ value = core.BNRemoteCreateGroup(self._handle, name, c_users, len(users))
if value is None:
raise RuntimeError(util._last_error())
return group.Group(value)
diff --git a/rust/src/collaboration/group.rs b/rust/src/collaboration/group.rs
index 01f92169..e3ee82d0 100644
--- a/rust/src/collaboration/group.rs
+++ b/rust/src/collaboration/group.rs
@@ -1,4 +1,5 @@
use super::Remote;
+use crate::collaboration::RemoteUser;
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
use crate::string::{BnString, IntoCStr};
use binaryninjacore_sys::*;
@@ -55,55 +56,40 @@ impl RemoteGroup {
}
/// Get list of users in the group
- pub fn users(&self) -> Result<(Array<BnString>, Array<BnString>), ()> {
- let mut usernames = std::ptr::null_mut();
- let mut user_ids = std::ptr::null_mut();
+ pub fn users(&self) -> Result<Array<RemoteUser>, ()> {
let mut count = 0;
// TODO: This should only fail if collaboration is not supported.
// TODO: Because you should not have a RemoteGroup at that point we can ignore?
- let success = unsafe {
- BNCollaborationGroupGetUsers(
- self.handle.as_ptr(),
- &mut user_ids,
- &mut usernames,
- &mut count,
- )
- };
- success
- .then(|| unsafe {
- let ids = Array::new(user_ids, count, ());
- let users = Array::new(usernames, count, ());
- (ids, users)
- })
+ let result = unsafe { BNCollaborationGroupGetUsers(self.handle.as_ptr(), &mut count) };
+ (!result.is_null())
+ .then(|| unsafe { Array::new(result, count, ()) })
.ok_or(())
}
// TODO: Are any permissions required to the set the remote group users?
- /// Set the list of users in a group by their usernames.
+ /// Set the list of users in a group.
/// You will need to push the group to update the Remote.
- pub fn set_users<I>(&self, usernames: I) -> Result<(), ()>
+ pub fn set_users<I>(&self, users: I) -> Result<(), ()>
where
- I: IntoIterator<Item = String>,
+ I: IntoIterator<Item = Ref<RemoteUser>>,
{
- let usernames: Vec<_> = usernames.into_iter().map(|u| u.to_cstr()).collect();
- let mut usernames_raw: Vec<_> = usernames.iter().map(|s| s.as_ptr()).collect();
+ let mut users_raw: Vec<_> = users.into_iter().map(|s| s.handle.as_ptr()).collect();
// TODO: This should only fail if collaboration is not supported.
// TODO: Because you should not have a RemoteGroup at that point we can ignore?
// TODO: Do you need any permissions to do this?
let success = unsafe {
- BNCollaborationGroupSetUsernames(
+ BNCollaborationGroupSetUsers(
self.handle.as_ptr(),
- usernames_raw.as_mut_ptr(),
- usernames_raw.len(),
+ users_raw.as_mut_ptr(),
+ users_raw.len(),
)
};
success.then_some(()).ok_or(())
}
- /// Test if a group has a user with the given username
- pub fn contains_user(&self, username: &str) -> bool {
- let username = username.to_cstr();
- unsafe { BNCollaborationGroupContainsUser(self.handle.as_ptr(), username.as_ptr()) }
+ /// Test if a group contains a user
+ pub fn contains_user(&self, user: Ref<RemoteUser>) -> bool {
+ unsafe { BNCollaborationGroupContainsUser(self.handle.as_ptr(), user.handle.as_ptr()) }
}
}
diff --git a/rust/src/collaboration/project.rs b/rust/src/collaboration/project.rs
index cfcc1db4..3a24ea8b 100644
--- a/rust/src/collaboration/project.rs
+++ b/rust/src/collaboration/project.rs
@@ -12,6 +12,7 @@ use super::{
};
use crate::binary_view::{BinaryView, BinaryViewExt};
+use crate::collaboration::RemoteUser;
use crate::database::Database;
use crate::file_metadata::FileMetadata;
use crate::progress::{NoProgressCallback, ProgressCallback};
@@ -761,34 +762,31 @@ impl RemoteProject {
success.then_some(()).ok_or(())
}
- /// Determine if a user is in any of the view/edit/admin groups.
+ /// Determine if a user has view permission (either directly or from a group)
///
/// # Arguments
///
- /// * `username` - Username of user to check
- pub fn can_user_view(&self, username: &str) -> bool {
- let username = username.to_cstr();
- unsafe { BNRemoteProjectCanUserView(self.handle.as_ptr(), username.as_ptr()) }
+ /// * `user` - User to check
+ pub fn can_user_view(&self, user: Ref<RemoteUser>) -> bool {
+ unsafe { BNRemoteProjectCanUserView(self.handle.as_ptr(), user.handle.as_ptr()) }
}
- /// Determine if a user is in any of the edit/admin groups.
+ /// Determine if a user has edit permission (either directly or from a group)
///
/// # Arguments
///
- /// * `username` - Username of user to check
- pub fn can_user_edit(&self, username: &str) -> bool {
- let username = username.to_cstr();
- unsafe { BNRemoteProjectCanUserEdit(self.handle.as_ptr(), username.as_ptr()) }
+ /// * `user` - User to check
+ pub fn can_user_edit(&self, user: Ref<RemoteUser>) -> bool {
+ unsafe { BNRemoteProjectCanUserEdit(self.handle.as_ptr(), user.handle.as_ptr()) }
}
- /// Determine if a user is in the admin group.
+ /// Determine if a user has admin permission (either directly or from a group)
///
/// # Arguments
///
- /// * `username` - Username of user to check
- pub fn can_user_admin(&self, username: &str) -> bool {
- let username = username.to_cstr();
- unsafe { BNRemoteProjectCanUserAdmin(self.handle.as_ptr(), username.as_ptr()) }
+ /// * `user` - User to check
+ pub fn can_user_admin(&self, user: Ref<RemoteUser>) -> bool {
+ unsafe { BNRemoteProjectCanUserAdmin(self.handle.as_ptr(), user.handle.as_ptr()) }
}
/// Get the default directory path for a remote Project. This is based off
diff --git a/rust/src/collaboration/remote.rs b/rust/src/collaboration/remote.rs
index 03c808bc..22e65245 100644
--- a/rust/src/collaboration/remote.rs
+++ b/rust/src/collaboration/remote.rs
@@ -515,21 +515,20 @@ impl Remote {
/// # Arguments
///
/// * `name` - Group name
- /// * `usernames` - List of usernames of users in the group
- pub fn create_group<I>(&self, name: &str, usernames: I) -> Result<Ref<RemoteGroup>, ()>
+ /// * `users` - List of users in the group
+ pub fn create_group<I>(&self, name: &str, users: I) -> Result<Ref<RemoteGroup>, ()>
where
- I: IntoIterator<Item = String>,
+ I: IntoIterator<Item = Ref<RemoteUser>>,
{
let name = name.to_cstr();
- let usernames: Vec<_> = usernames.into_iter().map(|s| s.to_cstr()).collect();
- let mut username_ptrs: Vec<_> = usernames.iter().map(|s| s.as_ptr()).collect();
+ let mut user_ptrs: Vec<_> = users.into_iter().map(|s| s.handle.as_ptr()).collect();
let value = unsafe {
BNRemoteCreateGroup(
self.handle.as_ptr(),
name.as_ptr(),
- username_ptrs.as_mut_ptr(),
- username_ptrs.len(),
+ user_ptrs.as_mut_ptr(),
+ user_ptrs.len(),
)
};
NonNull::new(value)