Skip to content

Commit 4d358e9

Browse files
pvgritsenko-ansibleP. GritsenkoToa741
authored
Support query parameters in members and labels searching endpoints (#851)
* Support query parameters in projects/:id/labels, groups/:id/labels, projects/:id/members and groups/:id/members endpoints * Remove methods with optional parameters and add additional methods for binary compatibility * Extract query parameter adding to the separate methods * Fix the query parameters array type * fix the Label count properties type * Add UserIds and SkipUsers getters to the Unshipped.txt --------- Co-authored-by: P. Gritsenko <pavel.gritsenko@lanit-tercom.com> Co-authored-by: Thomas Cortes <78750681+Toa741@users.noreply.github.com>
1 parent 0880fab commit 4d358e9

12 files changed

+290
-35
lines changed

Diff for: NGitLab.Mock/Clients/LabelClient.cs

+10
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ public Models.Label EditGroupLabel(LabelEdit label)
151151
}
152152

153153
public IEnumerable<Models.Label> ForGroup(long groupId)
154+
{
155+
return ForGroup(groupId, query: null);
156+
}
157+
158+
public IEnumerable<Models.Label> ForGroup(long groupId, LabelQuery query)
154159
{
155160
using (Context.BeginOperationScope())
156161
{
@@ -160,6 +165,11 @@ public Models.Label EditGroupLabel(LabelEdit label)
160165
}
161166

162167
public IEnumerable<Models.Label> ForProject(long projectId)
168+
{
169+
return ForProject(projectId, query: null);
170+
}
171+
172+
public IEnumerable<Models.Label> ForProject(long projectId, LabelQuery query)
163173
{
164174
using (Context.BeginOperationScope())
165175
{

Diff for: NGitLab.Mock/Clients/MembersClient.cs

+24-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,15 @@ public MembersClient(ClientContext context)
1919

2020
public IEnumerable<Membership> OfProject(string projectId)
2121
{
22-
return OfProject(projectId, includeInheritedMembers: false);
22+
return OfProject(projectId, includeInheritedMembers: false, query: null);
2323
}
2424

2525
public IEnumerable<Membership> OfProject(string projectId, bool includeInheritedMembers)
26+
{
27+
return OfProject(projectId, includeInheritedMembers, query: null);
28+
}
29+
30+
public IEnumerable<Membership> OfProject(string projectId, bool includeInheritedMembers, MemberQuery query)
2631
{
2732
using (Context.BeginOperationScope())
2833
{
@@ -32,7 +37,12 @@ public IEnumerable<Membership> OfProject(string projectId, bool includeInherited
3237
}
3338
}
3439

35-
public GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers = false)
40+
public GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers)
41+
{
42+
return OfProjectAsync(projectId, includeInheritedMembers, query: null);
43+
}
44+
45+
public GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers = false, MemberQuery query = null)
3646
{
3747
return GitLabCollectionResponse.Create(OfProject(projectId.ValueAsString(), includeInheritedMembers));
3848
}
@@ -133,10 +143,15 @@ public IEnumerable<Membership> OfNamespace(string groupId)
133143

134144
public IEnumerable<Membership> OfGroup(string groupId)
135145
{
136-
return OfGroup(groupId, includeInheritedMembers: false);
146+
return OfGroup(groupId, includeInheritedMembers: false, null);
137147
}
138148

139149
public IEnumerable<Membership> OfGroup(string groupId, bool includeInheritedMembers)
150+
{
151+
return OfGroup(groupId, includeInheritedMembers, query: null);
152+
}
153+
154+
public IEnumerable<Membership> OfGroup(string groupId, bool includeInheritedMembers, MemberQuery query)
140155
{
141156
using (Context.BeginOperationScope())
142157
{
@@ -146,7 +161,12 @@ public IEnumerable<Membership> OfGroup(string groupId, bool includeInheritedMemb
146161
}
147162
}
148163

149-
public GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers = false)
164+
public GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers)
165+
{
166+
return OfGroupAsync(groupId, includeInheritedMembers, query: null);
167+
}
168+
169+
public GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers = false, MemberQuery query = null)
150170
{
151171
return GitLabCollectionResponse.Create(OfGroup(groupId.ValueAsString(), includeInheritedMembers));
152172
}

Diff for: NGitLab/ILabelClient.cs

+14
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,27 @@ public interface ILabelClient
1313
/// <returns></returns>
1414
IEnumerable<Label> ForProject(long projectId);
1515

16+
/// <summary>
17+
/// Return a list of labels for a project.
18+
/// </summary>
19+
/// <param name="projectId"></param>
20+
/// <returns></returns>
21+
IEnumerable<Label> ForProject(long projectId, LabelQuery labelQuery);
22+
1623
/// <summary>
1724
/// Return a list of labels for a group.
1825
/// </summary>
1926
/// <param name="groupId"></param>
2027
/// <returns></returns>
2128
IEnumerable<Label> ForGroup(long groupId);
2229

30+
/// <summary>
31+
/// Return a list of labels for a group.
32+
/// </summary>
33+
/// <param name="groupId"></param>
34+
/// <returns></returns>
35+
IEnumerable<Label> ForGroup(long groupId, LabelQuery labelQuery);
36+
2337
/// <summary>
2438
/// Return a specified label from the project or null;
2539
/// </summary>

Diff for: NGitLab/IMembersClient.cs

+10-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ public interface IMembersClient
1515

1616
IEnumerable<Membership> OfProject(string projectId, bool includeInheritedMembers);
1717

18-
GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers = false);
18+
IEnumerable<Membership> OfProject(string projectId, bool includeInheritedMembers, MemberQuery query);
19+
20+
GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers);
21+
22+
GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers = false, MemberQuery query = null);
1923

2024
Membership GetMemberOfProject(string projectId, string userId);
2125

@@ -40,7 +44,11 @@ public interface IMembersClient
4044

4145
IEnumerable<Membership> OfGroup(string groupId, bool includeInheritedMembers);
4246

43-
GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers = false);
47+
IEnumerable<Membership> OfGroup(string groupId, bool includeInheritedMembers, MemberQuery query);
48+
49+
GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers);
50+
51+
GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers = false, MemberQuery query = null);
4452

4553
Membership GetMemberOfGroup(string groupId, string userId);
4654

Diff for: NGitLab/Impl/LabelClient.cs

+33-4
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,31 @@ public LabelClient(API api)
2121

2222
public IEnumerable<Label> ForProject(long projectId)
2323
{
24-
return _api.Get().GetAll<Label>(string.Format(CultureInfo.InvariantCulture, ProjectLabelUrl, projectId));
24+
return ForProject(projectId, query: null);
25+
}
26+
27+
public IEnumerable<Label> ForProject(long projectId, LabelQuery query)
28+
{
29+
string url = AddLabelParameterQuery(string.Format(CultureInfo.InvariantCulture, ProjectLabelUrl, projectId), query);
30+
31+
return _api.Get().GetAll<Label>(url);
2532
}
2633

2734
public IEnumerable<Label> ForGroup(long groupId)
2835
{
29-
return _api.Get().GetAll<Label>(string.Format(CultureInfo.InvariantCulture, GroupLabelUrl, groupId));
36+
return ForGroup(groupId, query: null);
37+
}
38+
39+
public IEnumerable<Label> ForGroup(long groupId, LabelQuery query)
40+
{
41+
string url = AddLabelParameterQuery(string.Format(CultureInfo.InvariantCulture, GroupLabelUrl, groupId), query);
42+
43+
return _api.Get().GetAll<Label>(url);
3044
}
3145

3246
public Label GetProjectLabel(long projectId, string name)
3347
{
34-
return ForProject(projectId).FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.Ordinal));
48+
return ForProject(projectId, new LabelQuery() { Search = name }).FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.Ordinal));
3549
}
3650

3751
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -42,7 +56,7 @@ public Label GetLabel(long projectId, string name)
4256

4357
public Label GetGroupLabel(long groupId, string name)
4458
{
45-
return ForGroup(groupId).FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.Ordinal));
59+
return ForGroup(groupId, new LabelQuery() { Search = name }).FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.Ordinal));
4660
}
4761

4862
public Label CreateProjectLabel(long projectId, ProjectLabelCreate label)
@@ -125,4 +139,19 @@ public Label Delete(LabelDelete label)
125139
Name = label.Name,
126140
});
127141
}
142+
143+
private static string AddLabelParameterQuery(string url, LabelQuery query)
144+
{
145+
if (query == null)
146+
{
147+
return url;
148+
}
149+
150+
url = Utils.AddParameter(url, "with_counts", query.WithCounts);
151+
url = Utils.AddParameter(url, "per_page", query.PerPage);
152+
url = Utils.AddParameter(url, "search", query.Search);
153+
url = Utils.AddParameter(url, "include_ancestor_groups ", query.IncludeAncestorGroups);
154+
155+
return url;
156+
}
128157
}

Diff for: NGitLab/Impl/MembersClient.cs

+53-20
Original file line numberDiff line numberDiff line change
@@ -17,41 +17,43 @@ public MembersClient(API api)
1717
_api = api;
1818
}
1919

20-
private IEnumerable<Membership> GetAll(string url, bool includeInheritedMembers)
20+
private IEnumerable<Membership> GetAll(string url, bool includeInheritedMembers, MemberQuery query)
2121
{
22-
url += "/members";
23-
if (includeInheritedMembers)
24-
{
25-
url += "/all";
26-
}
22+
url = GetMemberUrlWithQueryParameters(url, includeInheritedMembers, query);
2723

2824
return _api.Get().GetAll<Membership>(url);
2925
}
3026

31-
private GitLabCollectionResponse<Membership> GetAllAsync(string url, bool includeInheritedMembers)
27+
private GitLabCollectionResponse<Membership> GetAllAsync(string url, bool includeInheritedMembers, MemberQuery query)
3228
{
33-
url += "/members";
34-
if (includeInheritedMembers)
35-
{
36-
url += "/all";
37-
}
29+
url = GetMemberUrlWithQueryParameters(url, includeInheritedMembers, query);
3830

3931
return _api.Get().GetAllAsync<Membership>(url);
4032
}
4133

4234
public IEnumerable<Membership> OfProject(string projectId)
4335
{
44-
return OfProject(projectId, includeInheritedMembers: false);
36+
return OfProject(projectId, includeInheritedMembers: false, query: null);
4537
}
4638

4739
public IEnumerable<Membership> OfProject(string projectId, bool includeInheritedMembers)
4840
{
49-
return GetAll($"{Project.Url}/{WebUtility.UrlEncode(projectId)}", includeInheritedMembers);
41+
return OfProject(projectId, includeInheritedMembers, query: null);
42+
}
43+
44+
public IEnumerable<Membership> OfProject(string projectId, bool includeInheritedMembers, MemberQuery query)
45+
{
46+
return GetAll($"{Project.Url}/{WebUtility.UrlEncode(projectId)}", includeInheritedMembers, query);
5047
}
5148

52-
public GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers = false)
49+
public GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers)
5350
{
54-
return GetAllAsync($"{Project.Url}/{projectId.ValueAsUriParameter()}", includeInheritedMembers);
51+
return OfProjectAsync(projectId, includeInheritedMembers, query: null);
52+
}
53+
54+
public GitLabCollectionResponse<Membership> OfProjectAsync(ProjectId projectId, bool includeInheritedMembers = false, MemberQuery query = null)
55+
{
56+
return GetAllAsync($"{Project.Url}/{projectId.ValueAsUriParameter()}", includeInheritedMembers, query);
5557
}
5658

5759
public Membership GetMemberOfProject(string projectId, string userId)
@@ -104,17 +106,27 @@ public IEnumerable<Membership> OfNamespace(string groupId)
104106

105107
public IEnumerable<Membership> OfGroup(string groupId)
106108
{
107-
return OfGroup(groupId, includeInheritedMembers: false);
109+
return OfGroup(groupId, includeInheritedMembers: false, null);
108110
}
109111

110112
public IEnumerable<Membership> OfGroup(string groupId, bool includeInheritedMembers)
111113
{
112-
return GetAll($"{Group.Url}/{WebUtility.UrlEncode(groupId)}", includeInheritedMembers);
114+
return OfGroup(groupId, includeInheritedMembers, query: null);
115+
}
116+
117+
public IEnumerable<Membership> OfGroup(string groupId, bool includeInheritedMembers, MemberQuery query)
118+
{
119+
return GetAll($"{Group.Url}/{WebUtility.UrlEncode(groupId)}", includeInheritedMembers, query);
120+
}
121+
122+
public GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers)
123+
{
124+
return OfGroupAsync(groupId, includeInheritedMembers, query: null);
113125
}
114126

115-
public GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers = false)
127+
public GitLabCollectionResponse<Membership> OfGroupAsync(GroupId groupId, bool includeInheritedMembers = false, MemberQuery query = null)
116128
{
117-
return GetAllAsync($"{Group.Url}/{groupId.ValueAsUriParameter()}", includeInheritedMembers);
129+
return GetAllAsync($"{Group.Url}/{groupId.ValueAsUriParameter()}", includeInheritedMembers, query);
118130
}
119131

120132
public Membership GetMemberOfGroup(string groupId, string userId)
@@ -158,4 +170,25 @@ public Task RemoveMemberFromGroupAsync(GroupId groupId, long userId, Cancellatio
158170
{
159171
return _api.Delete().ExecuteAsync($"{Group.Url}/{groupId.ValueAsUriParameter()}/members/{userId.ToStringInvariant()}", cancellationToken);
160172
}
173+
174+
private static string GetMemberUrlWithQueryParameters(string url, bool includeInheritedMembers, MemberQuery query)
175+
{
176+
url += "/members";
177+
if (includeInheritedMembers)
178+
{
179+
url += "/all";
180+
}
181+
182+
if (query != null)
183+
{
184+
url = Utils.AddParameter(url, "user_ids", query.UserIds);
185+
url = Utils.AddParameter(url, "state", query.State);
186+
url = Utils.AddParameter(url, "per_page ", query.PerPage);
187+
url = Utils.AddParameter(url, "query", query.Query);
188+
url = Utils.AddParameter(url, "show_seat_info", query.ShowSeatInfo);
189+
url = Utils.AddParameter(url, "skip_users", query.SkipUsers);
190+
}
191+
192+
return url;
193+
}
161194
}

Diff for: NGitLab/Impl/UserClient.cs

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public IEnumerable<User> Get(UserQuery query)
6565
url = Utils.AddParameter(url, "with_custom_attributes", query.WithCustomAttributes);
6666
url = Utils.AddParameter(url, "two_factor", query.TwoFactor);
6767
url = Utils.AddParameter(url, "admins", query.IsAdmin);
68+
url = Utils.AddParameter(url, "humans", query.IsHuman);
69+
url = Utils.AddParameter(url, "exclude_active", query.ExcludeActive);
70+
url = Utils.AddParameter(url, "exclude_humans", query.ExcludeHumans);
71+
url = Utils.AddParameter(url, "exclude_internal", query.ExcludeInternal);
6872

6973
return _api.Get().GetAll<User>(url);
7074
}

Diff for: NGitLab/Models/Label.cs

+9
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,13 @@ public class Label
1212

1313
[JsonPropertyName("description")]
1414
public string Description { get; set; }
15+
16+
[JsonPropertyName("open_issues_count")]
17+
public int OpenIssuesCount { get; set; }
18+
19+
[JsonPropertyName("closed_issues_count")]
20+
public int ClosedIssuesCount { get; set; }
21+
22+
[JsonPropertyName("open_merge_requests_count")]
23+
public int OpenMergeRequestsCount { get; set; }
1524
}

Diff for: NGitLab/Models/LabelQuery.cs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace NGitLab.Models;
2+
3+
public class LabelQuery
4+
{
5+
/// <summary>
6+
/// Specifies how many records per page (GitLab supports a maximum of 100 items per page and defaults to 20).
7+
/// </summary>
8+
public int? PerPage { get; set; }
9+
10+
/// <summary>
11+
/// Keyword to filter labels by.
12+
/// </summary>
13+
public string Search { get; set; }
14+
15+
/// <summary>
16+
/// Include ancestor groups. Defaults to true.
17+
/// </summary>
18+
public bool? IncludeAncestorGroups { get; set; }
19+
20+
/// <summary>
21+
/// Whether or not to include issue and merge request counts. Defaults to false.
22+
/// </summary>
23+
public bool? WithCounts { get; set; }
24+
}

0 commit comments

Comments
 (0)