Commit d831c161 authored by Ben Boeckel's avatar Ben Boeckel Committed by Kitware Robot
Browse files

Merge topic 'member-access-fold-with-group'

8390db2c update CHANGELOG to reflect members include ancestors endpoint change
f61a42ca fix endpoint test for members including ancestors API
8610ff05 add all_builder() for project member(s) query incl ancestors
091f63cf add support for /projects/:project/members/all/:id
c25125e9 update api README.md
3dbfa662

 add support for project member queries including ancestors
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Ben Boeckel's avatarBen Boeckel <ben.boeckel@kitware.com>
Merge-request: !247
parents 4bc5aed8 8390db2c
......@@ -46,6 +46,10 @@
This allows for clients to not be tied to `reqwest` and for mocking and
testing of the endpoints themselves.
* GitLab errors now detect error objects returned from the API.
* Updated `api::projects::members::ProjectMember[s]` to support the ability
to include member details for those members that have access as a result
of belonging to ancestor/enclosing groups, in addition to directly added
members.
## Fixes
......
......@@ -44,6 +44,8 @@ These API endpoints have been implemented.
* `POST /projects/:project/labels` `projects/labels/create.rs`
* `GET /projects/:project/labels/:label` `projects/labels/labels.rs`
* `GET /projects/:project/members` `projects/members/members.rs`
* `GET /projects/:project/members/all` `projects/members/members.rs`
* `GET /projects/:project/members/all/:id` `projects/members/member.rs`
* `POST /projects/:project/members` `projects/members/add.rs`
* `GET /projects/:project/members/:id` `projects/members/member.rs`
* `GET /projects/:project/merge_requests` projects/merge_requests/merge_requests.rs
......@@ -206,8 +208,6 @@ instead of having to search the page for missing endpoints.
* `POST /projects/:project/labels/:label/subscribe` https://gitlab.kitware.com/help/api/labels.md#subscribe-to-a-label
* `POST /projects/:project/labels/:label/unsubscribe` https://gitlab.kitware.com/help/api/labels.md#unsubscribe-from-a-label
* `GET /projects/:project/languages` https://gitlab.kitware.com/help/api/projects.md#languages
* `GET /projects/:project/members/all` https://gitlab.kitware.com/help/api/members.md#list-all-members-of-a-group-or-project-including-inherited-members
* `GET /projects/:project/members/all/:id` https://gitlab.kitware.com/help/api/members.md#get-a-member-of-a-group-or-project-including-inherited-members
* `PUT /projects/:project/members/:id` https://gitlab.kitware.com/help/api/members.md#edit-a-member-of-a-group-or-project
* `DELETE /projects/:project/members/:id` https://gitlab.kitware.com/help/api/members.md#remove-a-member-from-a-group-or-project
* `DELETE /projects/:project/merge_requests/:merge_request` https://gitlab.kitware.com/help/api/merge_requests.md#delete-a-merge-request
......
......@@ -17,12 +17,24 @@ pub struct ProjectMember<'a> {
project: NameOrId<'a>,
/// The ID of the user.
user: u64,
// Whether to include ancestor users from enclosing Groups in the queried list of members.
#[builder(private)]
_include_ancestors: bool,
}
impl<'a> ProjectMember<'a> {
/// Create a builder for the endpoint.
pub fn builder() -> ProjectMemberBuilder<'a> {
ProjectMemberBuilder::default()
let mut builder = ProjectMemberBuilder::default();
builder._include_ancestors(false);
builder
}
/// Create an ancester-including builder for the endpoint.
pub fn all_builder() -> ProjectMemberBuilder<'a> {
let mut builder = ProjectMemberBuilder::default();
builder._include_ancestors = Some(true);
builder
}
}
......@@ -32,7 +44,11 @@ impl<'a> Endpoint for ProjectMember<'a> {
}
fn endpoint(&self) -> Cow<'static, str> {
format!("projects/{}/members/{}", self.project, self.user).into()
if self._include_ancestors {
format!("projects/{}/members/all/{}", self.project, self.user).into()
} else {
format!("projects/{}/members/{}", self.project, self.user).into()
}
}
}
......@@ -46,23 +62,37 @@ mod tests {
fn project_and_user_are_needed() {
let err = ProjectMember::builder().build().unwrap_err();
assert_eq!(err, "`project` must be initialized");
let err = ProjectMember::all_builder().build().unwrap_err();
assert_eq!(err, "`project` must be initialized");
}
#[test]
fn project_is_needed() {
let err = ProjectMember::builder().user(1).build().unwrap_err();
assert_eq!(err, "`project` must be initialized");
let err = ProjectMember::all_builder().user(1).build().unwrap_err();
assert_eq!(err, "`project` must be initialized");
}
#[test]
fn user_is_needed() {
let err = ProjectMember::builder().project(1).build().unwrap_err();
assert_eq!(err, "`user` must be initialized");
let err = ProjectMember::all_builder().project(1).build().unwrap_err();
assert_eq!(err, "`user` must be initialized");
}
#[test]
fn project_and_user_are_sufficient() {
ProjectMember::builder().project(1).user(1).build().unwrap();
ProjectMember::all_builder()
.project(1)
.user(1)
.build()
.unwrap();
}
#[test]
......@@ -80,4 +110,20 @@ mod tests {
.unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn endpoint_all() {
let endpoint = ExpectedUrl::builder()
.endpoint("projects/simple%2Fproject/members/all/1")
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = ProjectMember::all_builder()
.project("simple/project")
.user(1)
.build()
.unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
}
......@@ -25,12 +25,24 @@ pub struct ProjectMembers<'a> {
/// A search string to filter members by.
#[builder(setter(name = "_user_ids"), default, private)]
user_ids: BTreeSet<u64>,
// Whether to include ancestor users from enclosing Groups in the queried list of members.
#[builder(private)]
_include_ancestors: bool,
}
impl<'a> ProjectMembers<'a> {
/// Create a builder for the endpoint.
pub fn builder() -> ProjectMembersBuilder<'a> {
ProjectMembersBuilder::default()
let mut builder = ProjectMembersBuilder::default();
builder._include_ancestors(false);
builder
}
/// Create a builder for the endpoint.
pub fn all_builder() -> ProjectMembersBuilder<'a> {
let mut builder = ProjectMembersBuilder::default();
builder._include_ancestors(true);
builder
}
}
......@@ -59,7 +71,11 @@ impl<'a> Endpoint for ProjectMembers<'a> {
}
fn endpoint(&self) -> Cow<'static, str> {
format!("projects/{}/members", self.project).into()
if self._include_ancestors {
format!("projects/{}/members/all", self.project).into()
} else {
format!("projects/{}/members", self.project).into()
}
}
fn parameters(&self) -> QueryParams {
......@@ -85,11 +101,16 @@ mod tests {
fn project_is_needed() {
let err = ProjectMembers::builder().build().unwrap_err();
assert_eq!(err, "`project` must be initialized");
let err = ProjectMembers::all_builder().build().unwrap_err();
assert_eq!(err, "`project` must be initialized");
}
#[test]
fn project_is_sufficient() {
ProjectMembers::builder().project(1).build().unwrap();
ProjectMembers::all_builder().project(1).build().unwrap();
}
#[test]
......@@ -107,6 +128,21 @@ mod tests {
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn endpoint_all() {
let endpoint = ExpectedUrl::builder()
.endpoint("projects/simple%2Fproject/members/all")
.build()
.unwrap();
let client = SingleTestClient::new_raw(endpoint, "");
let endpoint = ProjectMembers::all_builder()
.project("simple/project")
.build()
.unwrap();
api::ignore(endpoint).query(&client).unwrap();
}
#[test]
fn endpoint_query() {
let endpoint = ExpectedUrl::builder()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment