Skip to main content

bitwarden_emergency_access/
get.rs

1use bitwarden_core::{ApiError, MissingFieldError};
2use bitwarden_error::bitwarden_error;
3use thiserror::Error;
4
5use crate::{EmergencyAccessClient, EmergencyAccessId, GranteeEmergencyAccess};
6
7/// Errors returned when fetching an emergency access.
8#[bitwarden_error(flat)]
9#[derive(Debug, Error)]
10pub enum EmergencyAccessGetError {
11    /// The request to the server failed.
12    #[error(transparent)]
13    Api(#[from] ApiError),
14    /// A required field was missing from the server response.
15    #[error(transparent)]
16    MissingField(#[from] MissingFieldError),
17}
18
19#[bitwarden_ffi::wasm_export]
20impl EmergencyAccessClient {
21    /// Fetches an emergency access the current user granted.
22    ///
23    /// Called by the grantor.
24    pub async fn get(
25        &self,
26        emergency_access_id: EmergencyAccessId,
27    ) -> Result<GranteeEmergencyAccess, EmergencyAccessGetError> {
28        let response = self
29            .api_configurations
30            .api_client
31            .emergency_access_api()
32            .get(emergency_access_id.into())
33            .await?;
34
35        Ok(response.try_into()?)
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use bitwarden_api_api::models::{
42        EmergencyAccessGranteeDetailsResponseModel, EmergencyAccessStatusType,
43        EmergencyAccessType as ApiEmergencyAccessType,
44    };
45    use bitwarden_core::client::test_accounts::test_bitwarden_com_account;
46
47    use super::*;
48    use crate::{
49        EmergencyAccessClientExt, EmergencyAccessStatus, EmergencyAccessType,
50        test_support::{TEST_EMERGENCY_ACCESS_ID, api_error, is_test_id, test_client, test_id},
51    };
52
53    async fn get(
54        response: EmergencyAccessGranteeDetailsResponseModel,
55    ) -> Result<GranteeEmergencyAccess, EmergencyAccessGetError> {
56        let client = test_client(test_bitwarden_com_account(), move |mock| {
57            mock.emergency_access_api
58                .expect_get()
59                .withf(is_test_id)
60                .returning(move |_| Ok(response.clone()))
61                .once();
62        })
63        .await;
64
65        client.emergency_access().get(test_id()).await
66    }
67
68    #[tokio::test]
69    async fn maps_emergency_access() {
70        let response = EmergencyAccessGranteeDetailsResponseModel {
71            id: Some(TEST_EMERGENCY_ACCESS_ID.parse().unwrap()),
72            status: Some(EmergencyAccessStatusType::Accepted),
73            r#type: Some(ApiEmergencyAccessType::View),
74            wait_time_days: Some(3),
75            email: Some("[email protected]".to_owned()),
76            ..Default::default()
77        };
78
79        let result = get(response).await.unwrap();
80
81        assert_eq!(result.id, test_id());
82        assert_eq!(result.r#type, EmergencyAccessType::View);
83        assert_eq!(result.status, EmergencyAccessStatus::Accepted);
84        assert_eq!(result.wait_time_days, 3);
85        assert_eq!(result.email.as_deref(), Some("[email protected]"));
86    }
87
88    #[tokio::test]
89    async fn fails_when_id_is_missing() {
90        let result = get(EmergencyAccessGranteeDetailsResponseModel::default()).await;
91
92        assert!(matches!(
93            result,
94            Err(EmergencyAccessGetError::MissingField(_))
95        ));
96    }
97
98    #[tokio::test]
99    async fn fails_when_request_fails() {
100        let client = test_client(test_bitwarden_com_account(), |mock| {
101            mock.emergency_access_api
102                .expect_get()
103                .returning(|_| api_error())
104                .once();
105        })
106        .await;
107
108        let result = client.emergency_access().get(test_id()).await;
109
110        assert!(matches!(result, Err(EmergencyAccessGetError::Api(_))));
111    }
112}