use crate::permission::Permission;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Team {
pub id: u64,
pub org_id: u64,
pub name: String,
pub description: Option<String>,
pub members: HashSet<String>,
pub permission: Permission,
pub repos: HashSet<String>,
pub created_at: u64,
pub updated_at: u64,
pub created_by: String,
}
impl Team {
pub fn new(
id: u64,
org_id: u64,
name: String,
permission: Permission,
created_by: String,
) -> Self {
let now = Self::now();
Self {
id,
org_id,
name,
description: None,
members: HashSet::new(),
permission,
repos: HashSet::new(),
created_at: now,
updated_at: now,
created_by,
}
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self.updated_at = Self::now();
self
}
pub fn is_member(&self, user: &str) -> bool {
self.members.contains(user)
}
pub fn add_member(&mut self, user: String) -> bool {
let added = self.members.insert(user);
if added {
self.updated_at = Self::now();
}
added
}
pub fn remove_member(&mut self, user: &str) -> bool {
let removed = self.members.remove(user);
if removed {
self.updated_at = Self::now();
}
removed
}
pub fn has_repo(&self, repo_key: &str) -> bool {
self.repos.contains(repo_key)
}
pub fn add_repo(&mut self, repo_key: String) -> bool {
let added = self.repos.insert(repo_key);
if added {
self.updated_at = Self::now();
}
added
}
pub fn remove_repo(&mut self, repo_key: &str) -> bool {
let removed = self.repos.remove(repo_key);
if removed {
self.updated_at = Self::now();
}
removed
}
pub fn get_repo_permission(&self, repo_key: &str) -> Option<Permission> {
if self.repos.contains(repo_key) {
Some(self.permission)
} else {
None
}
}
pub fn set_permission(&mut self, permission: Permission) {
self.permission = permission;
self.updated_at = Self::now();
}
fn now() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_team_creation() {
let team = Team::new(1, 1, "backend".into(), Permission::Write, "creator".into());
assert_eq!(team.id, 1);
assert_eq!(team.org_id, 1);
assert_eq!(team.name, "backend");
assert_eq!(team.permission, Permission::Write);
assert!(team.members.is_empty());
assert!(team.repos.is_empty());
}
#[test]
fn test_team_members() {
let mut team = Team::new(1, 1, "backend".into(), Permission::Write, "creator".into());
assert!(team.add_member("user1".into()));
assert!(team.is_member("user1"));
assert!(!team.add_member("user1".into()));
assert!(team.add_member("user2".into()));
assert_eq!(team.members.len(), 2);
assert!(team.remove_member("user1"));
assert!(!team.is_member("user1"));
assert!(!team.remove_member("user1")); }
#[test]
fn test_team_repos() {
let mut team = Team::new(1, 1, "backend".into(), Permission::Write, "creator".into());
assert!(team.add_repo("acme/api".into()));
assert!(team.has_repo("acme/api"));
assert_eq!(
team.get_repo_permission("acme/api"),
Some(Permission::Write)
);
assert_eq!(team.get_repo_permission("acme/other"), None);
assert!(team.remove_repo("acme/api"));
assert!(!team.has_repo("acme/api"));
}
#[test]
fn test_team_permission_update() {
let mut team = Team::new(1, 1, "backend".into(), Permission::Read, "creator".into());
team.add_repo("acme/api".into());
assert_eq!(team.get_repo_permission("acme/api"), Some(Permission::Read));
team.set_permission(Permission::Admin);
assert_eq!(
team.get_repo_permission("acme/api"),
Some(Permission::Admin)
);
}
}