Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add group labels and issues methods #99

Merged
merged 9 commits into from
Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/GitLabApiClient/GitLabClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ public GitLabClient(string hostUrl, string authenticationToken = "")
authenticationToken);

var projectQueryBuilder = new ProjectsQueryBuilder();
var projectIssuesQueryBuilder = new ProjectIssuesQueryBuilder();
var projectIssueNotesQueryBuilder = new ProjectIssueNotesQueryBuilder();
var issuesQueryBuilder = new IssuesQueryBuilder();
var mergeRequestsQueryBuilder = new MergeRequestsQueryBuilder();
var projectMilestonesQueryBuilder = new MilestonesQueryBuilder();
var projectMergeRequestsQueryBuilder = new ProjectMergeRequestsQueryBuilder();
var groupsQueryBuilder = new GroupsQueryBuilder();
var groupLabelsQueryBuilder = new GroupLabelsQueryBuilder();
var projectsGroupsQueryBuilder = new ProjectsGroupQueryBuilder();
var branchQueryBuilder = new BranchQueryBuilder();
var releaseQueryBuilder = new ReleaseQueryBuilder();
Expand All @@ -52,12 +52,12 @@ public GitLabClient(string hostUrl, string authenticationToken = "")
var pipelineQueryBuilder = new PipelineQueryBuilder();
var treeQueryBuilder = new TreeQueryBuilder();

Issues = new IssuesClient(_httpFacade, issuesQueryBuilder, projectIssuesQueryBuilder, projectIssueNotesQueryBuilder);
Issues = new IssuesClient(_httpFacade, issuesQueryBuilder, projectIssueNotesQueryBuilder);
Uploads = new UploadsClient(_httpFacade);
MergeRequests = new MergeRequestsClient(_httpFacade, mergeRequestsQueryBuilder, projectMergeRequestsQueryBuilder);
Projects = new ProjectsClient(_httpFacade, projectQueryBuilder, projectMilestonesQueryBuilder);
Users = new UsersClient(_httpFacade);
Groups = new GroupsClient(_httpFacade, groupsQueryBuilder, projectsGroupsQueryBuilder, projectMilestonesQueryBuilder);
Groups = new GroupsClient(_httpFacade, groupsQueryBuilder, projectsGroupsQueryBuilder, projectMilestonesQueryBuilder, groupLabelsQueryBuilder);
Branches = new BranchClient(_httpFacade, branchQueryBuilder);
Releases = new ReleaseClient(_httpFacade, releaseQueryBuilder);
Tags = new TagClient(_httpFacade, tagQueryBuilder);
Expand Down
93 changes: 72 additions & 21 deletions src/GitLabApiClient/GroupsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,35 @@ public sealed class GroupsClient
private readonly GroupsQueryBuilder _queryBuilder;
private readonly ProjectsGroupQueryBuilder _projectsQueryBuilder;
private readonly MilestonesQueryBuilder _queryMilestonesBuilder;
private readonly GroupLabelsQueryBuilder _queryGroupLabelBuilder;

internal GroupsClient(
GitLabHttpFacade httpFacade,
GroupsQueryBuilder queryBuilder,
ProjectsGroupQueryBuilder projectsQueryBuilder,
MilestonesQueryBuilder queryMilestonesBuilder)
MilestonesQueryBuilder queryMilestonesBuilder,
GroupLabelsQueryBuilder queryGroupLabelBuilder)
{
_httpFacade = httpFacade;
_queryBuilder = queryBuilder;
_projectsQueryBuilder = projectsQueryBuilder;
_queryMilestonesBuilder = queryMilestonesBuilder;
_queryGroupLabelBuilder = queryGroupLabelBuilder;
}

/// <summary>
/// Get all details of a group.
/// This endpoint can be accessed without authentication if the group is publicly accessible.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
public async Task<Group> GetAsync(GroupId groupId) =>
await _httpFacade.Get<Group>($"groups/{groupId}");

/// <summary>
/// Get all subgroups of a group.
/// This endpoint can be accessed without authentication if the group is publicly accessible.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
public async Task<IList<Group>> GetSubgroupsAsync(GroupId groupId) =>
await _httpFacade.GetPagedList<Group>($"groups/{groupId}/subgroups");

Expand Down Expand Up @@ -80,7 +83,7 @@ public async Task<IList<Group>> GetAsync(Action<GroupsQueryOptions> options = nu
/// Get a list of projects in this group.
/// When accessed without authentication, only public projects are returned.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="options">Groups projects retrieval options.</param>
/// <returns>Issues satisfying options.</returns>
public async Task<IList<Project>> GetProjectsAsync(GroupId groupId, Action<ProjectsGroupQueryOptions> options = null)
Expand All @@ -95,7 +98,7 @@ public async Task<IList<Project>> GetProjectsAsync(GroupId groupId, Action<Proje
/// <summary>
/// Get a list of members in this group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="search">A query string to search for members.</param>
/// <returns>Group members satisfying options.</returns>
public async Task<IList<Member>> GetMembersAsync(GroupId groupId, string search = null)
Expand All @@ -113,7 +116,7 @@ public async Task<IList<Member>> GetMembersAsync(GroupId groupId, string search
/// <summary>
/// Get a list of all members (including inherited) in this group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="search">A query string to search for members.</param>
/// <returns>Group members satisfying options.</returns>
public async Task<IList<Member>> GetAllMembersAsync(GroupId groupId, string search = null)
Expand All @@ -131,7 +134,7 @@ public async Task<IList<Member>> GetAllMembersAsync(GroupId groupId, string sear
/// <summary>
/// Adds a member to the group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="request">Create milestone request.</param>
/// <returns>Newly created milestone.</returns>
public async Task<Milestone> CreateMilestoneAsync(GroupId groupId, CreateGroupMilestoneRequest request)
Expand All @@ -143,7 +146,7 @@ public async Task<Milestone> CreateMilestoneAsync(GroupId groupId, CreateGroupMi
/// <summary>
/// Get a list of milestones in this group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="options">Query options.</param>
public async Task<IList<Milestone>> GetMilestonesAsync(GroupId groupId, Action<MilestonesQueryOptions> options = null)
{
Expand All @@ -157,7 +160,7 @@ public async Task<IList<Milestone>> GetMilestonesAsync(GroupId groupId, Action<M
/// <summary>
/// Retrieves a group milestone by its id.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="milestoneId">Id of the milestone.</param>
public async Task<Milestone> GetMilestoneAsync(GroupId groupId, int milestoneId) =>
await _httpFacade.Get<Milestone>($"groups/{groupId}/milestones/{milestoneId}");
Expand All @@ -174,7 +177,7 @@ public async Task<Group> CreateAsync(CreateGroupRequest request) =>
/// <summary>
/// Adds a user to a group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="request">Add group member request.</param>
/// <returns>Newly created membership.</returns>
public async Task<Member> AddMemberAsync(GroupId groupId, AddGroupMemberRequest request)
Expand All @@ -186,7 +189,7 @@ public async Task<Member> AddMemberAsync(GroupId groupId, AddGroupMemberRequest
/// <summary>
/// Updates a user's group membership.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="userId">The user ID of the member.</param>
/// <param name="request">Update group member request.</param>
/// <returns>Updated membership.</returns>
Expand All @@ -199,15 +202,15 @@ public async Task<Member> UpdateMemberAsync(GroupId groupId, int userId, AddGrou
/// <summary>
/// Removes a user as a member of the group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="userId">The user ID of the member.</param>
public async Task RemoveMemberAsync(GroupId groupId, int userId) =>
await _httpFacade.Delete($"groups/{groupId}/members/{userId}");

/// <summary>
/// Transfer a project to the Group namespace. Available only for admin
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="projectId">The ID, path or <see cref="Project"/> of the project.</param>
/// <returns>The newly updated group.</returns>
public async Task<Group> TransferAsync(GroupId groupId, ProjectId projectId) =>
Expand All @@ -218,15 +221,15 @@ public async Task<Group> TransferAsync(GroupId groupId, ProjectId projectId) =>
/// Only available to group owners and administrators.
/// </summary>
/// <returns>The updated group.</returns>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="request">Update group request.</param>
public async Task<Group> UpdateAsync(GroupId groupId, UpdateGroupRequest request) =>
await _httpFacade.Put<Group>($"groups/{groupId}", request);

/// <summary>
/// Updates an existing group milestone.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="milestoneId">The ID of the group's milestone.</param>
/// <param name="request">Update milestone request.</param>
/// <returns>Newly modified milestone.</returns>
Expand All @@ -240,14 +243,14 @@ public async Task<Milestone> UpdateMilestoneAsync(GroupId groupId, int milestone
/// Removes group with all projects inside.
/// Only available to group owners and administrators.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
public async Task DeleteAsync(GroupId groupId) =>
await _httpFacade.Delete($"groups/{groupId}");

/// <summary>
/// Deletes a group milestone. Only for user with developer access to the group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="milestoneId">The ID of the group's milestone.</param>
public async Task DeleteMilestoneAsync(GroupId groupId, int milestoneId) =>
await _httpFacade.Delete($"groups/{groupId}/milestones/{milestoneId}");
Expand All @@ -256,22 +259,22 @@ public async Task DeleteMilestoneAsync(GroupId groupId, int milestoneId) =>
/// Syncs the group with its linked LDAP group.
/// Only available to group owners and administrators.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
public async Task SyncLdapAsync(GroupId groupId) =>
await _httpFacade.Post($"groups/{groupId}/ldap_sync");

/// <summary>
/// Creates LDAP group link.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="request">Create LDAP group link request.</param>
public async Task CreateLdapLinkAsync(GroupId groupId, CreateLdapGroupLinkRequest request) =>
await _httpFacade.Post($"groups/{groupId}/ldap_group_links", request);

/// <summary>
/// Deletes a LDAP group link.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="cn">The CN of a LDAP group</param>
public async Task DeleteLdapLinkAsync(GroupId groupId, string cn) =>
await _httpFacade.Delete($"groups/{groupId}/ldap_group_links/{cn}");
Expand All @@ -280,10 +283,58 @@ public async Task DeleteLdapLinkAsync(GroupId groupId, string cn) =>
/// <summary>
/// Deletes a LDAP group link for a specific LDAP provider.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the project.</param>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="provider">Name of a LDAP provider</param>
/// <param name="cn">The CN of a LDAP group</param>
public async Task DeleteProviderLdapLinkAsync(GroupId groupId, string provider, string cn) =>
await _httpFacade.Delete($"groups/{groupId}/ldap_group_links/{provider}/{cn}");


/// <summary>
/// Get all labels for a given group.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="options">Query options</param>
public async Task<IList<GroupLabel>> GetLabelsAsync(GroupId groupId,
Action<GroupLabelsQueryOptions> options = null)
{
var labelOptions = new GroupLabelsQueryOptions();
options?.Invoke(labelOptions);

string url = _queryGroupLabelBuilder.Build($"groups/{groupId}/labels", labelOptions);
return await _httpFacade.GetPagedList<GroupLabel>(url);
}

/// <summary>
/// Creates new group label.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="request">Create label request.</param>
/// <returns>Newly created label.</returns>
public async Task<GroupLabel> CreateLabelAsync(GroupId groupId, CreateGroupLabelRequest request)
{
Guard.NotNull(request, nameof(request));
return await _httpFacade.Post<GroupLabel>($"groups/{groupId}/labels", request);
}

/// <summary>
/// Updates an existing label with new name or new color. At least one parameter is required, to update the label.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="request">Update label request.</param>
/// <returns>Newly modified label.</returns>
public async Task<GroupLabel> UpdateLabelAsync(GroupId groupId, UpdateGroupLabelRequest request)
{
Guard.NotNull(request, nameof(request));
return await _httpFacade.Put<GroupLabel>($"groups/{groupId}/labels", request);
}

/// <summary>
/// Deletes group labels.
/// </summary>
/// <param name="groupId">The ID, path or <see cref="Group"/> of the group.</param>
/// <param name="name">Name of the label.</param>
public async Task DeleteLabelAsync(GroupId groupId, string name) =>
await _httpFacade.Delete($"groups/{groupId}/labels?name={name}");
}
}
25 changes: 25 additions & 0 deletions src/GitLabApiClient/Internal/Queries/GroupLabelsQueryBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using GitLabApiClient.Models.Groups.Requests;

namespace GitLabApiClient.Internal.Queries
{
internal class GroupLabelsQueryBuilder : QueryBuilder<GroupLabelsQueryOptions>
{
#region Overrides of QueryBuilder<GroupLabelsQueryOptions>

/// <inheritdoc />
protected override void BuildCore(GroupLabelsQueryOptions options)
{
if (options.WithCounts)
{
Add("with_counts", true);
}

if (!options.IncludeAncestorGroups)
{
Add("include_ancestor_groups", false);
}
}

#endregion
}
}
15 changes: 15 additions & 0 deletions src/GitLabApiClient/Internal/Queries/IssuesQueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ protected override void BuildCore(IssuesQueryOptions options)

if (!options.Filter.IsNullOrEmpty())
Add("search", options.Filter);

if (options.IsConfidential)
Add("confidential", true);

if (options.CreatedBefore.HasValue)
Add("created_before", options.CreatedBefore.Value);

if (options.CreatedAfter.HasValue)
Add("created_after", options.CreatedAfter.Value);

if (options.UpdatedBefore.HasValue)
Add("updated_before", options.UpdatedBefore.Value);

if (options.UpdatedAfter.HasValue)
Add("updated_after", options.UpdatedAfter.Value);
}

private static string GetStateQueryValue(IssueState state)
Expand Down
24 changes: 0 additions & 24 deletions src/GitLabApiClient/Internal/Queries/ProjectIssuesQueryBuilder.cs

This file was deleted.

Loading