litellm_rs/core/models/team/
settings.rs1use super::entity::TeamVisibility;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9pub struct TeamSettings {
10 pub default_member_role: Option<String>,
12 pub require_approval: bool,
14 pub allow_member_invites: bool,
16 pub visibility: TeamVisibility,
18 pub api_access: ApiAccessSettings,
20 pub notifications: TeamNotificationSettings,
22 pub security: TeamSecuritySettings,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize, Default)]
28pub struct ApiAccessSettings {
29 pub enabled: bool,
31 pub allowed_ips: Vec<String>,
33 pub allowed_domains: Vec<String>,
35 pub require_api_key: bool,
37 pub default_settings: HashMap<String, serde_json::Value>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize, Default)]
43pub struct TeamNotificationSettings {
44 pub slack_webhook: Option<String>,
46 pub email_notifications: bool,
48 pub webhook_notifications: bool,
50 pub channels: Vec<NotificationChannel>,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct NotificationChannel {
57 pub name: String,
59 pub channel_type: ChannelType,
61 pub config: HashMap<String, serde_json::Value>,
63 pub enabled: bool,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(rename_all = "snake_case")]
70pub enum ChannelType {
71 Email,
73 Slack,
75 Webhook,
77 Teams,
79 Discord,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize, Default)]
85pub struct TeamSecuritySettings {
86 pub require_2fa: bool,
88 pub password_policy: PasswordPolicy,
90 pub session_timeout: Option<u32>,
92 pub ip_whitelist: Vec<String>,
94 pub audit_logging: bool,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize, Default)]
100pub struct PasswordPolicy {
101 pub min_length: u32,
103 pub require_uppercase: bool,
105 pub require_lowercase: bool,
107 pub require_numbers: bool,
109 pub require_special: bool,
111 pub expiry_days: Option<u32>,
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
122 fn test_team_settings_default() {
123 let settings = TeamSettings::default();
124 assert!(settings.default_member_role.is_none());
125 assert!(!settings.require_approval);
126 assert!(!settings.allow_member_invites);
127 }
128
129 #[test]
130 fn test_team_settings_with_values() {
131 let settings = TeamSettings {
132 default_member_role: Some("member".to_string()),
133 require_approval: true,
134 allow_member_invites: true,
135 visibility: TeamVisibility::Public,
136 api_access: ApiAccessSettings::default(),
137 notifications: TeamNotificationSettings::default(),
138 security: TeamSecuritySettings::default(),
139 };
140
141 assert_eq!(settings.default_member_role, Some("member".to_string()));
142 assert!(settings.require_approval);
143 assert!(settings.allow_member_invites);
144 }
145
146 #[test]
147 fn test_team_settings_serialize() {
148 let settings = TeamSettings::default();
149 let json = serde_json::to_string(&settings).unwrap();
150 assert!(json.contains("require_approval"));
151 assert!(json.contains("visibility"));
152 }
153
154 #[test]
155 fn test_team_settings_clone() {
156 let original = TeamSettings {
157 default_member_role: Some("admin".to_string()),
158 ..Default::default()
159 };
160 let cloned = original.clone();
161 assert_eq!(original.default_member_role, cloned.default_member_role);
162 }
163
164 #[test]
167 fn test_api_access_settings_default() {
168 let settings = ApiAccessSettings::default();
169 assert!(!settings.enabled);
170 assert!(settings.allowed_ips.is_empty());
171 assert!(settings.allowed_domains.is_empty());
172 assert!(!settings.require_api_key);
173 }
174
175 #[test]
176 fn test_api_access_settings_enabled() {
177 let settings = ApiAccessSettings {
178 enabled: true,
179 allowed_ips: vec!["192.168.1.0/24".to_string()],
180 allowed_domains: vec!["example.com".to_string()],
181 require_api_key: true,
182 default_settings: std::collections::HashMap::new(),
183 };
184
185 assert!(settings.enabled);
186 assert_eq!(settings.allowed_ips.len(), 1);
187 assert!(settings.require_api_key);
188 }
189
190 #[test]
191 fn test_api_access_settings_serialize() {
192 let settings = ApiAccessSettings {
193 enabled: true,
194 allowed_ips: vec!["10.0.0.0/8".to_string()],
195 allowed_domains: vec![],
196 require_api_key: false,
197 default_settings: std::collections::HashMap::new(),
198 };
199
200 let json = serde_json::to_string(&settings).unwrap();
201 assert!(json.contains("10.0.0.0/8"));
202 }
203
204 #[test]
207 fn test_team_notification_settings_default() {
208 let settings = TeamNotificationSettings::default();
209 assert!(settings.slack_webhook.is_none());
210 assert!(!settings.email_notifications);
211 assert!(!settings.webhook_notifications);
212 assert!(settings.channels.is_empty());
213 }
214
215 #[test]
216 fn test_team_notification_settings_with_slack() {
217 let settings = TeamNotificationSettings {
218 slack_webhook: Some("https://hooks.slack.com/test".to_string()),
219 email_notifications: true,
220 webhook_notifications: false,
221 channels: vec![],
222 };
223
224 assert!(settings.slack_webhook.is_some());
225 assert!(settings.email_notifications);
226 }
227
228 #[test]
229 fn test_team_notification_settings_serialize() {
230 let settings = TeamNotificationSettings {
231 slack_webhook: Some("https://test.slack.com".to_string()),
232 email_notifications: true,
233 webhook_notifications: true,
234 channels: vec![],
235 };
236
237 let json = serde_json::to_string(&settings).unwrap();
238 assert!(json.contains("slack_webhook"));
239 }
240
241 #[test]
244 fn test_notification_channel_creation() {
245 let channel = NotificationChannel {
246 name: "alerts".to_string(),
247 channel_type: ChannelType::Slack,
248 config: std::collections::HashMap::new(),
249 enabled: true,
250 };
251
252 assert_eq!(channel.name, "alerts");
253 assert!(matches!(channel.channel_type, ChannelType::Slack));
254 assert!(channel.enabled);
255 }
256
257 #[test]
258 fn test_notification_channel_serialize() {
259 let channel = NotificationChannel {
260 name: "email-alerts".to_string(),
261 channel_type: ChannelType::Email,
262 config: std::collections::HashMap::new(),
263 enabled: false,
264 };
265
266 let json = serde_json::to_string(&channel).unwrap();
267 assert!(json.contains("email-alerts"));
268 assert!(json.contains("\"enabled\":false"));
269 }
270
271 #[test]
274 fn test_channel_type_email() {
275 let t = ChannelType::Email;
276 let json = serde_json::to_string(&t).unwrap();
277 assert_eq!(json, "\"email\"");
278 }
279
280 #[test]
281 fn test_channel_type_slack() {
282 let t = ChannelType::Slack;
283 let json = serde_json::to_string(&t).unwrap();
284 assert_eq!(json, "\"slack\"");
285 }
286
287 #[test]
288 fn test_channel_type_webhook() {
289 let t = ChannelType::Webhook;
290 let json = serde_json::to_string(&t).unwrap();
291 assert_eq!(json, "\"webhook\"");
292 }
293
294 #[test]
295 fn test_channel_type_teams() {
296 let t = ChannelType::Teams;
297 let json = serde_json::to_string(&t).unwrap();
298 assert_eq!(json, "\"teams\"");
299 }
300
301 #[test]
302 fn test_channel_type_discord() {
303 let t = ChannelType::Discord;
304 let json = serde_json::to_string(&t).unwrap();
305 assert_eq!(json, "\"discord\"");
306 }
307
308 #[test]
309 fn test_channel_type_deserialize() {
310 let t: ChannelType = serde_json::from_str("\"slack\"").unwrap();
311 assert!(matches!(t, ChannelType::Slack));
312 }
313
314 #[test]
317 fn test_team_security_settings_default() {
318 let settings = TeamSecuritySettings::default();
319 assert!(!settings.require_2fa);
320 assert!(settings.session_timeout.is_none());
321 assert!(settings.ip_whitelist.is_empty());
322 assert!(!settings.audit_logging);
323 }
324
325 #[test]
326 fn test_team_security_settings_strict() {
327 let settings = TeamSecuritySettings {
328 require_2fa: true,
329 password_policy: PasswordPolicy {
330 min_length: 12,
331 require_uppercase: true,
332 require_lowercase: true,
333 require_numbers: true,
334 require_special: true,
335 expiry_days: Some(90),
336 },
337 session_timeout: Some(30),
338 ip_whitelist: vec!["10.0.0.0/8".to_string()],
339 audit_logging: true,
340 };
341
342 assert!(settings.require_2fa);
343 assert_eq!(settings.session_timeout, Some(30));
344 assert!(settings.audit_logging);
345 }
346
347 #[test]
348 fn test_team_security_settings_serialize() {
349 let settings = TeamSecuritySettings {
350 require_2fa: true,
351 password_policy: PasswordPolicy::default(),
352 session_timeout: Some(60),
353 ip_whitelist: vec![],
354 audit_logging: true,
355 };
356
357 let json = serde_json::to_string(&settings).unwrap();
358 assert!(json.contains("require_2fa"));
359 assert!(json.contains("audit_logging"));
360 }
361
362 #[test]
365 fn test_password_policy_default() {
366 let policy = PasswordPolicy::default();
367 assert_eq!(policy.min_length, 0);
368 assert!(!policy.require_uppercase);
369 assert!(!policy.require_lowercase);
370 assert!(!policy.require_numbers);
371 assert!(!policy.require_special);
372 assert!(policy.expiry_days.is_none());
373 }
374
375 #[test]
376 fn test_password_policy_strict() {
377 let policy = PasswordPolicy {
378 min_length: 16,
379 require_uppercase: true,
380 require_lowercase: true,
381 require_numbers: true,
382 require_special: true,
383 expiry_days: Some(30),
384 };
385
386 assert_eq!(policy.min_length, 16);
387 assert!(policy.require_uppercase);
388 assert!(policy.require_special);
389 assert_eq!(policy.expiry_days, Some(30));
390 }
391
392 #[test]
393 fn test_password_policy_serialize() {
394 let policy = PasswordPolicy {
395 min_length: 8,
396 require_uppercase: true,
397 require_lowercase: true,
398 require_numbers: false,
399 require_special: false,
400 expiry_days: None,
401 };
402
403 let json = serde_json::to_string(&policy).unwrap();
404 assert!(json.contains("min_length"));
405 assert!(json.contains("require_uppercase"));
406 }
407
408 #[test]
409 fn test_password_policy_clone() {
410 let original = PasswordPolicy {
411 min_length: 10,
412 require_uppercase: true,
413 require_lowercase: true,
414 require_numbers: true,
415 require_special: false,
416 expiry_days: Some(60),
417 };
418
419 let cloned = original.clone();
420 assert_eq!(original.min_length, cloned.min_length);
421 assert_eq!(original.expiry_days, cloned.expiry_days);
422 }
423}