Skip to main content

bitwarden_pam/approvals/
models.rs

1use bitwarden_api_api::models::{
2    AccessDecisionRequestModel, AccessDecisionVerdict as ApiAccessDecisionVerdict,
3};
4use serde::{Deserialize, Serialize};
5#[cfg(feature = "wasm")]
6use tsify::Tsify;
7
8use super::error::ApprovalError;
9use crate::AccessDecisionVerdict;
10
11/// An approver's decision on a pending access request.
12#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
13#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
14#[serde(rename_all = "camelCase")]
15pub struct AccessDecisionRequest {
16    /// The verdict to record; [`AccessDecisionVerdict::Unknown`] cannot be submitted.
17    pub verdict: AccessDecisionVerdict,
18    /// An optional note shown to the requester.
19    pub comment: Option<String>,
20}
21
22impl TryFrom<AccessDecisionRequest> for AccessDecisionRequestModel {
23    type Error = ApprovalError;
24
25    fn try_from(request: AccessDecisionRequest) -> Result<Self, Self::Error> {
26        let verdict = match request.verdict {
27            AccessDecisionVerdict::Approve => ApiAccessDecisionVerdict::Approve,
28            AccessDecisionVerdict::Deny => ApiAccessDecisionVerdict::Deny,
29            AccessDecisionVerdict::Unknown => return Err(ApprovalError::UnsubmittableVerdict),
30        };
31
32        Ok(Self {
33            verdict,
34            comment: request.comment,
35        })
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn approve_converts_to_model() {
45        let request = AccessDecisionRequest {
46            verdict: AccessDecisionVerdict::Approve,
47            comment: Some("Looks fine".to_string()),
48        };
49
50        let model = AccessDecisionRequestModel::try_from(request).unwrap();
51
52        assert_eq!(model.verdict, ApiAccessDecisionVerdict::Approve);
53        assert_eq!(model.comment, Some("Looks fine".to_string()));
54    }
55
56    #[test]
57    fn deny_converts_to_model() {
58        let request = AccessDecisionRequest {
59            verdict: AccessDecisionVerdict::Deny,
60            comment: None,
61        };
62
63        let model = AccessDecisionRequestModel::try_from(request).unwrap();
64
65        assert_eq!(model.verdict, ApiAccessDecisionVerdict::Deny);
66        assert_eq!(model.comment, None);
67    }
68
69    #[test]
70    fn unknown_verdict_is_rejected() {
71        let request = AccessDecisionRequest {
72            verdict: AccessDecisionVerdict::Unknown,
73            comment: None,
74        };
75
76        let result = AccessDecisionRequestModel::try_from(request);
77
78        assert!(matches!(result, Err(ApprovalError::UnsubmittableVerdict)));
79    }
80}