1use crate::permission::Permission;
4use serde::{Deserialize, Serialize};
5use std::collections::HashSet;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct Team {
13 pub id: u64,
15 pub org_id: u64,
17 pub name: String,
19 pub description: Option<String>,
21 pub members: HashSet<String>,
23 pub permission: Permission,
25 pub repos: HashSet<String>,
27 pub created_at: u64,
29 pub updated_at: u64,
31 pub created_by: String,
33}
34
35impl Team {
36 pub fn new(
38 id: u64,
39 org_id: u64,
40 name: String,
41 permission: Permission,
42 created_by: String,
43 ) -> Self {
44 let now = Self::now();
45 Self {
46 id,
47 org_id,
48 name,
49 description: None,
50 members: HashSet::new(),
51 permission,
52 repos: HashSet::new(),
53 created_at: now,
54 updated_at: now,
55 created_by,
56 }
57 }
58
59 pub fn with_description(mut self, description: impl Into<String>) -> Self {
61 self.description = Some(description.into());
62 self.updated_at = Self::now();
63 self
64 }
65
66 pub fn is_member(&self, user: &str) -> bool {
68 self.members.contains(user)
69 }
70
71 pub fn add_member(&mut self, user: String) -> bool {
73 let added = self.members.insert(user);
74 if added {
75 self.updated_at = Self::now();
76 }
77 added
78 }
79
80 pub fn remove_member(&mut self, user: &str) -> bool {
82 let removed = self.members.remove(user);
83 if removed {
84 self.updated_at = Self::now();
85 }
86 removed
87 }
88
89 pub fn has_repo(&self, repo_key: &str) -> bool {
91 self.repos.contains(repo_key)
92 }
93
94 pub fn add_repo(&mut self, repo_key: String) -> bool {
96 let added = self.repos.insert(repo_key);
97 if added {
98 self.updated_at = Self::now();
99 }
100 added
101 }
102
103 pub fn remove_repo(&mut self, repo_key: &str) -> bool {
105 let removed = self.repos.remove(repo_key);
106 if removed {
107 self.updated_at = Self::now();
108 }
109 removed
110 }
111
112 pub fn get_repo_permission(&self, repo_key: &str) -> Option<Permission> {
115 if self.repos.contains(repo_key) {
116 Some(self.permission)
117 } else {
118 None
119 }
120 }
121
122 pub fn set_permission(&mut self, permission: Permission) {
124 self.permission = permission;
125 self.updated_at = Self::now();
126 }
127
128 fn now() -> u64 {
129 std::time::SystemTime::now()
130 .duration_since(std::time::UNIX_EPOCH)
131 .unwrap_or_default()
132 .as_secs()
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139
140 #[test]
141 fn test_team_creation() {
142 let team = Team::new(1, 1, "backend".into(), Permission::Write, "creator".into());
143
144 assert_eq!(team.id, 1);
145 assert_eq!(team.org_id, 1);
146 assert_eq!(team.name, "backend");
147 assert_eq!(team.permission, Permission::Write);
148 assert!(team.members.is_empty());
149 assert!(team.repos.is_empty());
150 }
151
152 #[test]
153 fn test_team_members() {
154 let mut team = Team::new(1, 1, "backend".into(), Permission::Write, "creator".into());
155
156 assert!(team.add_member("user1".into()));
157 assert!(team.is_member("user1"));
158 assert!(!team.add_member("user1".into())); assert!(team.add_member("user2".into()));
161 assert_eq!(team.members.len(), 2);
162
163 assert!(team.remove_member("user1"));
164 assert!(!team.is_member("user1"));
165 assert!(!team.remove_member("user1")); }
167
168 #[test]
169 fn test_team_repos() {
170 let mut team = Team::new(1, 1, "backend".into(), Permission::Write, "creator".into());
171
172 assert!(team.add_repo("acme/api".into()));
173 assert!(team.has_repo("acme/api"));
174 assert_eq!(
175 team.get_repo_permission("acme/api"),
176 Some(Permission::Write)
177 );
178 assert_eq!(team.get_repo_permission("acme/other"), None);
179
180 assert!(team.remove_repo("acme/api"));
181 assert!(!team.has_repo("acme/api"));
182 }
183
184 #[test]
185 fn test_team_permission_update() {
186 let mut team = Team::new(1, 1, "backend".into(), Permission::Read, "creator".into());
187 team.add_repo("acme/api".into());
188
189 assert_eq!(team.get_repo_permission("acme/api"), Some(Permission::Read));
190
191 team.set_permission(Permission::Admin);
192 assert_eq!(
193 team.get_repo_permission("acme/api"),
194 Some(Permission::Admin)
195 );
196 }
197}