bitwarden_policies/
policy_client.rs1use bitwarden_core::Client;
4#[cfg(feature = "wasm")]
5use wasm_bindgen::prelude::wasm_bindgen;
6
7use crate::{
8 OrganizationUserPolicyContext, PolicyType, PolicyView, policy_overrides::*,
9 registry::PolicyRegistry,
10};
11
12fn build_policy_registry() -> PolicyRegistry {
13 PolicyRegistry::builder()
14 .register(MasterPasswordPolicy)
15 .register(PasswordGeneratorPolicy)
16 .register(MaximumVaultTimeoutPolicy)
17 .register(FreeFamiliesSponsorshipPolicy)
18 .register(RemoveUnlockWithPinPolicy)
19 .register(RestrictedItemTypesPolicy)
20 .register(AutomaticUserConfirmationPolicy)
21 .register(OrganizationUserNotificationPolicy)
22 .build()
23}
24
25#[cfg_attr(feature = "wasm", wasm_bindgen)]
29pub struct PolicyClient {
30 registry: PolicyRegistry,
31}
32
33impl Default for PolicyClient {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl PolicyClient {
40 pub fn new() -> Self {
42 Self {
43 registry: build_policy_registry(),
44 }
45 }
46}
47
48#[cfg_attr(feature = "wasm", wasm_bindgen)]
49impl PolicyClient {
50 pub fn filter_by_type(
55 &self,
56 policies: Vec<PolicyView>,
57 organization_user_policy_contexts: Vec<OrganizationUserPolicyContext>,
58 policy_type: PolicyType,
59 ) -> Vec<PolicyView> {
60 self.registry
61 .filter_by_type(&policies, &organization_user_policy_contexts, policy_type)
62 .into_iter()
63 .cloned()
64 .collect()
65 }
66}
67
68pub trait PoliciesClientExt {
70 fn policies(&self) -> PolicyClient;
72}
73
74impl PoliciesClientExt for Client {
75 fn policies(&self) -> PolicyClient {
76 PolicyClient::new()
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use bitwarden_organizations::{OrganizationUserStatusType, OrganizationUserType};
83 use uuid::Uuid;
84
85 use super::*;
86 use crate::filter::Policy;
87
88 fn policy_view(organization_id: Uuid, policy_type: PolicyType, enabled: bool) -> PolicyView {
89 PolicyView {
90 id: Uuid::new_v4(),
91 organization_id,
92 r#type: policy_type,
93 data: None,
94 enabled,
95 revision_date: Default::default(),
96 }
97 }
98
99 fn organization(id: Uuid) -> OrganizationUserPolicyContext {
100 OrganizationUserPolicyContext {
101 id,
102 role: OrganizationUserType::User,
103 status: OrganizationUserStatusType::Confirmed,
104 enabled: true,
105 use_policies: true,
106 is_provider_user: false,
107 }
108 }
109
110 #[test]
111 fn filter_by_type_delegates_to_registry() {
112 let org_id = Uuid::new_v4();
113 let policies = vec![
114 policy_view(org_id, PolicyType::MasterPassword, true),
115 policy_view(org_id, PolicyType::PasswordGenerator, true),
116 ];
117 let orgs = vec![organization(org_id)];
118
119 let client = PolicyClient::new();
120 let result = client.filter_by_type(policies, orgs, PolicyType::MasterPassword);
121
122 assert_eq!(result.len(), 1);
123 assert_eq!(result[0].r#type, PolicyType::MasterPassword);
124 }
125
126 #[test]
127 fn filter_by_type_returns_empty_for_no_match() {
128 let org_id = Uuid::new_v4();
129 let policies = vec![policy_view(org_id, PolicyType::MasterPassword, true)];
130 let orgs = vec![organization(org_id)];
131
132 let client = PolicyClient::new();
133 let result = client.filter_by_type(policies, orgs, PolicyType::TwoFactorAuthentication);
134
135 assert!(result.is_empty());
136 }
137
138 #[test]
139 fn filter_by_type_uses_registered_policy_definition() {
140 struct NoExemptionPolicy;
141 impl Policy for NoExemptionPolicy {
142 fn policy_type(&self) -> PolicyType {
143 PolicyType::MasterPassword
144 }
145 fn exempt_roles(&self) -> &[OrganizationUserType] {
146 &[]
147 }
148 }
149
150 let org_id = Uuid::new_v4();
151 let policies = vec![policy_view(org_id, PolicyType::MasterPassword, true)];
153 let orgs = vec![OrganizationUserPolicyContext {
154 id: org_id,
155 role: OrganizationUserType::Owner,
156 status: OrganizationUserStatusType::Confirmed,
157 enabled: true,
158 use_policies: true,
159 is_provider_user: false,
160 }];
161
162 let registry = PolicyRegistry::builder()
163 .register(NoExemptionPolicy)
164 .build();
165 let client = PolicyClient { registry };
166 let result = client.filter_by_type(policies, orgs, PolicyType::MasterPassword);
167
168 assert_eq!(result.len(), 1);
169 }
170}