security/
authorization.rs1use bitflags::bitflags;
2use serde_json::Value;
3
4use crate::bridge;
5use crate::error::Result;
6
7bitflags! {
8 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9 pub struct AuthorizationOptions: u32 {
11 const DEFAULTS = 0;
13 const INTERACTION_ALLOWED = 1 << 0;
15 const EXTEND_RIGHTS = 1 << 1;
17 const PARTIAL_RIGHTS = 1 << 2;
19 const DESTROY_RIGHTS = 1 << 3;
21 const PREAUTHORIZE = 1 << 4;
23 const SKIP_INTERNAL_AUTH = 1 << 9;
25 const NO_DATA = 1 << 20;
27 }
28}
29
30#[derive(Debug)]
31pub struct Authorization {
33 handle: bridge::Handle,
34}
35
36impl Authorization {
37 #[cfg(feature = "async")]
38 pub(crate) fn as_ptr(&self) -> *mut std::ffi::c_void {
39 self.handle.as_ptr()
40 }
41
42 pub fn new() -> Result<Self> {
44 Self::with_options(AuthorizationOptions::DEFAULTS)
45 }
46
47 pub fn with_options(options: AuthorizationOptions) -> Result<Self> {
49 let mut status = 0;
50 let mut error = std::ptr::null_mut();
51 let raw = unsafe {
52 bridge::security_authorization_create(options.bits(), &mut status, &mut error)
53 };
54 bridge::required_handle("security_authorization_create", raw, status, error)
55 .map(|handle| Self { handle })
56 }
57
58 pub fn external_form(&self) -> Result<Vec<u8>> {
60 let mut status = 0;
61 let mut error = std::ptr::null_mut();
62 let raw = unsafe {
63 bridge::security_authorization_make_external_form(
64 self.handle.as_ptr(),
65 &mut status,
66 &mut error,
67 )
68 };
69 bridge::required_data(
70 "security_authorization_make_external_form",
71 raw,
72 status,
73 error,
74 )
75 }
76
77 pub fn from_external_form(external_form: &[u8]) -> Result<Self> {
79 let mut status = 0;
80 let mut error = std::ptr::null_mut();
81 let raw = unsafe {
82 bridge::security_authorization_create_from_external_form(
83 external_form.as_ptr().cast(),
84 bridge::len_to_isize(external_form.len())?,
85 &mut status,
86 &mut error,
87 )
88 };
89 bridge::required_handle(
90 "security_authorization_create_from_external_form",
91 raw,
92 status,
93 error,
94 )
95 .map(|handle| Self { handle })
96 }
97
98 pub fn copy_info(&self, tag: Option<&str>) -> Result<Value> {
100 let tag = tag.map(bridge::cstring).transpose()?;
101 let mut status = 0;
102 let mut error = std::ptr::null_mut();
103 let raw = unsafe {
104 bridge::security_authorization_copy_info(
105 self.handle.as_ptr(),
106 tag.as_ref()
107 .map_or(std::ptr::null(), |value| value.as_ptr()),
108 &mut status,
109 &mut error,
110 )
111 };
112 bridge::required_json("security_authorization_copy_info", raw, status, error)
113 }
114
115 pub fn copy_rights(&self, rights: &[&str], options: AuthorizationOptions) -> Result<Value> {
117 let rights_json = bridge::json_cstring(&rights)?;
118 let mut status = 0;
119 let mut error = std::ptr::null_mut();
120 let raw = unsafe {
121 bridge::security_authorization_copy_rights(
122 self.handle.as_ptr(),
123 rights_json.as_ptr(),
124 options.bits(),
125 &mut status,
126 &mut error,
127 )
128 };
129 bridge::required_json("security_authorization_copy_rights", raw, status, error)
130 }
131
132 pub fn copy_rights_async(
134 &self,
135 rights: &[&str],
136 options: AuthorizationOptions,
137 ) -> Result<Value> {
138 let rights_json = bridge::json_cstring(&rights)?;
139 let mut status = 0;
140 let mut error = std::ptr::null_mut();
141 let raw = unsafe {
142 bridge::security_authorization_copy_rights_async(
143 self.handle.as_ptr(),
144 rights_json.as_ptr(),
145 options.bits(),
146 &mut status,
147 &mut error,
148 )
149 };
150 bridge::required_json(
151 "security_authorization_copy_rights_async",
152 raw,
153 status,
154 error,
155 )
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn defaults_are_empty() {
165 assert!(AuthorizationOptions::DEFAULTS.is_empty());
166 assert_eq!(AuthorizationOptions::DEFAULTS.bits(), 0);
167 }
168
169 #[test]
170 fn authorization_options_round_trip_through_bits() {
171 let options = AuthorizationOptions::INTERACTION_ALLOWED
172 | AuthorizationOptions::EXTEND_RIGHTS
173 | AuthorizationOptions::PREAUTHORIZE;
174
175 assert_eq!(
176 AuthorizationOptions::from_bits(options.bits()),
177 Some(options)
178 );
179 }
180
181 #[test]
182 fn authorization_options_keep_sparse_bits() {
183 let options = AuthorizationOptions::SKIP_INTERNAL_AUTH | AuthorizationOptions::NO_DATA;
184
185 assert!(options.contains(AuthorizationOptions::SKIP_INTERNAL_AUTH));
186 assert!(options.contains(AuthorizationOptions::NO_DATA));
187 assert_eq!(options.bits(), (1 << 9) | (1 << 20));
188 }
189}