Skip to main content

gitlab/api/projects/members/
members.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7use std::collections::BTreeSet;
8
9use derive_builder::Builder;
10
11use crate::api::common::NameOrId;
12use crate::api::endpoint_prelude::*;
13
14/// Query a members of a project.
15#[derive(Debug, Builder, Clone)]
16#[builder(setter(strip_option))]
17pub struct ProjectMembers<'a> {
18    /// The project to query for membership.
19    #[builder(setter(into))]
20    project: NameOrId<'a>,
21
22    /// A search string to filter members by.
23    #[builder(setter(into), default)]
24    query: Option<Cow<'a, str>>,
25    /// A search string to filter members by.
26    #[builder(setter(name = "_user_ids"), default, private)]
27    user_ids: BTreeSet<u64>,
28    /// Skip certain user results.
29    #[builder(setter(name = "_skip_users"), default, private)]
30    skip_users: BTreeSet<u64>,
31    /// Show seat information for users.
32    #[builder(default)]
33    show_seat_info: Option<bool>,
34}
35
36impl<'a> ProjectMembers<'a> {
37    /// Create a builder for the endpoint.
38    pub fn builder() -> ProjectMembersBuilder<'a> {
39        ProjectMembersBuilder::default()
40    }
41}
42
43impl ProjectMembersBuilder<'_> {
44    /// Filter results by the given user ID.
45    pub fn user_id(&mut self, user_id: u64) -> &mut Self {
46        self.user_ids
47            .get_or_insert_with(BTreeSet::new)
48            .insert(user_id);
49        self
50    }
51
52    /// Filter results by the given user IDs.
53    pub fn user_ids<I>(&mut self, iter: I) -> &mut Self
54    where
55        I: Iterator<Item = u64>,
56    {
57        self.user_ids.get_or_insert_with(BTreeSet::new).extend(iter);
58        self
59    }
60
61    /// Skip a certain user.
62    pub fn skip_user(&mut self, user_id: u64) -> &mut Self {
63        self.skip_users
64            .get_or_insert_with(BTreeSet::new)
65            .insert(user_id);
66        self
67    }
68
69    /// Skip a set of users.
70    pub fn skip_users<I>(&mut self, iter: I) -> &mut Self
71    where
72        I: Iterator<Item = u64>,
73    {
74        self.skip_users
75            .get_or_insert_with(BTreeSet::new)
76            .extend(iter);
77        self
78    }
79}
80
81impl Endpoint for ProjectMembers<'_> {
82    fn method(&self) -> Method {
83        Method::GET
84    }
85
86    fn endpoint(&self) -> Cow<'static, str> {
87        format!("projects/{}/members", self.project).into()
88    }
89
90    fn parameters(&self) -> QueryParams<'_> {
91        let mut params = QueryParams::default();
92
93        params
94            .push_opt("query", self.query.as_ref())
95            .extend(self.user_ids.iter().map(|&value| ("user_ids[]", value)))
96            .extend(self.skip_users.iter().map(|&value| ("skip_users[]", value)))
97            .push_opt("show_seat_info", self.show_seat_info);
98
99        params
100    }
101}
102
103impl Pageable for ProjectMembers<'_> {}
104
105#[cfg(test)]
106mod tests {
107    use crate::api::projects::members::{ProjectMembers, ProjectMembersBuilderError};
108    use crate::api::{self, Query};
109    use crate::test::client::{ExpectedUrl, SingleTestClient};
110
111    #[test]
112    fn project_is_needed() {
113        let err = ProjectMembers::builder().build().unwrap_err();
114        crate::test::assert_missing_field!(err, ProjectMembersBuilderError, "project");
115    }
116
117    #[test]
118    fn project_is_sufficient() {
119        ProjectMembers::builder().project(1).build().unwrap();
120    }
121
122    #[test]
123    fn endpoint() {
124        let endpoint = ExpectedUrl::builder()
125            .endpoint("projects/simple%2Fproject/members")
126            .build()
127            .unwrap();
128        let client = SingleTestClient::new_raw(endpoint, "");
129
130        let endpoint = ProjectMembers::builder()
131            .project("simple/project")
132            .build()
133            .unwrap();
134        api::ignore(endpoint).query(&client).unwrap();
135    }
136
137    #[test]
138    fn endpoint_query() {
139        let endpoint = ExpectedUrl::builder()
140            .endpoint("projects/simple%2Fproject/members")
141            .add_query_params(&[("query", "search")])
142            .build()
143            .unwrap();
144        let client = SingleTestClient::new_raw(endpoint, "");
145
146        let endpoint = ProjectMembers::builder()
147            .project("simple/project")
148            .query("search")
149            .build()
150            .unwrap();
151        api::ignore(endpoint).query(&client).unwrap();
152    }
153
154    #[test]
155    fn endpoint_user_ids() {
156        let endpoint = ExpectedUrl::builder()
157            .endpoint("projects/simple%2Fproject/members")
158            .add_query_params(&[("user_ids[]", "1"), ("user_ids[]", "2")])
159            .build()
160            .unwrap();
161        let client = SingleTestClient::new_raw(endpoint, "");
162
163        let endpoint = ProjectMembers::builder()
164            .project("simple/project")
165            .user_id(1)
166            .user_ids([1, 2].iter().copied())
167            .build()
168            .unwrap();
169        api::ignore(endpoint).query(&client).unwrap();
170    }
171
172    #[test]
173    fn endpoint_skip_users() {
174        let endpoint = ExpectedUrl::builder()
175            .endpoint("projects/simple%2Fproject/members")
176            .add_query_params(&[("skip_users[]", "1"), ("skip_users[]", "2")])
177            .build()
178            .unwrap();
179        let client = SingleTestClient::new_raw(endpoint, "");
180
181        let endpoint = ProjectMembers::builder()
182            .project("simple/project")
183            .skip_user(1)
184            .skip_users([1, 2].iter().copied())
185            .build()
186            .unwrap();
187        api::ignore(endpoint).query(&client).unwrap();
188    }
189
190    #[test]
191    fn endpoint_show_seat_info() {
192        let endpoint = ExpectedUrl::builder()
193            .endpoint("projects/simple%2Fproject/members")
194            .add_query_params(&[("show_seat_info", "true")])
195            .build()
196            .unwrap();
197        let client = SingleTestClient::new_raw(endpoint, "");
198
199        let endpoint = ProjectMembers::builder()
200            .project("simple/project")
201            .show_seat_info(true)
202            .build()
203            .unwrap();
204        api::ignore(endpoint).query(&client).unwrap();
205    }
206}