Skip to main content

gitea_sdk_rs/options/org/
team.rs

1// Copyright 2026 infinitete. All rights reserved.
2// Use of this source code is governed by a MIT-style
3// license that can be found in the LICENSE file.
4
5use crate::pagination::{ListOptions, QueryEncode};
6use crate::types::enums::{AccessMode, RepoUnitType};
7use crate::{Deserialize, Serialize};
8
9use super::percent_encode;
10
11// ── org_team.go ─────────────────────────────────────────────────────────
12
13#[derive(Debug, Clone, Default)]
14pub struct ListTeamsOptions {
15    pub list_options: ListOptions,
16}
17
18impl QueryEncode for ListTeamsOptions {
19    fn query_encode(&self) -> String {
20        self.list_options.query_encode()
21    }
22}
23
24#[derive(Debug, Clone, Default)]
25pub struct SearchTeamsOptions {
26    pub list_options: ListOptions,
27    pub query: String,
28    pub include_description: bool,
29}
30
31impl QueryEncode for SearchTeamsOptions {
32    fn query_encode(&self) -> String {
33        let mut out = self.list_options.query_encode();
34        out.push_str(&format!(
35            "&q={}&include_desc={}",
36            percent_encode(&self.query),
37            self.include_description
38        ));
39        out
40    }
41}
42
43#[derive(Debug, Clone, Default, Serialize, Deserialize)]
44pub struct CreateTeamOption {
45    pub name: String,
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub description: Option<String>,
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub permission: Option<AccessMode>,
50    #[serde(
51        rename = "can_create_org_repo",
52        skip_serializing_if = "Option::is_none"
53    )]
54    pub can_create_org_repo: Option<bool>,
55    #[serde(
56        rename = "includes_all_repositories",
57        skip_serializing_if = "Option::is_none"
58    )]
59    pub includes_all_repositories: Option<bool>,
60    #[serde(default, skip_serializing_if = "Vec::is_empty")]
61    pub units: Vec<RepoUnitType>,
62}
63
64impl CreateTeamOption {
65    pub fn validate(&self) -> crate::Result<()> {
66        let perm = self.permission.unwrap_or(AccessMode::Read);
67        match perm {
68            AccessMode::Read | AccessMode::Write | AccessMode::Admin => {}
69            _ => {
70                return Err(crate::Error::Validation(
71                    "permission mode invalid".to_string(),
72                ));
73            }
74        }
75        if self.name.is_empty() {
76            return Err(crate::Error::Validation("name required".to_string()));
77        }
78        if self.name.len() > 255 {
79            return Err(crate::Error::Validation("name too long".to_string()));
80        }
81        if let Some(desc) = &self.description
82            && desc.len() > 255
83        {
84            return Err(crate::Error::Validation("description too long".to_string()));
85        }
86        Ok(())
87    }
88}
89
90#[derive(Debug, Clone, Default, Serialize, Deserialize)]
91pub struct EditTeamOption {
92    pub name: String,
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub description: Option<String>,
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub permission: Option<AccessMode>,
97    #[serde(
98        rename = "can_create_org_repo",
99        skip_serializing_if = "Option::is_none"
100    )]
101    pub can_create_org_repo: Option<bool>,
102    #[serde(
103        rename = "includes_all_repositories",
104        skip_serializing_if = "Option::is_none"
105    )]
106    pub includes_all_repositories: Option<bool>,
107    #[serde(default, skip_serializing_if = "Vec::is_empty")]
108    pub units: Vec<RepoUnitType>,
109}
110
111impl EditTeamOption {
112    pub fn validate(&self) -> crate::Result<()> {
113        let perm = self.permission.unwrap_or(AccessMode::Read);
114        match perm {
115            AccessMode::Read | AccessMode::Write | AccessMode::Admin => {}
116            _ => {
117                return Err(crate::Error::Validation(
118                    "permission mode invalid".to_string(),
119                ));
120            }
121        }
122        if self.name.is_empty() {
123            return Err(crate::Error::Validation("name required".to_string()));
124        }
125        if self.name.len() > 30 {
126            return Err(crate::Error::Validation("name too long".to_string()));
127        }
128        if let Some(desc) = &self.description
129            && desc.len() > 255
130        {
131            return Err(crate::Error::Validation("description too long".to_string()));
132        }
133        Ok(())
134    }
135}
136
137#[derive(Debug, Clone, Default)]
138pub struct ListTeamMembersOptions {
139    pub list_options: ListOptions,
140}
141
142impl QueryEncode for ListTeamMembersOptions {
143    fn query_encode(&self) -> String {
144        self.list_options.query_encode()
145    }
146}
147
148#[derive(Debug, Clone, Default)]
149pub struct ListTeamRepositoriesOptions {
150    pub list_options: ListOptions,
151}
152
153impl QueryEncode for ListTeamRepositoriesOptions {
154    fn query_encode(&self) -> String {
155        self.list_options.query_encode()
156    }
157}
158
159#[cfg(test)]
160mod tests {
161    use super::*;
162
163    #[test]
164    fn test_create_team_option_validate_success() {
165        let opt = CreateTeamOption {
166            name: "core".to_string(),
167            description: Some("Core team".to_string()),
168            permission: Some(AccessMode::Read),
169            can_create_org_repo: None,
170            includes_all_repositories: None,
171            units: Vec::new(),
172        };
173        assert!(opt.validate().is_ok());
174    }
175
176    #[test]
177    fn test_create_team_option_validate_empty_name() {
178        let opt = CreateTeamOption {
179            name: String::new(),
180            description: None,
181            permission: None,
182            can_create_org_repo: None,
183            includes_all_repositories: None,
184            units: Vec::new(),
185        };
186        assert!(opt.validate().is_err());
187    }
188
189    #[test]
190    fn test_create_team_option_validate_name_too_long() {
191        let opt = CreateTeamOption {
192            name: "a".repeat(256),
193            description: None,
194            permission: None,
195            can_create_org_repo: None,
196            includes_all_repositories: None,
197            units: Vec::new(),
198        };
199        assert!(opt.validate().is_err());
200    }
201
202    #[test]
203    fn test_create_team_option_validate_description_too_long() {
204        let opt = CreateTeamOption {
205            name: "core".to_string(),
206            description: Some("d".repeat(256)),
207            permission: None,
208            can_create_org_repo: None,
209            includes_all_repositories: None,
210            units: Vec::new(),
211        };
212        assert!(opt.validate().is_err());
213    }
214
215    #[test]
216    fn test_create_team_option_validate_invalid_permission() {
217        let opt = CreateTeamOption {
218            name: "core".to_string(),
219            permission: Some(AccessMode::Owner),
220            description: None,
221            can_create_org_repo: None,
222            includes_all_repositories: None,
223            units: Vec::new(),
224        };
225        assert!(opt.validate().is_err());
226    }
227
228    #[test]
229    fn test_edit_team_option_validate_success() {
230        let opt = EditTeamOption {
231            name: "core".to_string(),
232            description: Some("Core team".to_string()),
233            permission: Some(AccessMode::Read),
234            can_create_org_repo: None,
235            includes_all_repositories: None,
236            units: Vec::new(),
237        };
238        assert!(opt.validate().is_ok());
239    }
240
241    #[test]
242    fn test_edit_team_option_validate_empty_name() {
243        let opt = EditTeamOption {
244            name: String::new(),
245            description: None,
246            permission: None,
247            can_create_org_repo: None,
248            includes_all_repositories: None,
249            units: Vec::new(),
250        };
251        assert!(opt.validate().is_err());
252    }
253
254    #[test]
255    fn test_edit_team_option_validate_name_too_long() {
256        let opt = EditTeamOption {
257            name: "a".repeat(31),
258            description: None,
259            permission: None,
260            can_create_org_repo: None,
261            includes_all_repositories: None,
262            units: Vec::new(),
263        };
264        assert!(opt.validate().is_err());
265    }
266}