Skip to main content

localauthentication/
la_right.rs

1//! `LARight` wrappers.
2
3use crate::ffi;
4use crate::la_authentication_requirement::LAAuthenticationRequirement;
5use crate::la_error::{LAError, Result};
6use crate::private::{bridge_i32, bridge_i64, bridge_ptr, bridge_unit, cstring, OwnedHandle};
7
8/// Possible authorization states for a `LARight`.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10#[non_exhaustive]
11pub enum LARightState {
12    Unknown,
13    Authorizing,
14    Authorized,
15    NotAuthorized,
16    UnknownValue(i32),
17}
18
19impl LARightState {
20    #[must_use]
21    pub const fn from_ffi(value: i32) -> Self {
22        match value {
23            ffi::la_right::STATE_UNKNOWN => Self::Unknown,
24            ffi::la_right::STATE_AUTHORIZING => Self::Authorizing,
25            ffi::la_right::STATE_AUTHORIZED => Self::Authorized,
26            ffi::la_right::STATE_NOT_AUTHORIZED => Self::NotAuthorized,
27            other => Self::UnknownValue(other),
28        }
29    }
30}
31
32/// Managed wrapper around Apple's `LARight`.
33#[derive(Debug)]
34pub struct LARight {
35    handle: OwnedHandle,
36}
37
38impl LARight {
39    pub(crate) const fn as_ptr(&self) -> *mut core::ffi::c_void {
40        self.handle.as_ptr()
41    }
42
43    /// Create a right with the framework's default authentication requirement.
44    ///
45    /// # Errors
46    ///
47    /// Returns an error if the API is unavailable or the Swift bridge rejects the request.
48    pub fn new() -> Result<Self> {
49        let raw =
50            bridge_ptr(|out, error_out| unsafe { ffi::la_right::la_right_new(out, error_out) })?;
51        Ok(Self {
52            handle: OwnedHandle::new(raw, ffi::la_right::la_right_release),
53        })
54    }
55
56    /// Create a right with an explicit authentication requirement.
57    ///
58    /// # Errors
59    ///
60    /// Returns an error if the API is unavailable or the Swift bridge rejects the request.
61    pub fn new_with_requirement(requirement: &LAAuthenticationRequirement) -> Result<Self> {
62        let raw = bridge_ptr(|out, error_out| unsafe {
63            ffi::la_right::la_right_new_with_requirement(requirement.as_ptr(), out, error_out)
64        })?;
65        Ok(Self {
66            handle: OwnedHandle::new(raw, ffi::la_right::la_right_release),
67        })
68    }
69
70    /// The current authorization state.
71    ///
72    /// # Errors
73    ///
74    /// Returns an error if the Swift bridge rejects the request.
75    pub fn state(&self) -> Result<LARightState> {
76        let raw = bridge_i32(|out, error_out| unsafe {
77            ffi::la_right::la_right_get_state(self.handle.as_ptr(), out, error_out)
78        })?;
79        Ok(LARightState::from_ffi(raw))
80    }
81
82    /// Application-controlled integer tag.
83    ///
84    /// # Errors
85    ///
86    /// Returns an error if the Swift bridge rejects the request.
87    pub fn tag(&self) -> Result<i64> {
88        bridge_i64(|out, error_out| unsafe {
89            ffi::la_right::la_right_get_tag(self.handle.as_ptr(), out, error_out)
90        })
91    }
92
93    /// Update the application-controlled integer tag.
94    ///
95    /// # Errors
96    ///
97    /// Returns an error if the Swift bridge rejects the request.
98    pub fn set_tag(&self, tag: i64) -> Result<()> {
99        bridge_unit(|error_out| unsafe {
100            ffi::la_right::la_right_set_tag(self.handle.as_ptr(), tag, error_out)
101        })
102    }
103
104    /// Attempt to authorize the right.
105    ///
106    /// # Errors
107    ///
108    /// Returns a mapped framework or bridge error when authorization fails.
109    pub fn authorize(&self, localized_reason: &str) -> Result<()> {
110        if localized_reason.is_empty() {
111            return Err(LAError::InvalidArgument(
112                "localized reason must not be empty".to_owned(),
113            ));
114        }
115        let localized_reason = cstring(localized_reason)?;
116        bridge_unit(|error_out| unsafe {
117            ffi::la_right::la_right_authorize(
118                self.handle.as_ptr(),
119                localized_reason.as_ptr(),
120                error_out,
121            )
122        })
123    }
124
125    /// Preflight whether the right can eventually be authorized.
126    ///
127    /// # Errors
128    ///
129    /// Returns a mapped framework or bridge error when authorization is not possible.
130    pub fn check_can_authorize(&self) -> Result<()> {
131        bridge_unit(|error_out| unsafe {
132            ffi::la_right::la_right_check_can_authorize(self.handle.as_ptr(), error_out)
133        })
134    }
135
136    /// Deauthorize the right.
137    ///
138    /// # Errors
139    ///
140    /// Returns an error if the Swift bridge rejects the request.
141    pub fn deauthorize(&self) -> Result<()> {
142        bridge_unit(|error_out| unsafe {
143            ffi::la_right::la_right_deauthorize(self.handle.as_ptr(), error_out)
144        })
145    }
146}