binaryninja/collaboration/
permission.rs

1use super::{GroupId, Remote, RemoteProject};
2use binaryninjacore_sys::*;
3use std::ptr::NonNull;
4
5use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
6use crate::string::BnString;
7
8pub type CollaborationPermissionLevel = BNCollaborationPermissionLevel;
9
10/// Struct representing a permission grant for a user or group on a project.
11#[repr(transparent)]
12pub struct Permission {
13    pub(crate) handle: NonNull<BNCollaborationPermission>,
14}
15
16impl Permission {
17    pub(crate) unsafe fn from_raw(handle: NonNull<BNCollaborationPermission>) -> Self {
18        Self { handle }
19    }
20
21    pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNCollaborationPermission>) -> Ref<Self> {
22        Ref::new(Self { handle })
23    }
24
25    pub fn remote(&self) -> Result<Ref<Remote>, ()> {
26        let result = unsafe { BNCollaborationPermissionGetRemote(self.handle.as_ptr()) };
27        NonNull::new(result)
28            .map(|handle| unsafe { Remote::ref_from_raw(handle) })
29            .ok_or(())
30    }
31
32    pub fn project(&self) -> Result<Ref<RemoteProject>, ()> {
33        let result = unsafe { BNCollaborationPermissionGetProject(self.handle.as_ptr()) };
34        NonNull::new(result)
35            .map(|handle| unsafe { RemoteProject::ref_from_raw(handle) })
36            .ok_or(())
37    }
38
39    /// Web api endpoint url
40    pub fn url(&self) -> String {
41        let value = unsafe { BNCollaborationPermissionGetUrl(self.handle.as_ptr()) };
42        assert!(!value.is_null());
43        unsafe { BnString::into_string(value) }
44    }
45
46    /// unique id
47    pub fn id(&self) -> String {
48        let value = unsafe { BNCollaborationPermissionGetId(self.handle.as_ptr()) };
49        assert!(!value.is_null());
50        unsafe { BnString::into_string(value) }
51    }
52
53    /// Level of permission
54    pub fn level(&self) -> CollaborationPermissionLevel {
55        unsafe { BNCollaborationPermissionGetLevel(self.handle.as_ptr()) }
56    }
57
58    /// Change the level of the permission
59    /// You will need to push the group to update the Remote.
60    pub fn set_level(&self, level: CollaborationPermissionLevel) {
61        unsafe { BNCollaborationPermissionSetLevel(self.handle.as_ptr(), level) }
62    }
63
64    /// Id of affected group
65    pub fn group_id(&self) -> Option<GroupId> {
66        let value = unsafe { BNCollaborationPermissionGetGroupId(self.handle.as_ptr()) };
67        if value != 0 {
68            Some(GroupId(value))
69        } else {
70            None
71        }
72    }
73
74    /// Name of affected group
75    pub fn group_name(&self) -> Option<BnString> {
76        let value = unsafe { BNCollaborationPermissionGetGroupName(self.handle.as_ptr()) };
77        assert!(!value.is_null());
78        let result = unsafe { BnString::from_raw(value) };
79        (!result.is_empty()).then_some(result)
80    }
81
82    /// Id of affected user
83    pub fn user_id(&self) -> Option<BnString> {
84        let value = unsafe { BNCollaborationPermissionGetUserId(self.handle.as_ptr()) };
85        assert!(!value.is_null());
86        let result = unsafe { BnString::from_raw(value) };
87        (!result.is_empty()).then_some(result)
88    }
89
90    /// Name of affected user
91    pub fn username(&self) -> Option<BnString> {
92        let value = unsafe { BNCollaborationPermissionGetUsername(self.handle.as_ptr()) };
93        assert!(!value.is_null());
94        let result = unsafe { BnString::from_raw(value) };
95        (!result.is_empty()).then_some(result)
96    }
97
98    /// If the permission grants the affect user/group the ability to read files in the project
99    pub fn can_view(&self) -> bool {
100        unsafe { BNCollaborationPermissionCanView(self.handle.as_ptr()) }
101    }
102
103    /// If the permission grants the affect user/group the ability to edit files in the project
104    pub fn can_edit(&self) -> bool {
105        unsafe { BNCollaborationPermissionCanEdit(self.handle.as_ptr()) }
106    }
107
108    /// If the permission grants the affect user/group the ability to administer the project
109    pub fn can_admin(&self) -> bool {
110        unsafe { BNCollaborationPermissionCanAdmin(self.handle.as_ptr()) }
111    }
112}
113
114impl PartialEq for Permission {
115    fn eq(&self, other: &Self) -> bool {
116        self.id() == other.id()
117    }
118}
119impl Eq for Permission {}
120
121impl ToOwned for Permission {
122    type Owned = Ref<Self>;
123
124    fn to_owned(&self) -> Self::Owned {
125        unsafe { RefCountable::inc_ref(self) }
126    }
127}
128
129unsafe impl RefCountable for Permission {
130    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
131        Ref::new(Self {
132            handle: NonNull::new(BNNewCollaborationPermissionReference(
133                handle.handle.as_ptr(),
134            ))
135            .unwrap(),
136        })
137    }
138
139    unsafe fn dec_ref(handle: &Self) {
140        BNFreeCollaborationPermission(handle.handle.as_ptr());
141    }
142}
143
144impl CoreArrayProvider for Permission {
145    type Raw = *mut BNCollaborationPermission;
146    type Context = ();
147    type Wrapped<'a> = Guard<'a, Self>;
148}
149
150unsafe impl CoreArrayProviderInner for Permission {
151    unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
152        BNFreeCollaborationPermissionList(raw, count)
153    }
154
155    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
156        let raw_ptr = NonNull::new(*raw).unwrap();
157        Guard::new(Self::from_raw(raw_ptr), context)
158    }
159}