gitlab/api/groups/
share.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 chrono::NaiveDate;
8use derive_builder::Builder;
9
10use crate::api::common::{AccessLevel, NameOrId};
11use crate::api::endpoint_prelude::*;
12
13/// Share group with another group.
14#[derive(Debug, Builder, Clone)]
15#[builder(setter(strip_option))]
16pub struct ShareGroup<'a> {
17    /// The ID or URL-encoded path of the group.
18    #[builder(setter(into))]
19    id: NameOrId<'a>,
20    /// The ID of the group to share with.
21    group_id: u64,
22    /// The access level to grant the group.
23    group_access: AccessLevel,
24    /// When the group's access expires.
25    #[builder(default)]
26    expires_at: Option<NaiveDate>,
27    /// The ID of a custom role to assign to the invited group.
28    #[builder(default)]
29    member_role_id: Option<u64>,
30}
31
32impl<'a> ShareGroup<'a> {
33    /// Create a builder for the endpoint.
34    pub fn builder() -> ShareGroupBuilder<'a> {
35        ShareGroupBuilder::default()
36    }
37}
38
39impl Endpoint for ShareGroup<'_> {
40    fn method(&self) -> Method {
41        Method::POST
42    }
43
44    fn endpoint(&self) -> Cow<'static, str> {
45        format!("groups/{}/share", self.id).into()
46    }
47
48    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
49        let mut params = FormParams::default();
50
51        params
52            .push("group_id", self.group_id)
53            .push("group_access", self.group_access.as_u64())
54            .push_opt("expires_at", self.expires_at)
55            .push_opt("member_role_id", self.member_role_id);
56
57        params.into_body()
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use chrono::NaiveDate;
64    use http::Method;
65
66    use crate::api::common::AccessLevel;
67    use crate::api::groups::{ShareGroup, ShareGroupBuilderError};
68    use crate::api::{self, Query};
69    use crate::test::client::{ExpectedUrl, SingleTestClient};
70
71    #[test]
72    fn all_parameters_are_needed() {
73        let err = ShareGroup::builder().build().unwrap_err();
74        crate::test::assert_missing_field!(err, ShareGroupBuilderError, "id");
75    }
76
77    #[test]
78    fn id_is_necessary() {
79        let err = ShareGroup::builder()
80            .group_id(1)
81            .group_access(AccessLevel::Developer)
82            .build()
83            .unwrap_err();
84        crate::test::assert_missing_field!(err, ShareGroupBuilderError, "id");
85    }
86
87    #[test]
88    fn group_id_is_necessary() {
89        let err = ShareGroup::builder()
90            .id(1)
91            .group_access(AccessLevel::Developer)
92            .build()
93            .unwrap_err();
94        crate::test::assert_missing_field!(err, ShareGroupBuilderError, "group_id");
95    }
96
97    #[test]
98    fn group_access_is_necessary() {
99        let err = ShareGroup::builder().id(1).group_id(1).build().unwrap_err();
100        crate::test::assert_missing_field!(err, ShareGroupBuilderError, "group_access");
101    }
102
103    #[test]
104    fn sufficient_parameters() {
105        ShareGroup::builder()
106            .id("id")
107            .group_id(1)
108            .group_access(AccessLevel::Developer)
109            .build()
110            .unwrap();
111    }
112
113    #[test]
114    fn endpoint() {
115        let endpoint = ExpectedUrl::builder()
116            .method(Method::POST)
117            .endpoint("groups/simple%2Fproject/share")
118            .content_type("application/x-www-form-urlencoded")
119            .body_str(concat!("group_id=1", "&group_access=30"))
120            .build()
121            .unwrap();
122        let client = SingleTestClient::new_raw(endpoint, "");
123
124        let endpoint = ShareGroup::builder()
125            .id("simple/project")
126            .group_id(1)
127            .group_access(AccessLevel::Developer)
128            .build()
129            .unwrap();
130        api::ignore(endpoint).query(&client).unwrap();
131    }
132
133    #[test]
134    fn endpoint_expires_at() {
135        let endpoint = ExpectedUrl::builder()
136            .method(Method::POST)
137            .endpoint("groups/1/share")
138            .content_type("application/x-www-form-urlencoded")
139            .body_str(concat!(
140                "group_id=1",
141                "&group_access=30",
142                "&expires_at=2020-01-01",
143            ))
144            .build()
145            .unwrap();
146        let client = SingleTestClient::new_raw(endpoint, "");
147
148        let endpoint = ShareGroup::builder()
149            .id(1)
150            .group_id(1)
151            .group_access(AccessLevel::Developer)
152            .expires_at(NaiveDate::from_ymd_opt(2020, 1, 1).unwrap())
153            .build()
154            .unwrap();
155        api::ignore(endpoint).query(&client).unwrap();
156    }
157
158    #[test]
159    fn endpoint_member_role_id() {
160        let endpoint = ExpectedUrl::builder()
161            .method(Method::POST)
162            .endpoint("groups/1/share")
163            .content_type("application/x-www-form-urlencoded")
164            .body_str(concat!(
165                "group_id=1",
166                "&group_access=30",
167                "&member_role_id=1234",
168            ))
169            .build()
170            .unwrap();
171        let client = SingleTestClient::new_raw(endpoint, "");
172
173        let endpoint = ShareGroup::builder()
174            .id(1)
175            .group_id(1)
176            .group_access(AccessLevel::Developer)
177            .member_role_id(1234)
178            .build()
179            .unwrap();
180        api::ignore(endpoint).query(&client).unwrap();
181    }
182}