From 409c58658f0833ca10c3846d239906ffd73e0c7b Mon Sep 17 00:00:00 2001 From: notauserx Date: Mon, 5 Dec 2022 09:06:28 +0600 Subject: [PATCH 01/39] update models with updated permission enum --- .editorconfig | 3 ++ Octokit.Tests/SimpleJsonSerializerTests.cs | 4 +- Octokit/Models/Request/NewTeam.cs | 2 +- Octokit/Models/Request/Permission.cs | 47 ++++++++++++++++++++++ Octokit/Models/Request/UpdateTeam.cs | 2 +- Octokit/Models/Response/Team.cs | 4 +- 6 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..fda97d8aca --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +root=true +[*.cs] +end_of_line = lf \ No newline at end of file diff --git a/Octokit.Tests/SimpleJsonSerializerTests.cs b/Octokit.Tests/SimpleJsonSerializerTests.cs index a1265bd002..dde09fcc9b 100644 --- a/Octokit.Tests/SimpleJsonSerializerTests.cs +++ b/Octokit.Tests/SimpleJsonSerializerTests.cs @@ -472,12 +472,12 @@ public void ShouldDeserializeParentTeamWithNullPermission() var result = new SimpleJsonSerializer().Deserialize(teamJson); // original value works as expected - Assert.Equal(PermissionLevel.Admin, result.Permission.Value); + Assert.Equal(TeamPermission.Admin, result.Permission.Value); Assert.Equal("admin", result.Permission.StringValue); // parent permission is marked as null and cannot be parsed Assert.Equal("null", result.Parent.Permission.StringValue); - PermissionLevel value; + TeamPermission value; Assert.False(result.Parent.Permission.TryParse(out value)); } } diff --git a/Octokit/Models/Request/NewTeam.cs b/Octokit/Models/Request/NewTeam.cs index 23ba322dec..59c10f4fcb 100644 --- a/Octokit/Models/Request/NewTeam.cs +++ b/Octokit/Models/Request/NewTeam.cs @@ -55,7 +55,7 @@ public NewTeam(string name) /// /// The permission that new repositories will be added to the team with when none is specified (default: Pull) /// - public Permission? Permission { get; set; } + public NewTeamPermission? Permission { get; set; } /// /// Id of a team to set as the parent team diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs index 8e5eca5c3f..7b57fff902 100644 --- a/Octokit/Models/Request/Permission.cs +++ b/Octokit/Models/Request/Permission.cs @@ -39,4 +39,51 @@ public enum Permission [Parameter(Value = "pull")] Pull } + + /// + /// Deprecated. The permission that new repositories will be added to the team with when none is specified + /// Default: pull + /// Can be one of: pull, push + /// + [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] + public enum NewTeamPermission + { + /// + /// team members can pull, but not push to or administer these repositories + /// + [Parameter(Value = "pull")] + Pull, + + /// + /// team members can pull and push, but not administer these repositories + /// + [Parameter(Value = "push")] + Push + } + + /// + /// Deprecated. The permission that new repositories will be added to the team with when none is specified. + /// Default: pull + /// Can be one of: pull, push, admin + /// + public enum TeamPermission + { + /// + /// team members can pull, but not push to or administer these repositories + /// + [Parameter(Value = "pull")] + Pull, + + /// + /// team members can pull and push, but not administer these repositories + /// + [Parameter(Value = "push")] + Push, + + /// + /// team members can pull, push and administer these repositories. + /// + [Parameter(Value = "admin")] + Admin, + } } diff --git a/Octokit/Models/Request/UpdateTeam.cs b/Octokit/Models/Request/UpdateTeam.cs index 960019094d..d912e529b6 100644 --- a/Octokit/Models/Request/UpdateTeam.cs +++ b/Octokit/Models/Request/UpdateTeam.cs @@ -37,7 +37,7 @@ public UpdateTeam(string name) /// /// The permission that new repositories will be added to the team with when none is specified (default: Pull) /// - public Permission? Permission { get; set; } + public TeamPermission? Permission { get; set; } /// /// Id of a team to set as the parent team diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs index 99fba9ecca..97350ea977 100644 --- a/Octokit/Models/Response/Team.cs +++ b/Octokit/Models/Response/Team.cs @@ -12,7 +12,7 @@ public class Team { public Team() { } - public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, PermissionLevel permission, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) + public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamPermission permission, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) { Url = url; HtmlUrl = htmlUrl; @@ -73,7 +73,7 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri /// /// permission attached to this team /// - public StringEnum Permission { get; private set; } + public StringEnum Permission { get; private set; } /// /// how many members in this team From ce9df33d2eb066f543a94cd6e9d941be215cc8a7 Mon Sep 17 00:00:00 2001 From: notauserx Date: Tue, 6 Dec 2022 14:39:43 +0600 Subject: [PATCH 02/39] add suppress message attribute --- Octokit/Models/Request/Permission.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs index 7b57fff902..33cb2f376b 100644 --- a/Octokit/Models/Request/Permission.cs +++ b/Octokit/Models/Request/Permission.cs @@ -66,6 +66,7 @@ public enum NewTeamPermission /// Default: pull /// Can be one of: pull, push, admin /// + [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] public enum TeamPermission { /// From 0eed29270653a0f0b5ac8beba3eb41695514fcec Mon Sep 17 00:00:00 2001 From: notauserx Date: Tue, 6 Dec 2022 14:40:03 +0600 Subject: [PATCH 03/39] update integration tests --- Octokit.Tests.Integration/Clients/TeamsClientTests.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index ac9260270c..32b03ab9ed 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -33,6 +33,7 @@ public async Task CreatesTeam() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); + Assert.Equal(TeamPermission.Pull, team.Permission); Assert.Equal(1, team.MembersCount); Assert.Equal(1, team.ReposCount); @@ -445,10 +446,14 @@ public async Task UpdatesTeam() { var teamName = Helper.MakeNameWithTimestamp("updated-team"); var teamDescription = Helper.MakeNameWithTimestamp("updated description"); + + // setting TeamPermission.Admin fails with Octokit.ApiValidationException : Setting team permission to admin is no longer supported + var teamPermission = TeamPermission.Push; var update = new UpdateTeam(teamName) { Description = teamDescription, Privacy = TeamPrivacy.Closed, + Permission = teamPermission, ParentTeamId = parentTeamContext.TeamId }; @@ -457,6 +462,7 @@ public async Task UpdatesTeam() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); + Assert.Equal(teamPermission, team.Permission); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); } } From 9b6164a64869356dbbb388bd0ef18f6581e8b34d Mon Sep 17 00:00:00 2001 From: notauserx Date: Tue, 6 Dec 2022 16:22:11 +0600 Subject: [PATCH 04/39] refactor: new and legacy update teams endpint --- .../Clients/IObservableTeamsClient.cs | 9 +++- .../Clients/ObservableTeamsClient.cs | 18 +++++++- .../Clients/TeamsClientTests.cs | 41 ++++++++++++++++++- .../Reactive/ObservableTeamsClientTests.cs | 40 +++++++++++++++++- Octokit.Tests/Clients/TeamsClientTests.cs | 34 ++++++++++++++- Octokit/Clients/ITeamsClient.cs | 9 +++- Octokit/Clients/TeamsClient.cs | 19 ++++++++- Octokit/Helpers/ApiUrls.cs | 12 ++++++ 8 files changed, 172 insertions(+), 10 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 95d382a9bd..86ad332cf5 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -124,12 +124,19 @@ public interface IObservableTeamsClient /// Newly created IObservable Create(string org, NewTeam team); + /// + /// Updates a team + /// To edit a team, the authenticated user must either be an organization owner or a team maintainer + /// + /// updated for the current org + IObservable Update(string org, string teamSlug, UpdateTeam team); + /// /// Returns updated for the current org. /// /// Thrown when a general API error occurs. /// Updated - IObservable Update(int id, UpdateTeam team); + IObservable UpdateLegacy(int id, UpdateTeam team); /// /// Delete a team - must have owner permissions to this diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 9fa0d3f7ba..a6cdc82322 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -193,16 +193,30 @@ public IObservable Create(string org, NewTeam team) return _client.Create(org, team).ToObservable(); } + /// + /// Updates a team + /// To edit a team, the authenticated user must either be an organization owner or a team maintainer + /// + /// updated for the current org + public IObservable Update(string org, string teamSlug, UpdateTeam team) + { + Ensure.ArgumentNotNull(org, nameof(org)); + Ensure.ArgumentNotNull(teamSlug, nameof(teamSlug)); + Ensure.ArgumentNotNull(team, nameof(team)); + + return _client.Update(org, teamSlug, team).ToObservable(); + } + /// /// Returns updated for the current org. /// /// Thrown when a general API error occurs. /// Updated - public IObservable Update(int id, UpdateTeam team) + public IObservable UpdateLegacy(int id, UpdateTeam team) { Ensure.ArgumentNotNull(team, nameof(team)); - return _client.Update(id, team).ToObservable(); + return _client.UpdateLegacy(id, team).ToObservable(); } /// diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index 32b03ab9ed..7888461619 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using System.Net; using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; @@ -457,7 +456,7 @@ public async Task UpdatesTeam() ParentTeamId = parentTeamContext.TeamId }; - var team = await _github.Organization.Team.Update(teamContext.TeamId, update); + var team = await _github.Organization.Team.Update(Helper.Organization, teamContext.Team.Slug, update); Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); @@ -467,4 +466,42 @@ public async Task UpdatesTeam() } } } + + public class TheUpdateLegacyMethod + { + private readonly IGitHubClient _github; + + public TheUpdateLegacyMethod() + { + _github = Helper.GetAuthenticatedClient(); + } + + [OrganizationTest] + public async Task UpdatesTeamLegacy() + { + using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team")))) + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team-fixture")))) + { + var teamName = Helper.MakeNameWithTimestamp("updated-team"); + var teamDescription = Helper.MakeNameWithTimestamp("updated description"); + + // setting TeamPermission.Admin fails with Octokit.ApiValidationException : Setting team permission to admin is no longer supported + var update = new UpdateTeam(teamName) + { + Description = teamDescription, + Privacy = TeamPrivacy.Closed, + Permission = TeamPermission.Push, + ParentTeamId = parentTeamContext.TeamId + }; + + var team = await _github.Organization.Team.UpdateLegacy(teamContext.TeamId, update); + + Assert.Equal(teamName, team.Name); + Assert.Equal(teamDescription, team.Description); + Assert.Equal(TeamPrivacy.Closed, team.Privacy); + Assert.Equal(TeamPermission.Push, team.Permission); + Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); + } + } + } } diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index 87431a8f56..3c3255f67f 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -386,12 +386,50 @@ public async Task UpdatesTeam() ParentTeamId = parentTeamContext.TeamId }; - var team = await _github.Organization.Team.Update(teamContext.TeamId, update); + var team = await _github.Organization.Team.Update(Helper.Organization, teamContext.Team.Slug, update); Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); + + _github.Organization.Team.Delete(teamContext.TeamId); + } + } + } + + public class TheUpdateLegacyMethod + { + private readonly IObservableGitHubClient _github; + + public TheUpdateLegacyMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + } + + [OrganizationTest] + public async Task UpdatesTeamLegacy() + { + using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team")))) + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team-fixture")))) + { + var teamName = Helper.MakeNameWithTimestamp("updated-team"); + var teamDescription = Helper.MakeNameWithTimestamp("updated description"); + var update = new UpdateTeam(teamName) + { + Description = teamDescription, + Privacy = TeamPrivacy.Closed, + ParentTeamId = parentTeamContext.TeamId + }; + + var team = await _github.Organization.Team.UpdateLegacy(teamContext.TeamId, update); + + Assert.Equal(teamName, team.Name); + Assert.Equal(teamDescription, team.Description); + Assert.Equal(TeamPrivacy.Closed, team.Privacy); + Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); + + _github.Organization.Team.Delete(teamContext.TeamId); } } } diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs index a1b7179405..028138279e 100644 --- a/Octokit.Tests/Clients/TeamsClientTests.cs +++ b/Octokit.Tests/Clients/TeamsClientTests.cs @@ -169,7 +169,37 @@ public void RequestsTheCorrectUrl() var client = new TeamsClient(connection); var team = new UpdateTeam("Octokittens"); - client.Update(1, team); + var org = "org"; + var slug = "slug"; + client.Update(org, slug , team); + + connection.Received().Patch( + Arg.Is(u => u.ToString() == "orgs/org/teams/slug"), + team); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => client.Update(null, "b", new UpdateTeam("update-team"))); + await Assert.ThrowsAsync(() => client.Update("a", null, new UpdateTeam("update-team"))); + await Assert.ThrowsAsync(() => client.Update("a", "b", null)); + } + } + + public class TheUpdateTeamLegacyMethod + { + [Fact] + public void RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + var team = new UpdateTeam("Octokittens"); + + client.UpdateLegacy(1, team); connection.Received().Patch( Arg.Is(u => u.ToString() == "teams/1"), @@ -182,7 +212,7 @@ public async Task EnsuresNonNullArguments() var connection = Substitute.For(); var client = new TeamsClient(connection); - await Assert.ThrowsAsync(() => client.Update(1, null)); + await Assert.ThrowsAsync(() => client.UpdateLegacy(1, null)); } } diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index ec3321d081..2bd75202c5 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -125,12 +125,19 @@ public interface ITeamsClient /// Newly created Task Create(string org, NewTeam team); + /// + /// Updates a team + /// To edit a team, the authenticated user must either be an organization owner or a team maintainer + /// + /// updated for the current org + Task Update(string org, string teamSlug, UpdateTeam team); + /// /// Returns updated for the current org. /// /// Thrown when a general API error occurs. /// Updated - Task Update(int id, UpdateTeam team); + Task UpdateLegacy(int id, UpdateTeam team); /// /// Delte a team - must have owner permissions to this diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 2d01a3445b..53d267a536 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -227,13 +227,30 @@ public Task Create(string org, NewTeam team) return ApiConnection.Post(endpoint, team); } + /// + /// Updates a team + /// To edit a team, the authenticated user must either be an organization owner or a team maintainer + /// + /// updated for the current org + [ManualRoute("PATCH", "/orgs/{org}/teams/{team_slug}")] + public Task Update(string org, string teamSlug, UpdateTeam team) + { + Ensure.ArgumentNotNull(org, nameof(org)); + Ensure.ArgumentNotNull(teamSlug, nameof(teamSlug)); + Ensure.ArgumentNotNull(team, nameof(team)); + + var endpoint = ApiUrls.TeamsByOrganizationAndSlug(org, teamSlug); + return ApiConnection.Patch(endpoint, team); + throw new NotImplementedException(); + } + /// /// Returns updated for the current org. /// /// Thrown when a general API error occurs. /// Updated [ManualRoute("PATCH", "/teams/{team_id}")] - public Task Update(int id, UpdateTeam team) + public Task UpdateLegacy(int id, UpdateTeam team) { Ensure.ArgumentNotNull(team, nameof(team)); diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 9bff25de4b..c0612bb599 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1922,6 +1922,18 @@ public static Uri Teams(int id) return "teams/{0}".FormatUri(id); } + /// + /// Returns the for teams + /// use for updating, or deleteing a . + /// + /// + /// + /// + public static Uri TeamsByOrganizationAndSlug(string org, string teamSlug) + { + return "orgs/{0}/teams/{1}".FormatUri(org,teamSlug); + } + /// /// returns the for team member /// From 1ad585e652f57f86fa014d0e92c6d8dae824fed7 Mon Sep 17 00:00:00 2001 From: notauserx Date: Tue, 6 Dec 2022 16:54:06 +0600 Subject: [PATCH 05/39] refactor: add new delete team endpoint --- .../Clients/IObservableTeamsClient.cs | 10 ++++++- .../Clients/ObservableTeamsClient.cs | 20 +++++++++++-- .../Clients/TeamsClientTests.cs | 2 +- Octokit.Tests.Integration/Helper.cs | 8 ++--- .../Helpers/TeamContext.cs | 5 ++-- .../Reactive/ObservableTeamsClientTests.cs | 4 +-- Octokit.Tests/Clients/TeamsClientTests.cs | 30 ++++++++++++++++++- Octokit/Clients/ITeamsClient.cs | 12 ++++++-- Octokit/Clients/TeamsClient.cs | 21 +++++++++++-- 9 files changed, 93 insertions(+), 19 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 86ad332cf5..2a07c05c56 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -138,12 +138,20 @@ public interface IObservableTeamsClient /// Updated IObservable UpdateLegacy(int id, UpdateTeam team); + /// + /// To delete a team, the authenticated user must be an organization owner or team maintainer. + /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. + /// + /// Thrown when a general API error occurs. + /// + IObservable Delete(string org, string teamSlug); + /// /// Delete a team - must have owner permissions to this /// /// Thrown when a general API error occurs. /// - IObservable Delete(int id); + IObservable DeleteLegacy(int id); /// /// Adds a to a . diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index a6cdc82322..64205da691 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -220,13 +220,27 @@ public IObservable UpdateLegacy(int id, UpdateTeam team) } /// - /// Delete a team - must have owner permissions to this + /// To delete a team, the authenticated user must be an organization owner or team maintainer. + /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. /// /// Thrown when a general API error occurs. /// - public IObservable Delete(int id) + public IObservable Delete(string org, string teamSlug) { - return _client.Delete(id).ToObservable(); + Ensure.ArgumentNotNull(org, nameof(org)); + Ensure.ArgumentNotNull(teamSlug, nameof(teamSlug)); + + return _client.Delete(org, teamSlug).ToObservable(); + } + + /// + /// Delete a team - must have owner permissions to do this + /// + /// Thrown when a general API error occurs. + /// + public IObservable DeleteLegacy(int id) + { + return _client.DeleteLegacy(id).ToObservable(); } /// diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index 7888461619..bfaa9cadc8 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -36,7 +36,7 @@ public async Task CreatesTeam() Assert.Equal(1, team.MembersCount); Assert.Equal(1, team.ReposCount); - await github.Organization.Team.Delete(team.Id); + await github.Organization.Team.Delete(Helper.Organization, team.Slug); } } } diff --git a/Octokit.Tests.Integration/Helper.cs b/Octokit.Tests.Integration/Helper.cs index 49ca013140..d3faac3f5b 100644 --- a/Octokit.Tests.Integration/Helper.cs +++ b/Octokit.Tests.Integration/Helper.cs @@ -187,18 +187,18 @@ public static void DeleteRepo(IConnection connection, string owner, string name) catch { } } - public static void DeleteTeam(IConnection connection, Team team) + public static void DeleteTeamLegacy(IConnection connection, Team team) { if (team != null) - DeleteTeam(connection, team.Id); + DeleteTeamLegacy(connection, team.Id); } - public static void DeleteTeam(IConnection connection, int teamId) + public static void DeleteTeamLegacy(IConnection connection, int teamId) { try { var client = new GitHubClient(connection); - client.Organization.Team.Delete(teamId).Wait(TimeSpan.FromSeconds(15)); + client.Organization.Team.DeleteLegacy(teamId).Wait(TimeSpan.FromSeconds(15)); } catch { } } diff --git a/Octokit.Tests.Integration/Helpers/TeamContext.cs b/Octokit.Tests.Integration/Helpers/TeamContext.cs index c04ceb2774..702c0e6074 100644 --- a/Octokit.Tests.Integration/Helpers/TeamContext.cs +++ b/Octokit.Tests.Integration/Helpers/TeamContext.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Octokit.Tests.Integration.Helpers { @@ -34,7 +32,8 @@ public void Dispose() if (Invitations.Any()) Helper.DeleteInvitations(_connection, Invitations, TeamId); - Helper.DeleteTeam(_connection, Team); + // TODO :: incorporate the new delete team + Helper.DeleteTeamLegacy(_connection, Team); } } } diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index 3c3255f67f..e0c6bf33f9 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -393,7 +393,7 @@ public async Task UpdatesTeam() Assert.Equal(TeamPrivacy.Closed, team.Privacy); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); - _github.Organization.Team.Delete(teamContext.TeamId); + _github.Organization.Team.Delete(Helper.Organization, team.Slug); } } } @@ -429,7 +429,7 @@ public async Task UpdatesTeamLegacy() Assert.Equal(TeamPrivacy.Closed, team.Privacy); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); - _github.Organization.Team.Delete(teamContext.TeamId); + _github.Organization.Team.DeleteLegacy(teamContext.TeamId); } } } diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs index 028138279e..bed6b5412b 100644 --- a/Octokit.Tests/Clients/TeamsClientTests.cs +++ b/Octokit.Tests/Clients/TeamsClientTests.cs @@ -223,7 +223,35 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new TeamsClient(connection); - client.Delete(1); + + var org = "org"; + var slug = "slug"; + + client.Delete(org, slug); + + connection.Received().Delete( + Arg.Is(u => u.ToString() == "orgs/org/teams/slug")); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => client.Delete("a", null)); + await Assert.ThrowsAsync(() => client.Delete(null, "a")); + } + } + + public class TheDeleteTeamLegacuMethod + { + [Fact] + public void RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + client.DeleteLegacy(1); connection.Received().Delete( Arg.Is(u => u.ToString() == "teams/1")); diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 2bd75202c5..5d6d607faf 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -140,11 +140,19 @@ public interface ITeamsClient Task UpdateLegacy(int id, UpdateTeam team); /// - /// Delte a team - must have owner permissions to this + /// To delete a team, the authenticated user must be an organization owner or team maintainer. + /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. /// /// Thrown when a general API error occurs. /// - Task Delete(int id); + Task Delete(string org, string teamSlug); + + /// + /// Delete a team - must have owner permissions to do this + /// + /// Thrown when a general API error occurs. + /// + Task DeleteLegacy(int id); /// /// Adds a to a . diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 53d267a536..c8d3ef6f74 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -259,12 +259,29 @@ public Task UpdateLegacy(int id, UpdateTeam team) } /// - /// Delte a team - must have owner permissions to this + /// To delete a team, the authenticated user must be an organization owner or team maintainer. + /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. + /// + /// Thrown when a general API error occurs. + /// + [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}")] + public Task Delete(string org, string teamSlug) + { + Ensure.ArgumentNotNull(org, nameof(org)); + Ensure.ArgumentNotNull(teamSlug, nameof(teamSlug)); + + var endpoint = ApiUrls.TeamsByOrganizationAndSlug(org, teamSlug); + + return ApiConnection.Delete(endpoint); + } + + /// + /// Delete a team - must have owner permissions to do this /// /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/teams/{team_id}")] - public Task Delete(int id) + public Task DeleteLegacy(int id) { var endpoint = ApiUrls.Teams(id); From 3a3dbddd30a222a7ee0399245a263ad8a5cf1acf Mon Sep 17 00:00:00 2001 From: notauserx Date: Wed, 7 Dec 2022 10:59:15 +0600 Subject: [PATCH 06/39] use TeamPermission on NewTeam --- Octokit.Tests/SimpleJsonSerializerTests.cs | 6 ++--- Octokit/Models/Request/NewTeam.cs | 2 +- Octokit/Models/Request/Permission.cs | 29 +--------------------- 3 files changed, 5 insertions(+), 32 deletions(-) diff --git a/Octokit.Tests/SimpleJsonSerializerTests.cs b/Octokit.Tests/SimpleJsonSerializerTests.cs index dde09fcc9b..8047912568 100644 --- a/Octokit.Tests/SimpleJsonSerializerTests.cs +++ b/Octokit.Tests/SimpleJsonSerializerTests.cs @@ -450,7 +450,7 @@ public void ShouldDeserializeParentTeamWithNullPermission() ""slug"": ""justice-league"", ""description"": ""A great team."", ""privacy"": ""closed"", - ""permission"": ""admin"", + ""permission"": ""push"", ""members_url"": ""https://api.github.com/teams/1/members{/member}"", ""repositories_url"": ""https://api.github.com/teams/1/repos"", ""parent"": { @@ -472,8 +472,8 @@ public void ShouldDeserializeParentTeamWithNullPermission() var result = new SimpleJsonSerializer().Deserialize(teamJson); // original value works as expected - Assert.Equal(TeamPermission.Admin, result.Permission.Value); - Assert.Equal("admin", result.Permission.StringValue); + Assert.Equal(TeamPermission.Push, result.Permission.Value); + Assert.Equal("push", result.Permission.StringValue); // parent permission is marked as null and cannot be parsed Assert.Equal("null", result.Parent.Permission.StringValue); diff --git a/Octokit/Models/Request/NewTeam.cs b/Octokit/Models/Request/NewTeam.cs index 59c10f4fcb..d506705d7b 100644 --- a/Octokit/Models/Request/NewTeam.cs +++ b/Octokit/Models/Request/NewTeam.cs @@ -55,7 +55,7 @@ public NewTeam(string name) /// /// The permission that new repositories will be added to the team with when none is specified (default: Pull) /// - public NewTeamPermission? Permission { get; set; } + public TeamPermission? Permission { get; set; } /// /// Id of a team to set as the parent team diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs index 33cb2f376b..453700364b 100644 --- a/Octokit/Models/Request/Permission.cs +++ b/Octokit/Models/Request/Permission.cs @@ -46,27 +46,6 @@ public enum Permission /// Can be one of: pull, push /// [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] - public enum NewTeamPermission - { - /// - /// team members can pull, but not push to or administer these repositories - /// - [Parameter(Value = "pull")] - Pull, - - /// - /// team members can pull and push, but not administer these repositories - /// - [Parameter(Value = "push")] - Push - } - - /// - /// Deprecated. The permission that new repositories will be added to the team with when none is specified. - /// Default: pull - /// Can be one of: pull, push, admin - /// - [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] public enum TeamPermission { /// @@ -79,12 +58,6 @@ public enum TeamPermission /// team members can pull and push, but not administer these repositories /// [Parameter(Value = "push")] - Push, - - /// - /// team members can pull, push and administer these repositories. - /// - [Parameter(Value = "admin")] - Admin, + Push } } From 754bece5c650fb49a132a789f7d5ed72ec5abfed Mon Sep 17 00:00:00 2001 From: notauserx Date: Wed, 7 Dec 2022 18:42:04 +0600 Subject: [PATCH 07/39] use updated delete on team context dispose --- Octokit.Tests.Integration/Helper.cs | 8 ++++---- Octokit.Tests.Integration/Helpers/TeamContext.cs | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Octokit.Tests.Integration/Helper.cs b/Octokit.Tests.Integration/Helper.cs index d3faac3f5b..9c94d78f64 100644 --- a/Octokit.Tests.Integration/Helper.cs +++ b/Octokit.Tests.Integration/Helper.cs @@ -187,18 +187,18 @@ public static void DeleteRepo(IConnection connection, string owner, string name) catch { } } - public static void DeleteTeamLegacy(IConnection connection, Team team) + public static void DeleteTeam(IConnection connection, Team team) { if (team != null) - DeleteTeamLegacy(connection, team.Id); + DeleteTeam(connection, team.Slug); } - public static void DeleteTeamLegacy(IConnection connection, int teamId) + public static void DeleteTeam(IConnection connection, string slug) { try { var client = new GitHubClient(connection); - client.Organization.Team.DeleteLegacy(teamId).Wait(TimeSpan.FromSeconds(15)); + client.Organization.Team.Delete(Organization, slug).Wait(TimeSpan.FromSeconds(15)); } catch { } } diff --git a/Octokit.Tests.Integration/Helpers/TeamContext.cs b/Octokit.Tests.Integration/Helpers/TeamContext.cs index 702c0e6074..f4cc15a26b 100644 --- a/Octokit.Tests.Integration/Helpers/TeamContext.cs +++ b/Octokit.Tests.Integration/Helpers/TeamContext.cs @@ -32,8 +32,7 @@ public void Dispose() if (Invitations.Any()) Helper.DeleteInvitations(_connection, Invitations, TeamId); - // TODO :: incorporate the new delete team - Helper.DeleteTeamLegacy(_connection, Team); + Helper.DeleteTeam(_connection, Team); } } } From b354217d781888c4b6708c8b26fd1f0bc56b95e8 Mon Sep 17 00:00:00 2001 From: notauserx Date: Wed, 7 Dec 2022 20:51:02 +0600 Subject: [PATCH 08/39] add permission enum for team response object --- .../Clients/TeamsClientTests.cs | 12 ++++---- Octokit.Tests/SimpleJsonSerializerTests.cs | 8 ++--- Octokit/Models/Request/Permission.cs | 29 ++++++++++++++++++- Octokit/Models/Response/Team.cs | 4 +-- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index bfaa9cadc8..a38b2ac91d 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -32,7 +32,8 @@ public async Task CreatesTeam() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); - Assert.Equal(TeamPermission.Pull, team.Permission); + // Permission defaults to pull when no permission is specified when creating a team + Assert.Equal(TeamResponsePermission.Pull, team.Permission); Assert.Equal(1, team.MembersCount); Assert.Equal(1, team.ReposCount); @@ -446,13 +447,11 @@ public async Task UpdatesTeam() var teamName = Helper.MakeNameWithTimestamp("updated-team"); var teamDescription = Helper.MakeNameWithTimestamp("updated description"); - // setting TeamPermission.Admin fails with Octokit.ApiValidationException : Setting team permission to admin is no longer supported - var teamPermission = TeamPermission.Push; var update = new UpdateTeam(teamName) { Description = teamDescription, Privacy = TeamPrivacy.Closed, - Permission = teamPermission, + Permission = TeamPermission.Push, ParentTeamId = parentTeamContext.TeamId }; @@ -461,7 +460,7 @@ public async Task UpdatesTeam() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); - Assert.Equal(teamPermission, team.Permission); + Assert.Equal(TeamResponsePermission.Push, team.Permission); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); } } @@ -485,7 +484,6 @@ public async Task UpdatesTeamLegacy() var teamName = Helper.MakeNameWithTimestamp("updated-team"); var teamDescription = Helper.MakeNameWithTimestamp("updated description"); - // setting TeamPermission.Admin fails with Octokit.ApiValidationException : Setting team permission to admin is no longer supported var update = new UpdateTeam(teamName) { Description = teamDescription, @@ -499,7 +497,7 @@ public async Task UpdatesTeamLegacy() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); - Assert.Equal(TeamPermission.Push, team.Permission); + Assert.Equal(TeamResponsePermission.Push, team.Permission); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); } } diff --git a/Octokit.Tests/SimpleJsonSerializerTests.cs b/Octokit.Tests/SimpleJsonSerializerTests.cs index 8047912568..ec54b61ed7 100644 --- a/Octokit.Tests/SimpleJsonSerializerTests.cs +++ b/Octokit.Tests/SimpleJsonSerializerTests.cs @@ -450,7 +450,7 @@ public void ShouldDeserializeParentTeamWithNullPermission() ""slug"": ""justice-league"", ""description"": ""A great team."", ""privacy"": ""closed"", - ""permission"": ""push"", + ""permission"": ""admin"", ""members_url"": ""https://api.github.com/teams/1/members{/member}"", ""repositories_url"": ""https://api.github.com/teams/1/repos"", ""parent"": { @@ -472,12 +472,12 @@ public void ShouldDeserializeParentTeamWithNullPermission() var result = new SimpleJsonSerializer().Deserialize(teamJson); // original value works as expected - Assert.Equal(TeamPermission.Push, result.Permission.Value); - Assert.Equal("push", result.Permission.StringValue); + Assert.Equal(TeamResponsePermission.Admin, result.Permission.Value); + Assert.Equal("admin", result.Permission.StringValue); // parent permission is marked as null and cannot be parsed Assert.Equal("null", result.Parent.Permission.StringValue); - TeamPermission value; + TeamResponsePermission value; Assert.False(result.Parent.Permission.TryParse(out value)); } } diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs index 453700364b..23013e7477 100644 --- a/Octokit/Models/Request/Permission.cs +++ b/Octokit/Models/Request/Permission.cs @@ -47,6 +47,27 @@ public enum Permission /// [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] public enum TeamPermission + { + /// + /// team members can pull, but not push to these repositories + /// + [Parameter(Value = "pull")] + Pull, + + /// + /// team members can pull and push to these repositories + /// + [Parameter(Value = "push")] + Push + } + + /// + /// Deprecated. The permission that new repositories will be added to the team with when none is specified + /// Default: pull + /// Can be one of: pull, push or admin + /// + [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] + public enum TeamResponsePermission { /// /// team members can pull, but not push to or administer these repositories @@ -58,6 +79,12 @@ public enum TeamPermission /// team members can pull and push, but not administer these repositories /// [Parameter(Value = "push")] - Push + Push, + + /// + /// team members can pull, push and administer these repositories. + /// + [Parameter(Value = "admin")] + Admin, } } diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs index 97350ea977..9b29d99f84 100644 --- a/Octokit/Models/Response/Team.cs +++ b/Octokit/Models/Response/Team.cs @@ -12,7 +12,7 @@ public class Team { public Team() { } - public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamPermission permission, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) + public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamResponsePermission permission, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) { Url = url; HtmlUrl = htmlUrl; @@ -73,7 +73,7 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri /// /// permission attached to this team /// - public StringEnum Permission { get; private set; } + public StringEnum Permission { get; private set; } /// /// how many members in this team From a9765300b5fecd975eb9ddd2b1a55b837ac597b5 Mon Sep 17 00:00:00 2001 From: notauserx Date: Wed, 7 Dec 2022 21:27:33 +0600 Subject: [PATCH 09/39] refactor: remove legacy suffix from method names --- Octokit.Reactive/Clients/IObservableTeamsClient.cs | 8 ++++++-- Octokit.Reactive/Clients/ObservableTeamsClient.cs | 12 ++++++++---- .../Clients/TeamsClientTests.cs | 2 +- .../Reactive/ObservableTeamsClientTests.cs | 4 ++-- Octokit.Tests/Clients/TeamsClientTests.cs | 6 +++--- Octokit/Clients/ITeamsClient.cs | 8 ++++++-- Octokit/Clients/TeamsClient.cs | 8 ++++++-- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 2a07c05c56..c6bf9883e1 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -133,10 +133,12 @@ public interface IObservableTeamsClient /// /// Returns updated for the current org. + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Update a team endpoint /// /// Thrown when a general API error occurs. /// Updated - IObservable UpdateLegacy(int id, UpdateTeam team); + IObservable Update(int id, UpdateTeam team); /// /// To delete a team, the authenticated user must be an organization owner or team maintainer. @@ -148,10 +150,12 @@ public interface IObservableTeamsClient /// /// Delete a team - must have owner permissions to this + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Delete a team endpoint. /// /// Thrown when a general API error occurs. /// - IObservable DeleteLegacy(int id); + IObservable Delete(int id); /// /// Adds a to a . diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 64205da691..ce5f7824fd 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -209,14 +209,16 @@ public IObservable Update(string org, string teamSlug, UpdateTeam team) /// /// Returns updated for the current org. + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Update a team endpoint /// /// Thrown when a general API error occurs. /// Updated - public IObservable UpdateLegacy(int id, UpdateTeam team) + public IObservable Update(int id, UpdateTeam team) { Ensure.ArgumentNotNull(team, nameof(team)); - return _client.UpdateLegacy(id, team).ToObservable(); + return _client.Update(id, team).ToObservable(); } /// @@ -235,12 +237,14 @@ public IObservable Delete(string org, string teamSlug) /// /// Delete a team - must have owner permissions to do this + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Delete a team endpoint. /// /// Thrown when a general API error occurs. /// - public IObservable DeleteLegacy(int id) + public IObservable Delete(int id) { - return _client.DeleteLegacy(id).ToObservable(); + return _client.Delete(id).ToObservable(); } /// diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index a38b2ac91d..d6ace16714 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -492,7 +492,7 @@ public async Task UpdatesTeamLegacy() ParentTeamId = parentTeamContext.TeamId }; - var team = await _github.Organization.Team.UpdateLegacy(teamContext.TeamId, update); + var team = await _github.Organization.Team.Update(teamContext.TeamId, update); Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index e0c6bf33f9..e1823960ef 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -422,14 +422,14 @@ public async Task UpdatesTeamLegacy() ParentTeamId = parentTeamContext.TeamId }; - var team = await _github.Organization.Team.UpdateLegacy(teamContext.TeamId, update); + var team = await _github.Organization.Team.Update(teamContext.TeamId, update); Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); - _github.Organization.Team.DeleteLegacy(teamContext.TeamId); + _github.Organization.Team.Delete(teamContext.TeamId); } } } diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs index bed6b5412b..6dce430d77 100644 --- a/Octokit.Tests/Clients/TeamsClientTests.cs +++ b/Octokit.Tests/Clients/TeamsClientTests.cs @@ -199,7 +199,7 @@ public void RequestsTheCorrectUrl() var client = new TeamsClient(connection); var team = new UpdateTeam("Octokittens"); - client.UpdateLegacy(1, team); + client.Update(1, team); connection.Received().Patch( Arg.Is(u => u.ToString() == "teams/1"), @@ -212,7 +212,7 @@ public async Task EnsuresNonNullArguments() var connection = Substitute.For(); var client = new TeamsClient(connection); - await Assert.ThrowsAsync(() => client.UpdateLegacy(1, null)); + await Assert.ThrowsAsync(() => client.Update(1, null)); } } @@ -251,7 +251,7 @@ public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new TeamsClient(connection); - client.DeleteLegacy(1); + client.Delete(1); connection.Received().Delete( Arg.Is(u => u.ToString() == "teams/1")); diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 5d6d607faf..da92ff39c8 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -134,10 +134,12 @@ public interface ITeamsClient /// /// Returns updated for the current org. + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Update a team endpoint /// /// Thrown when a general API error occurs. /// Updated - Task UpdateLegacy(int id, UpdateTeam team); + Task Update(int id, UpdateTeam team); /// /// To delete a team, the authenticated user must be an organization owner or team maintainer. @@ -149,10 +151,12 @@ public interface ITeamsClient /// /// Delete a team - must have owner permissions to do this + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Delete a team endpoint. /// /// Thrown when a general API error occurs. /// - Task DeleteLegacy(int id); + Task Delete(int id); /// /// Adds a to a . diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index c8d3ef6f74..5dfbcd7b13 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -246,11 +246,13 @@ public Task Update(string org, string teamSlug, UpdateTeam team) /// /// Returns updated for the current org. + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Update a team endpoint /// /// Thrown when a general API error occurs. /// Updated [ManualRoute("PATCH", "/teams/{team_id}")] - public Task UpdateLegacy(int id, UpdateTeam team) + public Task Update(int id, UpdateTeam team) { Ensure.ArgumentNotNull(team, nameof(team)); @@ -277,11 +279,13 @@ public Task Delete(string org, string teamSlug) /// /// Delete a team - must have owner permissions to do this + /// This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Delete a team endpoint. /// /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/teams/{team_id}")] - public Task DeleteLegacy(int id) + public Task Delete(int id) { var endpoint = ApiUrls.Teams(id); From c22a76daa61a265cf07514e8311eefba61059a23 Mon Sep 17 00:00:00 2001 From: notauserx Date: Wed, 7 Dec 2022 23:49:19 +0600 Subject: [PATCH 10/39] introduce permissions object on Team --- Octokit/Models/Request/Permission.cs | 93 +++++++++++++++++++++++++--- Octokit/Models/Response/Team.cs | 8 ++- 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs index 23013e7477..6983bc936c 100644 --- a/Octokit/Models/Request/Permission.cs +++ b/Octokit/Models/Request/Permission.cs @@ -1,4 +1,6 @@ +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using Octokit.Internal; namespace Octokit @@ -10,19 +12,19 @@ namespace Octokit public enum Permission { /// - /// team members can pull, push and administer these repositories. + /// team members can pull, push and administer these repositories. /// [Parameter(Value = "admin")] Admin, /// - /// team members can manage the repository without access to sensitive or destructive actions. Recommended for project managers. Only applies to repositories owned by organizations. + /// team members can manage the repository without access to sensitive or destructive actions. Recommended for project managers. Only applies to repositories owned by organizations. /// [Parameter(Value = "maintain")] Maintain, /// - /// team members can proactively manage issues and pull requests without write access. Recommended for contributors who triage a repository. Only applies to repositories owned by organizations. + /// team members can proactively manage issues and pull requests without write access. Recommended for contributors who triage a repository. Only applies to repositories owned by organizations. /// [Parameter(Value = "triage")] Triage, @@ -64,27 +66,104 @@ public enum TeamPermission /// /// Deprecated. The permission that new repositories will be added to the team with when none is specified /// Default: pull - /// Can be one of: pull, push or admin /// [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] public enum TeamResponsePermission { /// - /// team members can pull, but not push to or administer these repositories + /// Can read and clone repository. + /// Can also open and comment on issues and pull requests. /// [Parameter(Value = "pull")] Pull, /// - /// team members can pull and push, but not administer these repositories + /// Can read and clone repository. + /// Can also manage issues and pull requests. + /// + [Parameter(Value = "triage")] + Triage, + + /// + /// Can read, clone, and push to repository. + /// Can also manage issues and pull requests. /// [Parameter(Value = "push")] Push, /// - /// team members can pull, push and administer these repositories. + /// Can read, clone, and push to repository. + /// They can also manage issues, pull requests, and some repository settings. + /// + [Parameter(Value = "maintain")] + Maintain, + + /// + /// Can read, clone, and push to repository. + /// Can also manage issues, pull requests, and repository settings, including adding collaborators. /// [Parameter(Value = "admin")] Admin, } + + /// + /// Object for team repository permissions + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class TeamRepositoryPermissions + { + public TeamRepositoryPermissions() { } + public TeamRepositoryPermissions(bool pull, bool triage, bool push, bool maintain, bool admin) + { + Pull = pull; + Triage = triage; + Push = push; + Maintain = maintain; + Admin = admin; + } + + /// + /// Can read and clone repository. + /// Can also open and comment on issues and pull requests. + /// Required + /// + public bool Pull { get; private set; } + + /// + /// Can read and clone repository. + /// Can also manage issues and pull requests. + /// Required + /// + public bool Triage { get; private set; } + + /// + /// Can read, clone, and push to repository. + /// Can also manage issues and pull requests. + /// Required + /// + public bool Push { get; private set; } + + /// + /// Can read, clone, and push to repository. + /// They can also manage issues, pull requests, and some repository settings. + /// Required + /// + public bool Maintain { get; private set; } + + /// + /// Can read, clone, and push to repository. + /// Can also manage issues, pull requests, and repository settings, including adding collaborators. + /// Required + /// + public bool Admin { get; private set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, + $"Permissions: Pull: {Pull}, Triage: {Triage}, Push: {Push}, Maintain: {Maintain}, Admin: {Admin}"); + } + } + } } diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs index 9b29d99f84..0878063791 100644 --- a/Octokit/Models/Response/Team.cs +++ b/Octokit/Models/Response/Team.cs @@ -12,7 +12,7 @@ public class Team { public Team() { } - public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamResponsePermission permission, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) + public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamResponsePermission permission, TeamRepositoryPermissions permissions, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) { Url = url; HtmlUrl = htmlUrl; @@ -23,6 +23,7 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri Description = description; Privacy = privacy; Permission = permission; + Permissions = permissions; MembersCount = membersCount; ReposCount = reposCount; Organization = organization; @@ -74,6 +75,11 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri /// permission attached to this team /// public StringEnum Permission { get; private set; } + + /// + /// + /// + public TeamRepositoryPermissions Permissions { get; private set; } /// /// how many members in this team From c5f0cf43ab7a0d50971bdf2b0e45dc6120f59063 Mon Sep 17 00:00:00 2001 From: notauserx Date: Wed, 7 Dec 2022 23:52:54 +0600 Subject: [PATCH 11/39] refactor: rename enum to TeamRepositoryPermission --- Octokit.Tests.Integration/Clients/TeamsClientTests.cs | 6 +++--- Octokit.Tests/SimpleJsonSerializerTests.cs | 4 ++-- Octokit/Models/Request/Permission.cs | 2 +- Octokit/Models/Response/Team.cs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index d6ace16714..3f1e971860 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -33,7 +33,7 @@ public async Task CreatesTeam() Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); // Permission defaults to pull when no permission is specified when creating a team - Assert.Equal(TeamResponsePermission.Pull, team.Permission); + Assert.Equal(TeamRespositoryPermission.Pull, team.Permission); Assert.Equal(1, team.MembersCount); Assert.Equal(1, team.ReposCount); @@ -460,7 +460,7 @@ public async Task UpdatesTeam() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); - Assert.Equal(TeamResponsePermission.Push, team.Permission); + Assert.Equal(TeamRespositoryPermission.Push, team.Permission); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); } } @@ -497,7 +497,7 @@ public async Task UpdatesTeamLegacy() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); - Assert.Equal(TeamResponsePermission.Push, team.Permission); + Assert.Equal(TeamRespositoryPermission.Push, team.Permission); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); } } diff --git a/Octokit.Tests/SimpleJsonSerializerTests.cs b/Octokit.Tests/SimpleJsonSerializerTests.cs index ec54b61ed7..e600e65c2e 100644 --- a/Octokit.Tests/SimpleJsonSerializerTests.cs +++ b/Octokit.Tests/SimpleJsonSerializerTests.cs @@ -472,12 +472,12 @@ public void ShouldDeserializeParentTeamWithNullPermission() var result = new SimpleJsonSerializer().Deserialize(teamJson); // original value works as expected - Assert.Equal(TeamResponsePermission.Admin, result.Permission.Value); + Assert.Equal(TeamRespositoryPermission.Admin, result.Permission.Value); Assert.Equal("admin", result.Permission.StringValue); // parent permission is marked as null and cannot be parsed Assert.Equal("null", result.Parent.Permission.StringValue); - TeamResponsePermission value; + TeamRespositoryPermission value; Assert.False(result.Parent.Permission.TryParse(out value)); } } diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs index 6983bc936c..498be7d256 100644 --- a/Octokit/Models/Request/Permission.cs +++ b/Octokit/Models/Request/Permission.cs @@ -68,7 +68,7 @@ public enum TeamPermission /// Default: pull /// [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] - public enum TeamResponsePermission + public enum TeamRespositoryPermission { /// /// Can read and clone repository. diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs index 0878063791..aa81ada99b 100644 --- a/Octokit/Models/Response/Team.cs +++ b/Octokit/Models/Response/Team.cs @@ -12,7 +12,7 @@ public class Team { public Team() { } - public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamResponsePermission permission, TeamRepositoryPermissions permissions, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) + public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamRespositoryPermission permission, TeamRepositoryPermissions permissions, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) { Url = url; HtmlUrl = htmlUrl; @@ -74,7 +74,7 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri /// /// permission attached to this team /// - public StringEnum Permission { get; private set; } + public StringEnum Permission { get; private set; } /// /// From 3b1617065d272a53800cfe8b56e0adda4f7b6e09 Mon Sep 17 00:00:00 2001 From: notauserx Date: Thu, 8 Dec 2022 00:11:01 +0600 Subject: [PATCH 12/39] fix formatting --- .editorconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index fda97d8aca..d605dc22d8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,3 @@ -root=true +root = true [*.cs] -end_of_line = lf \ No newline at end of file +end_of_line = lf From 76cfbff659e39e21c8bfa976f28a7edda570dd58 Mon Sep 17 00:00:00 2001 From: notauserx Date: Thu, 8 Dec 2022 09:15:33 +0600 Subject: [PATCH 13/39] change Permission to string to match api specs --- .../Clients/TeamsClientTests.cs | 6 +-- Octokit.Tests/SimpleJsonSerializerTests.cs | 7 +-- Octokit/Models/Request/Permission.cs | 43 ------------------- Octokit/Models/Response/Team.cs | 6 +-- 4 files changed, 8 insertions(+), 54 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index 3f1e971860..689beafffb 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -33,7 +33,7 @@ public async Task CreatesTeam() Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); // Permission defaults to pull when no permission is specified when creating a team - Assert.Equal(TeamRespositoryPermission.Pull, team.Permission); + Assert.Equal("pull", team.Permission); Assert.Equal(1, team.MembersCount); Assert.Equal(1, team.ReposCount); @@ -460,7 +460,7 @@ public async Task UpdatesTeam() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); - Assert.Equal(TeamRespositoryPermission.Push, team.Permission); + Assert.Equal("push", team.Permission); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); } } @@ -497,7 +497,7 @@ public async Task UpdatesTeamLegacy() Assert.Equal(teamName, team.Name); Assert.Equal(teamDescription, team.Description); Assert.Equal(TeamPrivacy.Closed, team.Privacy); - Assert.Equal(TeamRespositoryPermission.Push, team.Permission); + Assert.Equal("push", team.Permission); Assert.Equal(parentTeamContext.TeamId, team.Parent.Id); } } diff --git a/Octokit.Tests/SimpleJsonSerializerTests.cs b/Octokit.Tests/SimpleJsonSerializerTests.cs index e600e65c2e..040b7c107a 100644 --- a/Octokit.Tests/SimpleJsonSerializerTests.cs +++ b/Octokit.Tests/SimpleJsonSerializerTests.cs @@ -472,13 +472,10 @@ public void ShouldDeserializeParentTeamWithNullPermission() var result = new SimpleJsonSerializer().Deserialize(teamJson); // original value works as expected - Assert.Equal(TeamRespositoryPermission.Admin, result.Permission.Value); - Assert.Equal("admin", result.Permission.StringValue); + Assert.Equal("admin", result.Permission); // parent permission is marked as null and cannot be parsed - Assert.Equal("null", result.Parent.Permission.StringValue); - TeamRespositoryPermission value; - Assert.False(result.Parent.Permission.TryParse(out value)); + Assert.Null(result.Parent.Permission); } } diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs index 498be7d256..f3f94e003b 100644 --- a/Octokit/Models/Request/Permission.cs +++ b/Octokit/Models/Request/Permission.cs @@ -63,49 +63,6 @@ public enum TeamPermission Push } - /// - /// Deprecated. The permission that new repositories will be added to the team with when none is specified - /// Default: pull - /// - [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] - public enum TeamRespositoryPermission - { - /// - /// Can read and clone repository. - /// Can also open and comment on issues and pull requests. - /// - [Parameter(Value = "pull")] - Pull, - - /// - /// Can read and clone repository. - /// Can also manage issues and pull requests. - /// - [Parameter(Value = "triage")] - Triage, - - /// - /// Can read, clone, and push to repository. - /// Can also manage issues and pull requests. - /// - [Parameter(Value = "push")] - Push, - - /// - /// Can read, clone, and push to repository. - /// They can also manage issues, pull requests, and some repository settings. - /// - [Parameter(Value = "maintain")] - Maintain, - - /// - /// Can read, clone, and push to repository. - /// Can also manage issues, pull requests, and repository settings, including adding collaborators. - /// - [Parameter(Value = "admin")] - Admin, - } - /// /// Object for team repository permissions /// diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs index aa81ada99b..bff651938e 100644 --- a/Octokit/Models/Response/Team.cs +++ b/Octokit/Models/Response/Team.cs @@ -12,7 +12,7 @@ public class Team { public Team() { } - public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, TeamRespositoryPermission permission, TeamRepositoryPermissions permissions, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) + public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, string permission, TeamRepositoryPermissions permissions, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) { Url = url; HtmlUrl = htmlUrl; @@ -72,9 +72,9 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri public StringEnum Privacy { get; private set; } /// - /// permission attached to this team + /// Deprecated. The permission that new repositories will be added to the team with when none is specified /// - public StringEnum Permission { get; private set; } + public string Permission { get; private set; } /// /// From d05c0cd7b9f79e63978a8c80f9f44b593df7073c Mon Sep 17 00:00:00 2001 From: notauserx Date: Thu, 8 Dec 2022 12:34:41 +0600 Subject: [PATCH 14/39] add TeamRepository --- Octokit/Models/Response/TeamRepository.cs | 608 ++++++++++++++++++++++ 1 file changed, 608 insertions(+) create mode 100644 Octokit/Models/Response/TeamRepository.cs diff --git a/Octokit/Models/Response/TeamRepository.cs b/Octokit/Models/Response/TeamRepository.cs new file mode 100644 index 0000000000..dc3b5c12cc --- /dev/null +++ b/Octokit/Models/Response/TeamRepository.cs @@ -0,0 +1,608 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + /// + /// A teams's repository + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class TeamRepository + { + public TeamRepository() { } + + public TeamRepository(int id, + string nodeId, + string name, + string fullName, + LicenseMetadata license, + TeamRepositoryPermissions permissions, + string roleName, + User owner, + bool @private, + string htmlUrl, + string description, + bool fork, + string url, + string archiveUrl, + string assigneesUrl, + string blobsUrl, + string branchesUrl, + string collaboratorsUrl, + string commentsUrl, + string commitsUrl, + string compareUrl, + string contentsUrl, + string contributorsUrl, + string deploymentsUrl, + string downloadsUrl, + string eventsUrl, + string forksUrl, + string gitCommitUrl, + string gitRefsUrl, + string gitTagsUrl, + string gitUrl, + string issueCommentUrl, + string issueEventsUrl, + string issuesUrl, + string keysUrl, + string labelsUrl, + string languagesUrl, + string mergesUrl, + string milestonesUrl, + string notificationsUrl, + string pullsUrl, + string releasesUrl, + string sshUrl, + string stargazersUrl, + string statusesUrl, + string subscribersUrl, + string subscriptionUrl, + string tagsUrl, + string teamsUrl, + string treesUrl, + string cloneUrl, + string mirrorUrl, + string hooksUrl, + string svnUrl, + string homePage, + string language, + int forksCount, + int stargazersCount, + int watchersCount, + int size, + string defaultBranch, + int openIssuesCount, + bool isTemplate, + ICollection topics, + bool hasIssues, + bool hasProjects, + bool hasWiki, + bool hasPages, + bool hasDownloads, + bool archived, + bool disabled, + RepositoryVisibility? visibility, + DateTimeOffset? pushedAt, + DateTimeOffset createdAt, + DateTimeOffset updatedAt, + bool? allowRebaseMerge, + Repository templateRepository, + string tempCloneToken, + bool? allowSquashMerge, + bool? allowAutoMerge, + bool? deleteBranchOnMerge, + bool? allowMergeCommit, + bool? allowForking, + bool? webCommitSignoffRequired, + int subscribersCount, + int networkCount, + int openIssues, + int watchers, + string masterBranch) + { + Id = id; + NodeId = nodeId; + Name = name; + FullName = fullName; + License = license; + Permissions = permissions; + RoleName = roleName; + Owner = owner; + Private = @private; + HtmlUrl = htmlUrl; + Description = description; + Fork = fork; + Url = url; + ArchiveUrl = archiveUrl; + AssigneesUrl = assigneesUrl; + BlobsUrl = blobsUrl; + BranchesUrl = branchesUrl; + CollaboratorsUrl = collaboratorsUrl; + CommentsUrl = commentsUrl; + CommitsUrl = commitsUrl; + CompareUrl = compareUrl; + ContentsUrl = contentsUrl; + ContributorsUrl = contributorsUrl; + DeploymentsUrl = deploymentsUrl; + DownloadsUrl = downloadsUrl; + EventsUrl = eventsUrl; + ForksUrl = forksUrl; + GitCommitUrl = gitCommitUrl; + GitRefsUrl = gitRefsUrl; + GitTagsUrl = gitTagsUrl; + GitUrl = gitUrl; + IssueCommentUrl = issueCommentUrl; + IssueEventsUrl = issueEventsUrl; + IssuesUrl = issuesUrl; + KeysUrl = keysUrl; + LabelsUrl = labelsUrl; + LanguagesUrl = languagesUrl; + MergesUrl = mergesUrl; + MilestonesUrl = milestonesUrl; + NotificationsUrl = notificationsUrl; + PullsUrl = pullsUrl; + ReleasesUrl = releasesUrl; + SshUrl = sshUrl; + StargazersUrl = stargazersUrl; + StatusesUrl = statusesUrl; + SubscribersUrl = subscribersUrl; + SubscriptionUrl = subscriptionUrl; + TagsUrl = tagsUrl; + TeamsUrl = teamsUrl; + TreesUrl = treesUrl; + CloneUrl = cloneUrl; + MirrorUrl = mirrorUrl; + HooksUrl = hooksUrl; + SvnUrl = svnUrl; + HomePage = homePage; + Language = language; + ForksCount = forksCount; + StargazersCount = stargazersCount; + WatchersCount = watchersCount; + Size = size; + DefaultBranch = defaultBranch; + OpenIssuesCount = openIssuesCount; + IsTemplate = isTemplate; + Topics = topics; + HasIssues = hasIssues; + HasProjects = hasProjects; + HasWiki = hasWiki; + HasPages = hasPages; + HasDownloads = hasDownloads; + Archived = archived; + Disabled = disabled; + Visibility = visibility; + PushedAt = pushedAt; + CreatedAt = createdAt; + UpdatedAt = updatedAt; + AllowRebaseMerge = allowRebaseMerge; + TemplateRepository = templateRepository; + TempCloneToken = tempCloneToken; + AllowSquashMerge = allowSquashMerge; + AllowAutoMerge = allowAutoMerge; + DeleteBranchOnMerge = deleteBranchOnMerge; + AllowMergeCommit = allowMergeCommit; + AllowForking = allowForking; + WebCommitSignoffRequired = webCommitSignoffRequired; + SubscribersCount = subscribersCount; + NetworkCount = networkCount; + OpenIssues = openIssues; + Watchers = watchers; + MasterBranch = masterBranch; + } + + + /// + /// Unique identifier of the repository + /// + public int Id { get; private set; } + + /// + /// GraphQL Node Id + /// + public string NodeId { get; private set; } + + /// + /// The name of the repository + /// + public string Name { get; private set; } + + /// + /// example: octocat/Hello-World + /// + public string FullName { get; set; } + + public LicenseMetadata License { get; private set; } + + public TeamRepositoryPermissions Permissions { get; private set; } + + public string RoleName { get; private set; } + + public User Owner { get; private set; } + + /// + /// hether the repository is private or public. + /// default: false + /// + public bool Private { get; private set; } + + /// + /// format: uri + /// example: https://github.com/octocat/Hello-World + /// + public string HtmlUrl { get; private set; } + + /// + /// example: This your first repo! + /// nullable: true + /// + public string Description { get; private set; } + + public bool Fork { get; private set; } + + /// + /// format: uri + /// example: https://api.github.com/repos/octocat/Hello-World + /// + public string Url { get; set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref} + /// + public string ArchiveUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/assignees{/user} + /// + public string AssigneesUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha} + /// + public string BlobsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/branches{/branch} + /// + public string BranchesUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator} + /// + public string CollaboratorsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/comments{/number} + /// + public string CommentsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/commits{/sha} + /// + public string CommitsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head} + /// + public string CompareUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/contents/{+path} + /// + public string ContentsUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/contributors + /// + public string ContributorsUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/deployments + /// + public string DeploymentsUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/downloads + /// + public string DownloadsUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/events + /// + public string EventsUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/forks + /// + public string ForksUrl { get; private set; } + ///example: http://api.github.com/repos/octocat/Hello-World/git/commits{/sha} + public string GitCommitUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/git/refs{/sha} + /// + public string GitRefsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/git/tags{/sha} + /// + public string GitTagsUrl { get; private set; } + + /// + /// example: git:github.com/octocat/Hello-World.git + /// + public string GitUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/issues/comments{/number} + /// + public string IssueCommentUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/issues/events{/number} + /// + public string IssueEventsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/issues{/number} + /// + public string IssuesUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/keys{/key_id} + /// + public string KeysUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/labels{/name} + /// + public string LabelsUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/languages + /// + public string LanguagesUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/merges + /// + public string MergesUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/milestones{/number} + /// + public string MilestonesUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating} + /// + public string NotificationsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/pulls{/number} + /// + public string PullsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/releases{/id} + /// + public string ReleasesUrl { get; private set; } + + /// + /// example: git @github.com:octocat/Hello-World.git + /// + /// + public string SshUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/stargazers + /// + public string StargazersUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/statuses/{sha} + /// + public string StatusesUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/subscribers + /// + public string SubscribersUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/subscription + /// + public string SubscriptionUrl { get; private set; } + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/tags + /// + public string TagsUrl { get; private set; } + + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/teams + /// + public string TeamsUrl { get; private set; } + + /// + /// example: http://api.github.com/repos/octocat/Hello-World/git/trees{/sha} + /// + public string TreesUrl { get; private set; } + + /// + /// example: https://github.com/octocat/Hello-World.git + /// + public string CloneUrl { get; private set; } + + /// + /// format: uri + /// example: git:git.example.com/octocat/Hello-World + /// nullable: true + /// + public string MirrorUrl { get; private set; } + + + /// + /// format: uri + /// example: http://api.github.com/repos/octocat/Hello-World/hooks + /// + public string HooksUrl { get; private set; } + + /// + /// format: uri + /// example: https://svn.github.com/octocat/Hello-World + /// + public string SvnUrl { get; private set; } + + /// + /// format: uri + /// example: https://github.com + /// + public string HomePage { get; private set; } + + public string Language { get; private set; } + + public int ForksCount { get; private set; } + + public int StargazersCount { get; private set; } + + public int WatchersCount { get; private set; } + + public int Size { get; private set; } + + /// + /// he default branch of the repository. + /// example: master + /// + public string DefaultBranch { get; private set; } + + public int OpenIssuesCount { get; set; } + + /// + /// Whether this repository acts as a template that can be used to generate new repositories + /// default: false + /// + public bool IsTemplate { get; private set; } + + public ICollection Topics { get; private set; } + + /// + /// Whether issues are enabled. + /// + public bool HasIssues { get; private set; } + + /// + /// Whether projects are enabled. + /// + public bool HasProjects { get; private set; } + + /// + /// Whether the wiki is enabled + /// + public bool HasWiki { get; private set; } + + public bool HasPages { get; private set; } + + /// + /// Whether downloads are enabled + /// default: true + /// + public bool HasDownloads { get; private set; } + + /// + /// Whether the repository is archived + /// + public bool Archived { get; private set; } + + /// + /// Returns whether or not this repository disabled. + /// + public bool Disabled { get; private set; } + + /// + /// The repository visibility: public, private, or internal. + /// + public RepositoryVisibility? Visibility { get; private set; } + + /// + /// format: date-time + /// example: '2011-01-26T19:06:43Z' + /// + public DateTimeOffset? PushedAt { get; private set; } + + public DateTimeOffset CreatedAt { get; private set; } + + public DateTimeOffset UpdatedAt { get; private set; } + + /// + /// Whether to allow rebase merges for pull requests. + /// + public bool? AllowRebaseMerge { get; private set; } + + // TODO :: is Repository nullable-repository? + public Repository TemplateRepository { get; private set; } + + public string TempCloneToken { get; private set; } + + /// + /// Whether to allow squash merges for pull requests. + /// + public bool? AllowSquashMerge { get; private set; } + + /// + /// Whether to allow Auto-merge to be used on pull requests. + /// + public bool? AllowAutoMerge { get; private set; } + + /// + /// Whether to delete head branches when pull requests are merged + /// + public bool? DeleteBranchOnMerge { get; private set; } + + /// + /// hether to allow merge commits for pull requests. + /// + public bool? AllowMergeCommit { get; private set; } + + /// + /// Whether to allow forking this repo + /// + public bool? AllowForking { get; private set; } + + /// + /// Whether to require contributors to sign off on web-based commits + /// + public bool? WebCommitSignoffRequired { get; private set; } + + public int SubscribersCount { get; private set; } + + public int NetworkCount { get; private set; } + + public int OpenIssues { get; private set; } + + public int Watchers { get; private set; } + + public string MasterBranch { get; private set; } + + internal string DebuggerDisplay + { + get { return string.Format(CultureInfo.InvariantCulture, "Name: {0} ", FullName); } + } + } +} From baee28542f4ceb512fce642db4e4a3446f277449 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 08:01:51 +0600 Subject: [PATCH 15/39] add CheckTeamPermission endpoint support --- .../Clients/IObservableTeamsClient.cs | 21 ++++++ .../Clients/ObservableTeamsClient.cs | 24 +++++++ .../Clients/TeamsClientTests.cs | 65 +++++++++++++++++++ .../ObservableGithubClientExtensions.cs | 7 ++ .../Reactive/ObservableTeamsClientTests.cs | 64 ++++++++++++++++++ Octokit/Clients/ITeamsClient.cs | 21 ++++++ Octokit/Clients/TeamsClient.cs | 33 ++++++++++ Octokit/Helpers/ApiUrls.cs | 12 ++++ 8 files changed, 247 insertions(+) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index c6bf9883e1..8e8b005517 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -276,5 +276,26 @@ public interface IObservableTeamsClient /// Options to change API behaviour. /// IObservable GetAllPendingInvitations(int id, ApiOptions options); + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// privides repository as a media typ in accepts header + /// + /// + /// 200 Alternative response with repository permissions + /// This is the response when the repository media type has been provded in the Accept header. + /// 204 Response if team has permission for the repository. + /// This is the response when the repository media type hasn't been provded in the Accept header. + /// 404 Not Found if team does not have permission for the repository + /// + /// + IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, + bool provideRepositoryMediaTypeInAcceptHeader = false); } } diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index ce5f7824fd..481d25911e 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -423,5 +423,29 @@ public IObservable GetAllPendingInvitations(in return _connection.GetAndFlattenAllPages(ApiUrls.TeamPendingInvitations(id), null, options); } + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// privides repository as a media typ in accepts header + /// + /// + /// 200 Alternative response with repository permissions + /// This is the response when the repository media type has been provded in the Accept header. + /// 204 Response if team has permission for the repository. + /// This is the response when the repository media type hasn't been provded in the Accept header. + /// 404 Not Found if team does not have permission for the repository + /// + /// + public IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, + bool provideRepositoryMediaTypeInAcceptHeader = false) + { + return _client.CheckTeamPermissionsForARepository(org, teamSlug, owner, repo, provideRepositoryMediaTypeInAcceptHeader).ToObservable(); + } } } diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index 689beafffb..0910634c00 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -502,4 +502,69 @@ public async Task UpdatesTeamLegacy() } } } + + public class CheckTeamPermissionsForARepositoryMethod + { + [OrganizationTest] + public async Task ChecksTeamPermissions() + { + var github = Helper.GetAuthenticatedClient(); + var team = github.Organization.Team.GetAll(Helper.Organization).Result.First(); + + using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + + var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName, + true); + + Assert.Null(teamPermission); + } + } + + [OrganizationTest] + public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() + { + var github = Helper.GetAuthenticatedClient(); + var team = github.Organization.Team.GetAll(Helper.Organization).Result.First(); + + using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + + var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName, + true); + + Assert.NotNull(teamPermission); + Assert.NotNull(teamPermission.Permissions); + Assert.True(teamPermission.Permissions.Pull); + } + } + + [OrganizationTest] + public async Task ChecksTeamPermissionsThrowNotFoundException() + { + var github = Helper.GetAuthenticatedClient(); + var team = github.Organization.Team.GetAll(Helper.Organization).Result.First(); + + using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + await Assert.ThrowsAsync(async () => + await github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName, + false)); + } + } + } } diff --git a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs index 5c52a61246..506f27cca7 100644 --- a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs +++ b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs @@ -36,6 +36,13 @@ internal static async Task CreateTeamContext(this IObservableGitHub return new TeamContext(client.Connection, team); } + internal static async Task CreateOrganizationRepositoryContext(this IObservableGitHubClient client, string organizationLogin, NewRepository newRepository) + { + var repo = await client.Repository.Create(organizationLogin, newRepository); + + return new RepositoryContext(client.Connection, repo); + } + internal static async Task CreateEnterpriseUserContext(this IObservableGitHubClient client, NewUser newUser) { var user = await client.User.Administration.Create(newUser); diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index e1823960ef..8f1649382b 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -433,4 +433,68 @@ public async Task UpdatesTeamLegacy() } } } + + public class CheckTeamPermissionsForARepositoryMethod + { + [OrganizationTest] + public async Task ChecksTeamPermissions() + { + var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + var team = await github.Organization.Team.GetAll(Helper.Organization).FirstAsync(); + + using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + + var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName); + + Assert.Null(teamPermission); + } + } + + [OrganizationTest] + public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() + { + var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + var team = await github.Organization.Team.GetAll(Helper.Organization).FirstAsync(); + + using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + + var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName, + true); + + Assert.NotNull(teamPermission); + Assert.NotNull(teamPermission.Permissions); + Assert.True(teamPermission.Permissions.Pull); + } + } + + [OrganizationTest] + public async Task ChecksTeamPermissionsThrowNotFoundException() + { + var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + var team = await github.Organization.Team.GetAll(Helper.Organization).FirstAsync(); + + using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + await Assert.ThrowsAsync(async () => + await github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName, + false)); + } + } + } } diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index da92ff39c8..20e23e6feb 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -268,5 +268,26 @@ public interface ITeamsClient /// Options to change API behaviour. /// Task> GetAllPendingInvitations(int id, ApiOptions options); + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// privides repository as a media typ in accepts header + /// + /// + /// 200 Alternative response with repository permissions + /// This is the response when the repository media type has been provded in the Accept header. + /// 204 Response if team has permission for the repository. + /// This is the response when the repository media type hasn't been provded in the Accept header. + /// 404 Not Found if team does not have permission for the repository + /// + /// + Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, + bool provideRepositoryMediaTypeInAcceptHeader = false); } } diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 5dfbcd7b13..dd05a8a3da 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -543,5 +543,38 @@ public Task> GetAllPendingInvita { return ApiConnection.GetAll(ApiUrls.TeamPendingInvitations(id), null, options); } + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// privides repository as a media typ in accepts header + /// + /// + /// 200 Alternative response with repository permissions + /// 204 Response if team has permission for the repository. + /// This is the response when the repository media type hasn't been provded in the Accept header. + /// 404 Not Found if team does not have permission for the repository + /// + /// + [ManualRoute("GET", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] + public Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, + bool provideRepositoryMediaTypeInAcceptHeader = false) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(teamSlug, nameof(teamSlug)); + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); + + var endpoint = ApiUrls.CheckTeamPermissionsForARepository(org, teamSlug, owner, repo); + + return provideRepositoryMediaTypeInAcceptHeader + ? ApiConnection.Get(endpoint, null, "application/vnd.github.v3.repository+json") + : ApiConnection.Get(endpoint); + } } } diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index c0612bb599..1b8d1ee395 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1973,6 +1973,18 @@ public static Uri TeamRepository(int id, string organization, string repoName) return "teams/{0}/repos/{1}/{2}".FormatUri(id, organization, repoName); } + /// + /// returns the for a team repository + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + public static Uri CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo) + { + return "/orgs/{0}/teams/{1}/repos/{2}/{3}".FormatUri(org, teamSlug, owner, repo); + } + /// /// returns the for the teams pending invitations /// From 1c6313d252dd6ba3424d5878f89bcc82a32d037e Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 09:39:47 +0600 Subject: [PATCH 16/39] fix convention tests --- Octokit/Models/Response/TeamRepository.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Octokit/Models/Response/TeamRepository.cs b/Octokit/Models/Response/TeamRepository.cs index dc3b5c12cc..d1ca5f2141 100644 --- a/Octokit/Models/Response/TeamRepository.cs +++ b/Octokit/Models/Response/TeamRepository.cs @@ -76,7 +76,7 @@ public TeamRepository(int id, string defaultBranch, int openIssuesCount, bool isTemplate, - ICollection topics, + IReadOnlyList topics, bool hasIssues, bool hasProjects, bool hasWiki, @@ -213,7 +213,7 @@ public TeamRepository(int id, /// /// example: octocat/Hello-World /// - public string FullName { get; set; } + public string FullName { get; private set; } public LicenseMetadata License { get; private set; } @@ -247,7 +247,7 @@ public TeamRepository(int id, /// format: uri /// example: https://api.github.com/repos/octocat/Hello-World /// - public string Url { get; set; } + public string Url { get; private set; } /// /// example: http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref} @@ -492,7 +492,7 @@ public TeamRepository(int id, /// public string DefaultBranch { get; private set; } - public int OpenIssuesCount { get; set; } + public int OpenIssuesCount { get; private set; } /// /// Whether this repository acts as a template that can be used to generate new repositories @@ -500,7 +500,7 @@ public TeamRepository(int id, /// public bool IsTemplate { get; private set; } - public ICollection Topics { get; private set; } + public IReadOnlyList Topics { get; private set; } /// /// Whether issues are enabled. From a6be98d5e55fe8e9bec262277d0d291c4a779a59 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 10:27:17 +0600 Subject: [PATCH 17/39] update comments on TeamRepository props --- Octokit/Models/Response/TeamRepository.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Octokit/Models/Response/TeamRepository.cs b/Octokit/Models/Response/TeamRepository.cs index d1ca5f2141..bab62979c9 100644 --- a/Octokit/Models/Response/TeamRepository.cs +++ b/Octokit/Models/Response/TeamRepository.cs @@ -546,8 +546,16 @@ public TeamRepository(int id, /// public DateTimeOffset? PushedAt { get; private set; } + /// + /// format: date-time + /// example: '2011-01-26T19:01:12Z' + /// public DateTimeOffset CreatedAt { get; private set; } + /// + /// format: date-time + /// example: '2011-01-26T19:14:43Z' + /// public DateTimeOffset UpdatedAt { get; private set; } /// @@ -555,7 +563,9 @@ public TeamRepository(int id, /// public bool? AllowRebaseMerge { get; private set; } - // TODO :: is Repository nullable-repository? + /// + /// Template repository (nullable) + /// public Repository TemplateRepository { get; private set; } public string TempCloneToken { get; private set; } From d6f345bf2058d40aad80506a3692330cf2aab661 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 11:12:48 +0600 Subject: [PATCH 18/39] add two new endpoints in TeamsClient --- .../Clients/IObservableTeamsClient.cs | 34 +++++++++++++++ .../Clients/ObservableTeamsClient.cs | 42 +++++++++++++++++++ Octokit/Clients/ITeamsClient.cs | 34 +++++++++++++++ Octokit/Clients/TeamsClient.cs | 42 +++++++++++++++++++ 4 files changed, 152 insertions(+) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 8e8b005517..debef06ebd 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -297,5 +297,39 @@ public interface IObservableTeamsClient /// IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, bool provideRepositoryMediaTypeInAcceptHeader = false); + + /// + /// Add or update team repository permissions + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository + /// + /// + IObservable AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission); + + /// + /// Remove a repository from a team + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + IObservable RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo); } } diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 481d25911e..09120ed1ce 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -447,5 +447,47 @@ public IObservable CheckTeamPermissionsForARepository(string org { return _client.CheckTeamPermissionsForARepository(org, teamSlug, owner, repo, provideRepositoryMediaTypeInAcceptHeader).ToObservable(); } + + /// + /// Add or update team repository permissions + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository + /// + /// + [ManualRoute("PUT", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] + public IObservable AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission) + { + return _client.AddOrUpdateTeamRepositoryPermissions(org, teamSlug, owner, repo, permission).ToObservable(); + } + + /// + /// Remove a repository from a team + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] + public IObservable RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo) + { + return _client.RemoveRepositoryFromTeam(org, teamSlug, owner, repo).ToObservable(); + } } } diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 20e23e6feb..ab56a73076 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -289,5 +289,39 @@ public interface ITeamsClient /// Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, bool provideRepositoryMediaTypeInAcceptHeader = false); + + /// + /// Add or update team repository permissions + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository + /// + /// + Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission); + + /// + /// Remove a repository from a team + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + Task RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo); } } diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index dd05a8a3da..6018d0e9b0 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -576,5 +576,47 @@ public Task CheckTeamPermissionsForARepository(string org, strin ? ApiConnection.Get(endpoint, null, "application/vnd.github.v3.repository+json") : ApiConnection.Get(endpoint); } + + /// + /// Add or update team repository permissions + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository + /// + /// + [ManualRoute("PUT", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] + public Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission) + { + throw new NotImplementedException(); + } + + /// + /// Remove a repository from a team + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. + /// + [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] + public Task RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo) + { + throw new NotImplementedException(); + } } } From c01bb60459cb6f93999a1f2c23824ec522c072bf Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 11:15:47 +0600 Subject: [PATCH 19/39] refactor: rename ApiUrl for TeamPermission --- Octokit/Clients/TeamsClient.cs | 2 +- Octokit/Helpers/ApiUrls.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 6018d0e9b0..f1bdfc08bf 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -570,7 +570,7 @@ public Task CheckTeamPermissionsForARepository(string org, strin Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); - var endpoint = ApiUrls.CheckTeamPermissionsForARepository(org, teamSlug, owner, repo); + var endpoint = ApiUrls.TeamPermissionsForARepository(org, teamSlug, owner, repo); return provideRepositoryMediaTypeInAcceptHeader ? ApiConnection.Get(endpoint, null, "application/vnd.github.v3.repository+json") diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 1b8d1ee395..631ceb42b7 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1980,7 +1980,7 @@ public static Uri TeamRepository(int id, string organization, string repoName) /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. - public static Uri CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo) + public static Uri TeamPermissionsForARepository(string org, string teamSlug, string owner, string repo) { return "/orgs/{0}/teams/{1}/repos/{2}/{3}".FormatUri(org, teamSlug, owner, repo); } From d0f4f0c55f6d44dbe07a31b59ed6f22ff1407a21 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 11:53:12 +0600 Subject: [PATCH 20/39] fix test --- Octokit.Tests.Integration/Clients/TeamsClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index 0910634c00..aaf7fb5d31 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -520,7 +520,7 @@ public async Task ChecksTeamPermissions() team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName, - true); + false); Assert.Null(teamPermission); } From cba914197c5702f8a71c011a875894ee1ae018c9 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 13:41:58 +0600 Subject: [PATCH 21/39] implement methods for new endpoints --- .../Clients/TeamsClientTests.cs | 63 ++++++++++++++++++- Octokit/Clients/TeamsClient.cs | 39 +++++++++--- Octokit/Http/ApiConnection.cs | 15 +++++ Octokit/Http/Connection.cs | 7 ++- Octokit/Http/IApiConnection.cs | 9 +++ Octokit/Http/IConnection.cs | 3 +- 6 files changed, 123 insertions(+), 13 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index aaf7fb5d31..7ac775c434 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -503,7 +503,7 @@ public async Task UpdatesTeamLegacy() } } - public class CheckTeamPermissionsForARepositoryMethod + public class TheCheckTeamPermissionsForARepositoryMethod { [OrganizationTest] public async Task ChecksTeamPermissions() @@ -567,4 +567,65 @@ await github.Organization.Team.CheckTeamPermissionsForARepository( } } } + + public class TheAddOrUpdateTeamRepositoryPermissionsMethod + { + [OrganizationTest] + public async Task AddsTeamRepositoryPermissions() + { + var github = Helper.GetAuthenticatedClient(); + + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) + { + var team = teamContext.Team; + var repo = repoContext.Repository; + + var addRepo = await github.Organization.Team.AddRepository(team.Id, team.Organization.Login, repo.Name, new RepositoryPermissionRequest(Permission.Maintain)); + + Assert.True(addRepo); + + await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "admin"); + + var addedRepo = await github.Organization.Team.GetAllRepositories(team.Id); + + Assert.True(addedRepo.First(x => x.Id == repo.Id).Permissions.Admin); + } + } + } + + public class TheRemoveRepositoryFromTeamMethod + { + [OrganizationTest] + public async Task RemovesRepositoryFromTeam() + { + var github = Helper.GetAuthenticatedClient(); + + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) + { + var team = teamContext.Team; + var repo = repoContext.Repository; + + var addRepo = await github.Organization.Team.AddRepository(team.Id, team.Organization.Login, repo.Name, new RepositoryPermissionRequest(Permission.Admin)); + + Assert.True(addRepo); + + await github.Organization.Team.RemoveRepositoryFromTeam( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName); + + var addedRepo = await github.Organization.Team.GetAllRepositories(team.Id); + + Assert.Equal(0, addedRepo.Count); + } + } + } } diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index f1bdfc08bf..379d814015 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -370,11 +370,14 @@ public Task> GetAllRepositories(int id, ApiOptions opt } /// - /// Add a repository to the team + /// Add or update team repository permissions (Legacy) + /// Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new "Add or update team repository permissions" endpoint. /// /// Thrown when a general API error occurs. /// - [ManualRoute("PUT", "/orgs/{org}/team/{team_slug}/repos/{owner}/{repo}")] + [ManualRoute("PUT", "/teams/{team_id}/repos/{owner}/{repo}")] + // TODO :: rename method to AddOrUpdateTeamRepositoryPermissions public async Task AddRepository(int id, string organization, string repoName) { Ensure.ArgumentNotNullOrEmptyString(organization, nameof(organization)); @@ -406,7 +409,9 @@ public async Task AddRepository(int id, string organization, string repoNa } /// - /// Add a repository to the team + /// Add or update team repository permissions (Legacy) + /// Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new "Add or update team repository permissions" endpoint. /// /// The team identifier. /// Org to associate the repo with. @@ -414,7 +419,8 @@ public async Task AddRepository(int id, string organization, string repoNa /// The permission to grant the team on this repository. /// Thrown when a general API error occurs. /// - [ManualRoute("PUT", "/orgs/{org}/team/{team_slug}/repos/{owner}/{repo}")] + [ManualRoute("PUT", "/teams/{team_id}/repos/{owner}/{repo}")] + // TODO :: rename method to AddOrUpdateTeamRepositoryPermissions public async Task AddRepository(int id, string organization, string repoName, RepositoryPermissionRequest permission) { Ensure.ArgumentNotNullOrEmptyString(organization, nameof(organization)); @@ -446,11 +452,14 @@ public async Task AddRepository(int id, string organization, string repoNa } /// - /// Remove a repository from the team + /// Remove a repository from a team (Legacy) + /// Deprecation Notice: This endpoint route is deprecated and will be removed from the Teams API. + /// We recommend migrating your existing code to use the new Remove a repository from a team endpoint. /// /// Thrown when a general API error occurs. /// - [ManualRoute("DELETE", "/orgs/:org/teams/:team_slug/repos/:owner/:repo")] + [ManualRoute("DELETE", "/teams/{team_id}/repos/{owner}/{repo}")] + // TODO :: rename to RemoveRepositoryFromTeam public async Task RemoveRepository(int id, string organization, string repoName) { Ensure.ArgumentNotNullOrEmptyString(organization, nameof(organization)); @@ -598,7 +607,14 @@ public Task CheckTeamPermissionsForARepository(string org, strin [ManualRoute("PUT", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] public Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission) { - throw new NotImplementedException(); + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(teamSlug, nameof(teamSlug)); + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); + + var endpoint = ApiUrls.TeamPermissionsForARepository(org, teamSlug, owner, repo); + + return ApiConnection.Put(endpoint, new { permission }, null); } /// @@ -616,7 +632,14 @@ public Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, st [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] public Task RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo) { - throw new NotImplementedException(); + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(teamSlug, nameof(teamSlug)); + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); + + var endpoint = ApiUrls.TeamPermissionsForARepository(org, teamSlug, owner, repo); + + return ApiConnection.Delete(endpoint); } } } diff --git a/Octokit/Http/ApiConnection.cs b/Octokit/Http/ApiConnection.cs index 1a5694271c..0873e71195 100644 --- a/Octokit/Http/ApiConnection.cs +++ b/Octokit/Http/ApiConnection.cs @@ -338,6 +338,21 @@ public Task Put(Uri uri) return Connection.Put(uri); } + /// + /// Creates or replaces the API resource at the specified URI + /// + /// URI of the API resource to put + /// Object that describes the API resource; this will be serialized and used as the request's body + /// Accept header to use for the API request + /// A for the request's execution. + public Task Put(Uri uri, object data, string accepts) + { + Ensure.ArgumentNotNull(uri, nameof(uri)); + Ensure.ArgumentNotNull(data, nameof(data)); + + return Connection.Put(uri, data, null); + } + /// /// Creates or replaces the API resource at the specified URI. /// diff --git a/Octokit/Http/Connection.cs b/Octokit/Http/Connection.cs index bcace9f7ee..ba8402f024 100644 --- a/Octokit/Http/Connection.cs +++ b/Octokit/Http/Connection.cs @@ -498,14 +498,15 @@ public async Task Put(Uri uri) /// Performs an asynchronous HTTP PUT request that expects an empty response. /// /// URI endpoint to send request to + /// The object to serialize as the body of the request /// Specifies accepted response media types. /// The returned - public async Task Put(Uri uri, string accepts) + public async Task Put(Uri uri, object body, string accepts) { Ensure.ArgumentNotNull(uri, nameof(uri)); - Ensure.ArgumentNotNull(accepts, nameof(accepts)); + Ensure.ArgumentNotNull(body, nameof(body)); - var response = await SendData(uri, HttpMethod.Put, null, accepts, null, CancellationToken.None).ConfigureAwait(false); + var response = await SendData(uri, HttpMethod.Put, body, accepts, null, CancellationToken.None).ConfigureAwait(false); return response.HttpResponse.StatusCode; } diff --git a/Octokit/Http/IApiConnection.cs b/Octokit/Http/IApiConnection.cs index 730cd2f5d8..44d2c87fed 100644 --- a/Octokit/Http/IApiConnection.cs +++ b/Octokit/Http/IApiConnection.cs @@ -234,6 +234,15 @@ public interface IApiConnection /// A for the request's execution. Task Put(Uri uri); + /// + /// Creates or replaces the API resource at the specified URI + /// + /// URI of the API resource to put + /// Object that describes the API resource; this will be serialized and used as the request's body + /// Accept header to use for the API request + /// A for the request's execution. + Task Put(Uri uri, object data, string accepts); + /// /// Creates or replaces the API resource at the specified URI. /// diff --git a/Octokit/Http/IConnection.cs b/Octokit/Http/IConnection.cs index ff4b6359f1..1e38d4be9b 100644 --- a/Octokit/Http/IConnection.cs +++ b/Octokit/Http/IConnection.cs @@ -251,9 +251,10 @@ Task> Post( /// Performs an asynchronous HTTP PUT request that expects an empty response. /// /// URI endpoint to send request to + /// The object to serialize as the body of the request /// Specifies accepted response media types. /// The returned - Task Put(Uri uri, string accepts); + Task Put(Uri uri, object body, string accepts); /// /// Performs an asynchronous HTTP DELETE request that expects an empty response. From 426abdf59b6d4e3f9174c4699d13636eefc20c40 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 19:15:38 +0600 Subject: [PATCH 22/39] add the integration tests --- .../Clients/TeamsClientTests.cs | 85 +++++++---- .../Reactive/ObservableTeamsClientTests.cs | 144 +++++++++++++++--- 2 files changed, 181 insertions(+), 48 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index 7ac775c434..422c8b4ee2 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -505,19 +505,24 @@ public async Task UpdatesTeamLegacy() public class TheCheckTeamPermissionsForARepositoryMethod { + private readonly IGitHubClient github; + + public TheCheckTeamPermissionsForARepositoryMethod() + { + github = Helper.GetAuthenticatedClient(); + } + [OrganizationTest] public async Task ChecksTeamPermissions() { - var github = Helper.GetAuthenticatedClient(); - var team = github.Organization.Team.GetAll(Helper.Organization).Result.First(); - + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { - github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, - team.Slug, + teamContext.Team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName, false); @@ -529,16 +534,14 @@ public async Task ChecksTeamPermissions() [OrganizationTest] public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() { - var github = Helper.GetAuthenticatedClient(); - var team = github.Organization.Team.GetAll(Helper.Organization).Result.First(); - + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { - github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, - team.Slug, + teamContext.Team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName, true); @@ -552,15 +555,13 @@ public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() [OrganizationTest] public async Task ChecksTeamPermissionsThrowNotFoundException() { - var github = Helper.GetAuthenticatedClient(); - var team = github.Organization.Team.GetAll(Helper.Organization).Result.First(); - + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { await Assert.ThrowsAsync(async () => await github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, - team.Slug, + teamContext.Team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName, false)); @@ -578,13 +579,31 @@ public async Task AddsTeamRepositoryPermissions() using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) { - var team = teamContext.Team; - var repo = repoContext.Repository; + var teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId); + + Assert.Equal(0, teamRepositories.Count); - var addRepo = await github.Organization.Team.AddRepository(team.Id, team.Organization.Login, repo.Name, new RepositoryPermissionRequest(Permission.Maintain)); + await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "admin"); - Assert.True(addRepo); + teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId); + + Assert.True(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Admin); + } + } + [OrganizationTest] + public async Task UpdatesTeamRepositoryPermissions() + { + var github = Helper.GetAuthenticatedClient(); + + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) + { await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( Helper.Organization, teamContext.Team.Slug, @@ -592,9 +611,21 @@ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( repoContext.RepositoryName, "admin"); - var addedRepo = await github.Organization.Team.GetAllRepositories(team.Id); + var teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId); + + Assert.True(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Admin); + + await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "maintain"); + + teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId); - Assert.True(addedRepo.First(x => x.Id == repo.Id).Permissions.Admin); + Assert.False(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Admin); + Assert.True(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Maintain); } } } @@ -609,12 +640,12 @@ public async Task RemovesRepositoryFromTeam() using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) { - var team = teamContext.Team; - var repo = repoContext.Repository; - - var addRepo = await github.Organization.Team.AddRepository(team.Id, team.Organization.Login, repo.Name, new RepositoryPermissionRequest(Permission.Admin)); - - Assert.True(addRepo); + await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "admin"); await github.Organization.Team.RemoveRepositoryFromTeam( Helper.Organization, @@ -622,7 +653,7 @@ await github.Organization.Team.RemoveRepositoryFromTeam( repoContext.RepositoryOwner, repoContext.RepositoryName); - var addedRepo = await github.Organization.Team.GetAllRepositories(team.Id); + var addedRepo = await github.Organization.Team.GetAllRepositories(teamContext.TeamId); Assert.Equal(0, addedRepo.Count); } diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index 8f1649382b..6ddc25bddb 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -434,21 +434,25 @@ public async Task UpdatesTeamLegacy() } } - public class CheckTeamPermissionsForARepositoryMethod + public class TheCheckTeamPermissionsForARepositoryMethod { + private readonly IObservableGitHubClient _github; + public TheCheckTeamPermissionsForARepositoryMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + } [OrganizationTest] public async Task ChecksTeamPermissions() { - var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); - var team = await github.Organization.Team.GetAll(Helper.Organization).FirstAsync(); - - using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { - github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + _github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); - var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + var teamPermission = await _github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, - team.Slug, + teamContext.Team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName); @@ -459,16 +463,14 @@ public async Task ChecksTeamPermissions() [OrganizationTest] public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() { - var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); - var team = await github.Organization.Team.GetAll(Helper.Organization).FirstAsync(); - - using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { - github.Organization.Team.AddRepository(team.Id, Helper.Organization, repositoryContext.RepositoryName); + _github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); - var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + var teamPermission = await _github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, - team.Slug, + teamContext.Team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName, true); @@ -482,19 +484,119 @@ public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() [OrganizationTest] public async Task ChecksTeamPermissionsThrowNotFoundException() { - var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); - var team = await github.Organization.Team.GetAll(Helper.Organization).FirstAsync(); - - using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { await Assert.ThrowsAsync(async () => - await github.Organization.Team.CheckTeamPermissionsForARepository( + await _github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, - team.Slug, + teamContext.Team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName, false)); } } } + + public class TheAddOrUpdateTeamRepositoryPermissionsMethod + { + private readonly IObservableGitHubClient _github; + + public TheAddOrUpdateTeamRepositoryPermissionsMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + } + + [OrganizationTest] + public async Task AddsTeamRepositoryPermissions() + { + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repoContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) + { + var teamRepository = await _github.Organization.Team + .GetAllRepositories(teamContext.TeamId) + .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId); + + Assert.Null(teamRepository); + + await _github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "admin"); + + teamRepository = await _github.Organization.Team + .GetAllRepositories(teamContext.TeamId) + .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId); + + Assert.NotNull(teamRepository); + } + } + + [OrganizationTest] + public async Task UpdatesTeamRepositoryPermissions() + { + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repoContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) + { + await _github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "admin"); + + var teamRepository = await _github.Organization.Team + .GetAllRepositories(teamContext.TeamId) + .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId); + + Assert.True(teamRepository.Permissions.Admin); + + await _github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "maintain"); + + teamRepository = await _github.Organization.Team + .GetAllRepositories(teamContext.TeamId) + .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId); + + Assert.True(teamRepository.Permissions.Maintain); + Assert.False(teamRepository.Permissions.Admin); + } + } + } + + public class TheRemoveRepositoryFromTeamMethod + { + [OrganizationTest] + public async Task RemovesRepositoryFromTeam() + { + var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository")))) + { + await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName, + "admin"); + + await github.Organization.Team.RemoveRepositoryFromTeam( + Helper.Organization, + teamContext.Team.Slug, + repoContext.RepositoryOwner, + repoContext.RepositoryName); + + var addedRepo = await github.Organization.Team.GetAllRepositories(teamContext.TeamId).ToList(); + + Assert.Equal(0, addedRepo.Count); + } + } + } } From 19dd1497e36b13288e0668d5e2385dd0f14d8f84 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 20:49:59 +0600 Subject: [PATCH 23/39] fix spelling --- Octokit.Tests.Integration/Clients/TeamsClientTests.cs | 4 ++-- .../Reactive/ObservableTeamsClientTests.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index 422c8b4ee2..cc88c7ccd7 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -532,7 +532,7 @@ public async Task ChecksTeamPermissions() } [OrganizationTest] - public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() + public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAccepts() { using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) @@ -553,7 +553,7 @@ public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() } [OrganizationTest] - public async Task ChecksTeamPermissionsThrowNotFoundException() + public async Task ChecksTeamPermissionsThrowsNotFoundException() { using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index 6ddc25bddb..c6096b181d 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -442,6 +442,7 @@ public TheCheckTeamPermissionsForARepositoryMethod() _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); } + [OrganizationTest] public async Task ChecksTeamPermissions() { @@ -482,7 +483,7 @@ public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() } [OrganizationTest] - public async Task ChecksTeamPermissionsThrowNotFoundException() + public async Task ChecksTeamPermissionsThrowsNotFoundException() { using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) From 38b0881001f1ca502e27e6e4455d0e1fd3c01ebf Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 21:08:15 +0600 Subject: [PATCH 24/39] update comments --- .../Clients/IObservableTeamsClient.cs | 43 +++++++++++++------ .../Clients/ObservableTeamsClient.cs | 41 ++++++++++++------ Octokit/Clients/ITeamsClient.cs | 41 ++++++++++++------ Octokit/Clients/TeamsClient.cs | 40 +++++++++++------ 4 files changed, 113 insertions(+), 52 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index debef06ebd..779fa2c314 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -128,6 +128,10 @@ public interface IObservableTeamsClient /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// + /// /// + /// See the API documentation + /// for more information. + /// /// updated for the current org IObservable Update(string org, string teamSlug, UpdateTeam team); @@ -136,6 +140,10 @@ public interface IObservableTeamsClient /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Update a team endpoint /// + /// + /// See the API documentation + /// for more information. + /// /// Thrown when a general API error occurs. /// Updated IObservable Update(int id, UpdateTeam team); @@ -144,15 +152,24 @@ public interface IObservableTeamsClient /// To delete a team, the authenticated user must be an organization owner or team maintainer. /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. /// + /// + /// See the API documentation + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. /// Thrown when a general API error occurs. /// IObservable Delete(string org, string teamSlug); /// - /// Delete a team - must have owner permissions to this + /// Delete a team - must have owner permissions to do this /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. /// + /// + /// See the API documentation + /// + /// The unique identifier of the team. /// Thrown when a general API error occurs. /// IObservable Delete(int id); @@ -281,20 +298,16 @@ public interface IObservableTeamsClient /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. /// Repositories inherited through a parent team will also be checked. /// + /// + /// See the API Documentation + /// for more information. /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// privides repository as a media typ in accepts header - /// - /// - /// 200 Alternative response with repository permissions - /// This is the response when the repository media type has been provded in the Accept header. - /// 204 Response if team has permission for the repository. - /// This is the response when the repository media type hasn't been provded in the Accept header. - /// 404 Not Found if team does not have permission for the repository - /// - /// + /// Thrown when a general API error occurs. + /// IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, bool provideRepositoryMediaTypeInAcceptHeader = false); @@ -310,11 +323,12 @@ IObservable CheckTeamPermissionsForARepository(string org, strin /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// - /// The permission to grant the team on this repository. We accept the following permissions to be set: - /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the - /// owning organization has defined any. If no permission is specified, the team's permission attribute - /// will be used to determine what permission to grant the team on this repository + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository /// + /// Thrown when a general API error occurs. /// IObservable AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission); @@ -329,6 +343,7 @@ IObservable CheckTeamPermissionsForARepository(string org, strin /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. + /// Thrown when a general API error occurs. /// IObservable RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo); } diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 09120ed1ce..6d2c3885f9 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -197,6 +197,10 @@ public IObservable Create(string org, NewTeam team) /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// + /// /// + /// See the API documentation + /// for more information. + /// /// updated for the current org public IObservable Update(string org, string teamSlug, UpdateTeam team) { @@ -212,6 +216,10 @@ public IObservable Update(string org, string teamSlug, UpdateTeam team) /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Update a team endpoint /// + /// + /// See the API documentation + /// for more information. + /// /// Thrown when a general API error occurs. /// Updated public IObservable Update(int id, UpdateTeam team) @@ -225,6 +233,11 @@ public IObservable Update(int id, UpdateTeam team) /// To delete a team, the authenticated user must be an organization owner or team maintainer. /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. /// + /// + /// See the API documentation + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. /// Thrown when a general API error occurs. /// public IObservable Delete(string org, string teamSlug) @@ -240,6 +253,10 @@ public IObservable Delete(string org, string teamSlug) /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. /// + /// + /// See the API documentation + /// + /// The unique identifier of the team. /// Thrown when a general API error occurs. /// public IObservable Delete(int id) @@ -428,20 +445,16 @@ public IObservable GetAllPendingInvitations(in /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. /// Repositories inherited through a parent team will also be checked. /// + /// + /// See the API Documentation + /// for more information. /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// privides repository as a media typ in accepts header - /// - /// - /// 200 Alternative response with repository permissions - /// This is the response when the repository media type has been provded in the Accept header. - /// 204 Response if team has permission for the repository. - /// This is the response when the repository media type hasn't been provded in the Accept header. - /// 404 Not Found if team does not have permission for the repository - /// - /// + /// Thrown when a general API error occurs. + /// public IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, bool provideRepositoryMediaTypeInAcceptHeader = false) { @@ -460,11 +473,12 @@ public IObservable CheckTeamPermissionsForARepository(string org /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// - /// The permission to grant the team on this repository. We accept the following permissions to be set: - /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the - /// owning organization has defined any. If no permission is specified, the team's permission attribute - /// will be used to determine what permission to grant the team on this repository + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository /// + /// Thrown when a general API error occurs. /// [ManualRoute("PUT", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] public IObservable AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission) @@ -483,6 +497,7 @@ public IObservable AddOrUpdateTeamRepositoryPermissions(string org, string /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. + /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] public IObservable RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo) diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index ab56a73076..10ad23b6f9 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -129,6 +129,10 @@ public interface ITeamsClient /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// + /// /// + /// See the API documentation + /// for more information. + /// /// updated for the current org Task Update(string org, string teamSlug, UpdateTeam team); @@ -137,6 +141,10 @@ public interface ITeamsClient /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Update a team endpoint /// + /// + /// See the API documentation + /// for more information. + /// /// Thrown when a general API error occurs. /// Updated Task Update(int id, UpdateTeam team); @@ -145,6 +153,11 @@ public interface ITeamsClient /// To delete a team, the authenticated user must be an organization owner or team maintainer. /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. /// + /// + /// See the API documentation + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. /// Thrown when a general API error occurs. /// Task Delete(string org, string teamSlug); @@ -154,6 +167,10 @@ public interface ITeamsClient /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. /// + /// + /// See the API documentation + /// + /// The unique identifier of the team. /// Thrown when a general API error occurs. /// Task Delete(int id); @@ -273,20 +290,16 @@ public interface ITeamsClient /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. /// Repositories inherited through a parent team will also be checked. /// + /// + /// See the API Documentation + /// for more information. /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// privides repository as a media typ in accepts header - /// - /// - /// 200 Alternative response with repository permissions - /// This is the response when the repository media type has been provded in the Accept header. - /// 204 Response if team has permission for the repository. - /// This is the response when the repository media type hasn't been provded in the Accept header. - /// 404 Not Found if team does not have permission for the repository - /// - /// + /// Thrown when a general API error occurs. + /// Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, bool provideRepositoryMediaTypeInAcceptHeader = false); @@ -302,11 +315,12 @@ Task CheckTeamPermissionsForARepository(string org, string teamS /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// - /// The permission to grant the team on this repository. We accept the following permissions to be set: - /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the - /// owning organization has defined any. If no permission is specified, the team's permission attribute - /// will be used to determine what permission to grant the team on this repository + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository /// + /// Thrown when a general API error occurs. /// Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission); @@ -321,6 +335,7 @@ Task CheckTeamPermissionsForARepository(string org, string teamS /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. + /// Thrown when a general API error occurs. /// Task RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo); } diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 379d814015..c8b07f99b8 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -231,6 +231,10 @@ public Task Create(string org, NewTeam team) /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// + /// /// + /// See the API documentation + /// for more information. + /// /// updated for the current org [ManualRoute("PATCH", "/orgs/{org}/teams/{team_slug}")] public Task Update(string org, string teamSlug, UpdateTeam team) @@ -249,6 +253,10 @@ public Task Update(string org, string teamSlug, UpdateTeam team) /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Update a team endpoint /// + /// + /// See the API documentation + /// for more information. + /// /// Thrown when a general API error occurs. /// Updated [ManualRoute("PATCH", "/teams/{team_id}")] @@ -264,6 +272,11 @@ public Task Update(int id, UpdateTeam team) /// To delete a team, the authenticated user must be an organization owner or team maintainer. /// If you are an organization owner, deleting a parent team will delete all of its child teams as well. /// + /// + /// See the API documentation + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}")] @@ -282,6 +295,10 @@ public Task Delete(string org, string teamSlug) /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. /// + /// + /// See the API documentation + /// + /// The unique identifier of the team. /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/teams/{team_id}")] @@ -557,19 +574,16 @@ public Task> GetAllPendingInvita /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. /// Repositories inherited through a parent team will also be checked. /// + /// + /// See the API Documentation + /// for more information. /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// privides repository as a media typ in accepts header - /// - /// - /// 200 Alternative response with repository permissions - /// 204 Response if team has permission for the repository. - /// This is the response when the repository media type hasn't been provded in the Accept header. - /// 404 Not Found if team does not have permission for the repository - /// - /// + /// Thrown when a general API error occurs. + /// [ManualRoute("GET", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] public Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, bool provideRepositoryMediaTypeInAcceptHeader = false) @@ -598,11 +612,12 @@ public Task CheckTeamPermissionsForARepository(string org, strin /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. /// - /// The permission to grant the team on this repository. We accept the following permissions to be set: - /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the - /// owning organization has defined any. If no permission is specified, the team's permission attribute - /// will be used to determine what permission to grant the team on this repository + /// The permission to grant the team on this repository. We accept the following permissions to be set: + /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the + /// owning organization has defined any. If no permission is specified, the team's permission attribute + /// will be used to determine what permission to grant the team on this repository /// + /// Thrown when a general API error occurs. /// [ManualRoute("PUT", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] public Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission) @@ -628,6 +643,7 @@ public Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, st /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. + /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] public Task RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo) From de786e062e132e46ae2303ab604c04085ea25790 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 21:23:11 +0600 Subject: [PATCH 25/39] refactor: rename method name --- Octokit.Reactive/Clients/IObservableTeamsClient.cs | 2 +- Octokit.Reactive/Clients/ObservableTeamsClient.cs | 4 ++-- Octokit.Tests.Integration/Clients/TeamsClientTests.cs | 6 +++--- .../Reactive/ObservableTeamsClientTests.cs | 6 +++--- Octokit/Clients/ITeamsClient.cs | 2 +- Octokit/Clients/TeamsClient.cs | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 779fa2c314..810997a4e3 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -345,6 +345,6 @@ IObservable CheckTeamPermissionsForARepository(string org, strin /// The name of the repository. The name is not case sensitive. /// Thrown when a general API error occurs. /// - IObservable RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo); + IObservable RemoveRepositoryFromATeam(string org, string teamSlug, string owner, string repo); } } diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 6d2c3885f9..35f5d01ff8 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -500,9 +500,9 @@ public IObservable AddOrUpdateTeamRepositoryPermissions(string org, string /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] - public IObservable RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo) + public IObservable RemoveRepositoryFromATeam(string org, string teamSlug, string owner, string repo) { - return _client.RemoveRepositoryFromTeam(org, teamSlug, owner, repo).ToObservable(); + return _client.RemoveRepositoryFromATeam(org, teamSlug, owner, repo).ToObservable(); } } } diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index cc88c7ccd7..f49ffe82a5 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -630,10 +630,10 @@ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( } } - public class TheRemoveRepositoryFromTeamMethod + public class TheRemoveRepositoryFromATeamMethod { [OrganizationTest] - public async Task RemovesRepositoryFromTeam() + public async Task RemovesRepositoryFromATeam() { var github = Helper.GetAuthenticatedClient(); @@ -647,7 +647,7 @@ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( repoContext.RepositoryName, "admin"); - await github.Organization.Team.RemoveRepositoryFromTeam( + await github.Organization.Team.RemoveRepositoryFromATeam( Helper.Organization, teamContext.Team.Slug, repoContext.RepositoryOwner, diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index c6096b181d..05ca151375 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -571,10 +571,10 @@ await _github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( } } - public class TheRemoveRepositoryFromTeamMethod + public class TheRemoveRepositoryFromATeamMethod { [OrganizationTest] - public async Task RemovesRepositoryFromTeam() + public async Task RemovesRepositoryFromATeam() { var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); @@ -588,7 +588,7 @@ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( repoContext.RepositoryName, "admin"); - await github.Organization.Team.RemoveRepositoryFromTeam( + await github.Organization.Team.RemoveRepositoryFromATeam( Helper.Organization, teamContext.Team.Slug, repoContext.RepositoryOwner, diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 10ad23b6f9..bd8c6b4b6f 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -337,6 +337,6 @@ Task CheckTeamPermissionsForARepository(string org, string teamS /// The name of the repository. The name is not case sensitive. /// Thrown when a general API error occurs. /// - Task RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo); + Task RemoveRepositoryFromATeam(string org, string teamSlug, string owner, string repo); } } diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index c8b07f99b8..f52b87f998 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -646,7 +646,7 @@ public Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, st /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] - public Task RemoveRepositoryFromTeam(string org, string teamSlug, string owner, string repo) + public Task RemoveRepositoryFromATeam(string org, string teamSlug, string owner, string repo) { Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); Ensure.ArgumentNotNullOrEmptyString(teamSlug, nameof(teamSlug)); From d194b6883725f366dcb4c81d575d9e24859392c1 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 21:49:29 +0600 Subject: [PATCH 26/39] fix: add end tag for remarks --- Octokit.Reactive/Clients/IObservableTeamsClient.cs | 1 + Octokit.Reactive/Clients/ObservableTeamsClient.cs | 1 + Octokit/Clients/ITeamsClient.cs | 1 + Octokit/Clients/TeamsClient.cs | 1 + 4 files changed, 4 insertions(+) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 810997a4e3..622c350ea7 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -301,6 +301,7 @@ public interface IObservableTeamsClient /// /// See the API Documentation /// for more information. + /// /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 35f5d01ff8..3c814bcca0 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -448,6 +448,7 @@ public IObservable GetAllPendingInvitations(in /// /// See the API Documentation /// for more information. + /// /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index bd8c6b4b6f..9c542f898f 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -293,6 +293,7 @@ public interface ITeamsClient /// /// See the API Documentation /// for more information. + /// /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index f52b87f998..5183b260a6 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -577,6 +577,7 @@ public Task> GetAllPendingInvita /// /// See the API Documentation /// for more information. + /// /// The organization name. The name is not case sensitive. /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. From 28a36d646ab83c79a39aa7a6e80d1855bcc5e386 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 9 Dec 2022 21:58:36 +0600 Subject: [PATCH 27/39] refactor: remove unused method param --- Octokit/Clients/TeamsClient.cs | 5 +---- Octokit/Http/ApiConnection.cs | 5 ++--- Octokit/Http/Connection.cs | 5 ++--- Octokit/Http/IApiConnection.cs | 3 +-- Octokit/Http/IConnection.cs | 3 +-- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 5183b260a6..8ef5900be0 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -394,7 +394,6 @@ public Task> GetAllRepositories(int id, ApiOptions opt /// Thrown when a general API error occurs. /// [ManualRoute("PUT", "/teams/{team_id}/repos/{owner}/{repo}")] - // TODO :: rename method to AddOrUpdateTeamRepositoryPermissions public async Task AddRepository(int id, string organization, string repoName) { Ensure.ArgumentNotNullOrEmptyString(organization, nameof(organization)); @@ -437,7 +436,6 @@ public async Task AddRepository(int id, string organization, string repoNa /// Thrown when a general API error occurs. /// [ManualRoute("PUT", "/teams/{team_id}/repos/{owner}/{repo}")] - // TODO :: rename method to AddOrUpdateTeamRepositoryPermissions public async Task AddRepository(int id, string organization, string repoName, RepositoryPermissionRequest permission) { Ensure.ArgumentNotNullOrEmptyString(organization, nameof(organization)); @@ -476,7 +474,6 @@ public async Task AddRepository(int id, string organization, string repoNa /// Thrown when a general API error occurs. /// [ManualRoute("DELETE", "/teams/{team_id}/repos/{owner}/{repo}")] - // TODO :: rename to RemoveRepositoryFromTeam public async Task RemoveRepository(int id, string organization, string repoName) { Ensure.ArgumentNotNullOrEmptyString(organization, nameof(organization)); @@ -630,7 +627,7 @@ public Task AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, st var endpoint = ApiUrls.TeamPermissionsForARepository(org, teamSlug, owner, repo); - return ApiConnection.Put(endpoint, new { permission }, null); + return ApiConnection.Put(endpoint, new { permission }); } /// diff --git a/Octokit/Http/ApiConnection.cs b/Octokit/Http/ApiConnection.cs index 0873e71195..6893766b62 100644 --- a/Octokit/Http/ApiConnection.cs +++ b/Octokit/Http/ApiConnection.cs @@ -343,14 +343,13 @@ public Task Put(Uri uri) /// /// URI of the API resource to put /// Object that describes the API resource; this will be serialized and used as the request's body - /// Accept header to use for the API request /// A for the request's execution. - public Task Put(Uri uri, object data, string accepts) + public Task Put(Uri uri, object data) { Ensure.ArgumentNotNull(uri, nameof(uri)); Ensure.ArgumentNotNull(data, nameof(data)); - return Connection.Put(uri, data, null); + return Connection.Put(uri, data); } /// diff --git a/Octokit/Http/Connection.cs b/Octokit/Http/Connection.cs index ba8402f024..6a9f065c86 100644 --- a/Octokit/Http/Connection.cs +++ b/Octokit/Http/Connection.cs @@ -499,14 +499,13 @@ public async Task Put(Uri uri) /// /// URI endpoint to send request to /// The object to serialize as the body of the request - /// Specifies accepted response media types. /// The returned - public async Task Put(Uri uri, object body, string accepts) + public async Task Put(Uri uri, object body) { Ensure.ArgumentNotNull(uri, nameof(uri)); Ensure.ArgumentNotNull(body, nameof(body)); - var response = await SendData(uri, HttpMethod.Put, body, accepts, null, CancellationToken.None).ConfigureAwait(false); + var response = await SendData(uri, HttpMethod.Put, body, null, null, CancellationToken.None).ConfigureAwait(false); return response.HttpResponse.StatusCode; } diff --git a/Octokit/Http/IApiConnection.cs b/Octokit/Http/IApiConnection.cs index 44d2c87fed..ce915527c7 100644 --- a/Octokit/Http/IApiConnection.cs +++ b/Octokit/Http/IApiConnection.cs @@ -239,9 +239,8 @@ public interface IApiConnection /// /// URI of the API resource to put /// Object that describes the API resource; this will be serialized and used as the request's body - /// Accept header to use for the API request /// A for the request's execution. - Task Put(Uri uri, object data, string accepts); + Task Put(Uri uri, object data); /// /// Creates or replaces the API resource at the specified URI. diff --git a/Octokit/Http/IConnection.cs b/Octokit/Http/IConnection.cs index 1e38d4be9b..3eacde0494 100644 --- a/Octokit/Http/IConnection.cs +++ b/Octokit/Http/IConnection.cs @@ -252,9 +252,8 @@ Task> Post( /// /// URI endpoint to send request to /// The object to serialize as the body of the request - /// Specifies accepted response media types. /// The returned - Task Put(Uri uri, object body, string accepts); + Task Put(Uri uri, object body); /// /// Performs an asynchronous HTTP DELETE request that expects an empty response. From 662b40aeeb143ba02042539eaf72a61695de5c8e Mon Sep 17 00:00:00 2001 From: notauserx Date: Sun, 11 Dec 2022 09:49:12 +0600 Subject: [PATCH 28/39] fix docstring comment --- Octokit.Reactive/Clients/IObservableTeamsClient.cs | 2 +- Octokit.Reactive/Clients/ObservableTeamsClient.cs | 2 +- Octokit/Clients/ITeamsClient.cs | 2 +- Octokit/Clients/TeamsClient.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 622c350ea7..b3fe8fbe99 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -128,7 +128,7 @@ public interface IObservableTeamsClient /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// - /// /// + /// /// See the API documentation /// for more information. /// diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 3c814bcca0..b37e2d9c25 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -197,7 +197,7 @@ public IObservable Create(string org, NewTeam team) /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// - /// /// + /// /// See the API documentation /// for more information. /// diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 9c542f898f..c3d525bf46 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -129,7 +129,7 @@ public interface ITeamsClient /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// - /// /// + /// /// See the API documentation /// for more information. /// diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 8ef5900be0..114c92d4f1 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -231,7 +231,7 @@ public Task Create(string org, NewTeam team) /// Updates a team /// To edit a team, the authenticated user must either be an organization owner or a team maintainer /// - /// /// + /// /// See the API documentation /// for more information. /// From 2a6497f77c8f12192ad21966be39432ae3c96874 Mon Sep 17 00:00:00 2001 From: notauserx Date: Sun, 11 Dec 2022 18:18:27 +0600 Subject: [PATCH 29/39] the unit tests are in finally --- Octokit.Tests/Clients/TeamsClientTests.cs | 128 ++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs index 6dce430d77..f8005533d4 100644 --- a/Octokit.Tests/Clients/TeamsClientTests.cs +++ b/Octokit.Tests/Clients/TeamsClientTests.cs @@ -471,5 +471,133 @@ public async Task RequestsTheCorrectUrl() Args.ApiOptions); } } + + public class TheCheckTeamPermissionsForARepositoryMethod + { + [Fact] + public async Task EnsuresNonNullOrEmptyArguments() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository(null, "teamSlug", "owner", "repo")); + await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository("org", null, "owner", "repo")); + await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository("org", "teamSlug", null, "repo")); + await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository("org", "teamSlug", "owner", null)); + } + + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await client.CheckTeamPermissionsForARepository("org", "teamSlug", "owner", "repo"); + + var expected = "/orgs/org/teams/teamSlug/repos/owner/repo"; + + connection.Received().Get(Arg.Is(u => u.ToString() == expected)); + } + + [Fact] + public async Task RequestsTheCorrectUrlWithCustomMediaTypeHeader() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await client.CheckTeamPermissionsForARepository("org", "teamSlug", "owner", "repo", true); + + var expected = "/orgs/org/teams/teamSlug/repos/owner/repo"; + + connection.Received().Get( + Arg.Is(u => u.ToString() == expected), + null, + Arg.Is(s => s.Equals("application/vnd.github.v3.repository+json"))); + } + } + + public class TheAddOrUpdateTeamRepositoryPermissionsMethod + { + [Fact] + public async Task EnsuresNonNullOrEmptyArguments() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions(null, "teamSlug", "owner", "repo", "permission")); + await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", null, "owner", "repo", "permission")); + await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", null, "repo", "permission")); + await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", "owner", null, "permission")); + } + + [Fact] + public async Task EnsuresNullPermissionValueDoesNotThrow() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + var exception = await Record.ExceptionAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", "owner", "repo", null)); + + Assert.Null(exception); + } + + + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + var permission = "a"; + + await client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", "owner", "repo", permission); + + var expected = "/orgs/org/teams/teamSlug/repos/owner/repo"; + + connection.Received().Put( + Arg.Is(u => u.ToString() == expected), + Arg.Any()); + } + + [Fact] + public async Task PassesTheCorrestPermission() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + var permission = "a"; + + await client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", "owner", "repo", permission); + + connection.Received().Put( + Arg.Any(), + Arg.Is(o => o.GetType().GetProperty("permission").GetValue(o).ToString() == "a")); + } + } + + public class TheRemoveRepositoryFromATeamMethod + { + [Fact] + public async Task EnsuresNonNullOrEmptyArguments() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => client.RemoveRepositoryFromATeam(null, "teamSlug", "owner", "repo")); + await Assert.ThrowsAsync(() => client.RemoveRepositoryFromATeam("org", null, "owner", "repo")); + await Assert.ThrowsAsync(() => client.RemoveRepositoryFromATeam("org", "teamSlug", null, "repo")); + await Assert.ThrowsAsync(() => client.RemoveRepositoryFromATeam("org", "teamSlug", "owner", null)); + } + + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await client.RemoveRepositoryFromATeam("org", "teamSlug", "owner", "repo"); + + var expected = "/orgs/org/teams/teamSlug/repos/owner/repo"; + + connection.Received().Delete(Arg.Is(u => u.ToString() == expected)); + } + } } } From d40e98111225c0c9d55b371c1602d4a636255ca3 Mon Sep 17 00:00:00 2001 From: notauserx Date: Sun, 11 Dec 2022 18:52:23 +0600 Subject: [PATCH 30/39] add docs for teams api --- docs/teams.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 docs/teams.md diff --git a/docs/teams.md b/docs/teams.md new file mode 100644 index 0000000000..2bfb1f9d56 --- /dev/null +++ b/docs/teams.md @@ -0,0 +1,77 @@ +# Working with Teams + +To access the teams API, you need to be an authenticated member of the organization's team. OAuth access tokens require the read:org scope. The ITeamsClient houses the endpoints for the teams API. + +### Create, update or delete teams + +To create a new team, you need to be a member of owner of the organization. + +```csharp +var newTeam = new NewTeam("team-name") +{ + Description = "my cool team description", + Privacy = TeamPrivacy.Closed +}; +newTeam.Maintainers.Add("maintainer-name"); +newTeam.RepoNames.Add("repository-name"); + +var team = await github.Organization.Team.Create("organization-name", newTeam); +``` + +Updating and deleting a team is also possible + +```csharp +var update = new UpdateTeam("team-name",) +{ + Description = "my new team description", + Privacy = TeamPrivacy.Closed, + Permission = TeamPermission.Push, +}; + +var team = await _github.Organization.Team.Update("organization-name", "team-slug", update); +``` + +```csharp +var team = await _github.Organization.Team.Delete("organization-name", "team-slug"); +``` + +### Working with repositories for the team + +You can get the list of repositories for the team by following + +```csharp +var allRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId); +``` +Or check permissions for a specific repository with the CheckTeamPermissionsForARepository method. + +```csharp +await github.Organization.Team.CheckTeamPermissionsForARepository( + "organization-name", + "team-slug", + "repository-owner", + "repository-name", + false); +``` + + The following snippet shows how to add or update team repository permissions. + + Permissions can be one of pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the owning organization has defined any. If no permission is specified, the team's permission attribute will be used to determine what permission to grant the team on this repository. + +```csharp +await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions( + "organization-name", + "team-slug", + "repository-owner", + "repository-name", + "admin"); +``` + +To remove a repository form a team, use + +```csharp +await github.Organization.Team.RemoveRepositoryFromATeam( + "organization-name", + "team-slug", + "repository-owner", + "repository-name"); +``` \ No newline at end of file From a4deb959a00135388786c6d2725e4efcd5a40330 Mon Sep 17 00:00:00 2001 From: notauserx Date: Tue, 13 Dec 2022 19:14:57 +0600 Subject: [PATCH 31/39] split CheckTeamPermissions into two methods --- .../Clients/IObservableTeamsClient.cs | 19 ++++++-- .../Clients/ObservableTeamsClient.cs | 24 ++++++++-- Octokit.Tests.Conventions/PreviewsTests.cs | 3 +- .../Clients/TeamsClientTests.cs | 43 +++++++++++++---- .../Reactive/ObservableTeamsClientTests.cs | 47 ++++++++++++++----- Octokit.Tests/Clients/TeamsClientTests.cs | 23 ++++++++- Octokit/Clients/ITeamsClient.cs | 19 ++++++-- Octokit/Clients/TeamsClient.cs | 42 ++++++++++++++--- Octokit/Helpers/AcceptHeaders.cs | 2 + 9 files changed, 180 insertions(+), 42 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index b3fe8fbe99..52b960aec5 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -306,11 +306,24 @@ public interface IObservableTeamsClient /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. - /// privides repository as a media typ in accepts header + /// + IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo); + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. /// Thrown when a general API error occurs. /// - IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, - bool provideRepositoryMediaTypeInAcceptHeader = false); + IObservable CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(string org, string teamSlug, string owner, string repo); /// /// Add or update team repository permissions diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index b37e2d9c25..f9a0666bd3 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -453,13 +453,29 @@ public IObservable GetAllPendingInvitations(in /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. - /// privides repository as a media typ in accepts header + /// + public IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo) + { + return _client.CheckTeamPermissionsForARepository(org, teamSlug, owner, repo).ToObservable(); + } + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. /// Thrown when a general API error occurs. /// - public IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, - bool provideRepositoryMediaTypeInAcceptHeader = false) + public IObservable CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(string org, string teamSlug, string owner, string repo) { - return _client.CheckTeamPermissionsForARepository(org, teamSlug, owner, repo, provideRepositoryMediaTypeInAcceptHeader).ToObservable(); + return _client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(org, teamSlug, owner, repo).ToObservable(); } /// diff --git a/Octokit.Tests.Conventions/PreviewsTests.cs b/Octokit.Tests.Conventions/PreviewsTests.cs index 8fd06610c2..6a0fdfa6e4 100644 --- a/Octokit.Tests.Conventions/PreviewsTests.cs +++ b/Octokit.Tests.Conventions/PreviewsTests.cs @@ -70,7 +70,8 @@ public void NoStalePreviews() // https://developer.github.com/v3/repos/commits/#get-a-single-commit "application/vnd.github.v3.sha", // https://developer.github.com/v3/activity/starring/#alternative-response-with-star-creation-timestamps - "application/vnd.github.v3.star+json" + "application/vnd.github.v3.star+json", + "application/vnd.github.v3.repository+json" }; var validHeaders = defaultHeaders.Concat(previewAcceptHeaders); diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index f49ffe82a5..0735cc2f60 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -520,17 +520,42 @@ public async Task ChecksTeamPermissions() { github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); - var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + var teamPermissionResponse = await github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, teamContext.Team.Slug, repositoryContext.RepositoryOwner, - repositoryContext.RepositoryName, - false); + repositoryContext.RepositoryName); - Assert.Null(teamPermission); + Assert.True(teamPermissionResponse); } } + [OrganizationTest] + public async Task ChecksTeamPermissionsReturnsFalseOnNonTeamRepository() + { + using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + var response = await github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + teamContext.Team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName); + + Assert.False(response); + } + } + } + + public class TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod + { + private readonly IGitHubClient github; + + public TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod() + { + github = Helper.GetAuthenticatedClient(); + } + [OrganizationTest] public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAccepts() { @@ -539,12 +564,11 @@ public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAccepts() { github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); - var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepository( + var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader( Helper.Organization, teamContext.Team.Slug, repositoryContext.RepositoryOwner, - repositoryContext.RepositoryName, - true); + repositoryContext.RepositoryName); Assert.NotNull(teamPermission); Assert.NotNull(teamPermission.Permissions); @@ -559,12 +583,11 @@ public async Task ChecksTeamPermissionsThrowsNotFoundException() using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { await Assert.ThrowsAsync(async () => - await github.Organization.Team.CheckTeamPermissionsForARepository( + await github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader( Helper.Organization, teamContext.Team.Slug, repositoryContext.RepositoryOwner, - repositoryContext.RepositoryName, - false)); + repositoryContext.RepositoryName)); } } } diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index 05ca151375..00e5ef6996 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -451,34 +451,57 @@ public async Task ChecksTeamPermissions() { _github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); - var teamPermission = await _github.Organization.Team.CheckTeamPermissionsForARepository( + var teamPermissionResponse = await _github.Organization.Team.CheckTeamPermissionsForARepository( Helper.Organization, teamContext.Team.Slug, repositoryContext.RepositoryOwner, repositoryContext.RepositoryName); - Assert.Null(teamPermission); + Assert.True(teamPermissionResponse); } } [OrganizationTest] - public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAcceots() + public async Task ChecksTeamPermissionsReturnsFalseOnNonTeamRepository() + { + using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) + using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) + { + var response = await _github.Organization.Team.CheckTeamPermissionsForARepository( + Helper.Organization, + teamContext.Team.Slug, + repositoryContext.RepositoryOwner, + repositoryContext.RepositoryName); + + Assert.False(response); + } + } + } + + public class TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod + { + private readonly IObservableGitHubClient _github; + public TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod() + { + _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient()); + + } + + [OrganizationTest] + public async Task ChecksTeamPermissions() { using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team")))) using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { _github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName); - var teamPermission = await _github.Organization.Team.CheckTeamPermissionsForARepository( + var teamPermissionResponse = await _github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader( Helper.Organization, teamContext.Team.Slug, repositoryContext.RepositoryOwner, - repositoryContext.RepositoryName, - true); + repositoryContext.RepositoryName); - Assert.NotNull(teamPermission); - Assert.NotNull(teamPermission.Permissions); - Assert.True(teamPermission.Permissions.Pull); + Assert.NotNull(teamPermissionResponse); } } @@ -489,16 +512,14 @@ public async Task ChecksTeamPermissionsThrowsNotFoundException() using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo")))) { await Assert.ThrowsAsync(async () => - await _github.Organization.Team.CheckTeamPermissionsForARepository( + await _github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader( Helper.Organization, teamContext.Team.Slug, repositoryContext.RepositoryOwner, - repositoryContext.RepositoryName, - false)); + repositoryContext.RepositoryName)); } } } - public class TheAddOrUpdateTeamRepositoryPermissionsMethod { private readonly IObservableGitHubClient _github; diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs index f8005533d4..dbca008032 100644 --- a/Octokit.Tests/Clients/TeamsClientTests.cs +++ b/Octokit.Tests/Clients/TeamsClientTests.cs @@ -498,14 +498,33 @@ public async Task RequestsTheCorrectUrl() connection.Received().Get(Arg.Is(u => u.ToString() == expected)); } + } + public class TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod + { [Fact] - public async Task RequestsTheCorrectUrlWithCustomMediaTypeHeader() + public async Task EnsuresNonNullOrEmptyArguments() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => + client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(null, "teamSlug", "owner", "repo")); + await Assert.ThrowsAsync(() => + client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", null, "owner", "repo")); + await Assert.ThrowsAsync(() => + client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", "teamSlug", null, "repo")); + await Assert.ThrowsAsync(() => + client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", "teamSlug", "owner", null)); + } + + [Fact] + public async Task RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new TeamsClient(connection); - await client.CheckTeamPermissionsForARepository("org", "teamSlug", "owner", "repo", true); + await client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", "teamSlug", "owner", "repo"); var expected = "/orgs/org/teams/teamSlug/repos/owner/repo"; diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index c3d525bf46..2840811dd4 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -298,11 +298,24 @@ public interface ITeamsClient /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. - /// privides repository as a media typ in accepts header + /// + Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo); + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. /// Thrown when a general API error occurs. /// - Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, - bool provideRepositoryMediaTypeInAcceptHeader = false); + Task CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(string org, string teamSlug, string owner, string repo); /// /// Add or update team repository permissions diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 114c92d4f1..e41d057330 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -579,12 +579,44 @@ public Task> GetAllPendingInvita /// The slug of the team name. /// The account owner of the repository. The name is not case sensitive. /// The name of the repository. The name is not case sensitive. - /// privides repository as a media typ in accepts header + /// + [ManualRoute("GET", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] + public async Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrEmptyString(teamSlug, nameof(teamSlug)); + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); + + var endpoint = ApiUrls.TeamPermissionsForARepository(org, teamSlug, owner, repo); + + try + { + var response = await ApiConnection.Get(endpoint); + return response == null; + } + catch(NotFoundException) + { + return false; + } + } + + /// + /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository. + /// Repositories inherited through a parent team will also be checked. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The organization name. The name is not case sensitive. + /// The slug of the team name. + /// The account owner of the repository. The name is not case sensitive. + /// The name of the repository. The name is not case sensitive. /// Thrown when a general API error occurs. /// [ManualRoute("GET", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")] - public Task CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo, - bool provideRepositoryMediaTypeInAcceptHeader = false) + public Task CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(string org, string teamSlug, string owner, string repo) { Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); Ensure.ArgumentNotNullOrEmptyString(teamSlug, nameof(teamSlug)); @@ -593,9 +625,7 @@ public Task CheckTeamPermissionsForARepository(string org, strin var endpoint = ApiUrls.TeamPermissionsForARepository(org, teamSlug, owner, repo); - return provideRepositoryMediaTypeInAcceptHeader - ? ApiConnection.Get(endpoint, null, "application/vnd.github.v3.repository+json") - : ApiConnection.Get(endpoint); + return ApiConnection.Get(endpoint, null, AcceptHeaders.RepositoryContentMediaType); } /// diff --git a/Octokit/Helpers/AcceptHeaders.cs b/Octokit/Helpers/AcceptHeaders.cs index c39c1baddf..c43e9cbdfb 100644 --- a/Octokit/Helpers/AcceptHeaders.cs +++ b/Octokit/Helpers/AcceptHeaders.cs @@ -13,5 +13,7 @@ public static class AcceptHeaders /// /// https://developer.github.com/v3/repos/contents/#custom-media-types public const string RawContentMediaType = "application/vnd.github.v3.raw"; + + public const string RepositoryContentMediaType = "application/vnd.github.v3.repository+json"; } } From f3d6980bada3fb21519a62d2d57ca9b1ef047074 Mon Sep 17 00:00:00 2001 From: notauserx <82922717+notauserx@users.noreply.github.com> Date: Thu, 15 Dec 2022 10:35:02 +0600 Subject: [PATCH 32/39] Update ObservableTeamsClientTests.cs based on review Co-authored-by: Keegan Campbell --- Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs index 00e5ef6996..a818b20c04 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs @@ -520,6 +520,7 @@ await _github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcce } } } + public class TheAddOrUpdateTeamRepositoryPermissionsMethod { private readonly IObservableGitHubClient _github; From 960382c2ff68b604297d83443130d410eac48dbc Mon Sep 17 00:00:00 2001 From: notauserx Date: Thu, 15 Dec 2022 11:46:06 +0600 Subject: [PATCH 33/39] add cref to legacy update and delete endpoints --- Octokit.Reactive/Clients/IObservableTeamsClient.cs | 4 +++- Octokit.Reactive/Clients/ObservableTeamsClient.cs | 4 +++- Octokit/Clients/ITeamsClient.cs | 4 +++- Octokit/Clients/TeamsClient.cs | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 52b960aec5..745aa620e3 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -138,7 +138,8 @@ public interface IObservableTeamsClient /// /// Returns updated for the current org. /// This endpoint route is deprecated and will be removed from the Teams API. - /// We recommend migrating your existing code to use the new Update a team endpoint + /// We recommend migrating your existing code to use the new Update a team endpoint. + /// /// /// /// See the API documentation @@ -165,6 +166,7 @@ public interface IObservableTeamsClient /// Delete a team - must have owner permissions to do this /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. + /// . /// /// /// See the API documentation diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index f9a0666bd3..f068d468bb 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -214,7 +214,8 @@ public IObservable Update(string org, string teamSlug, UpdateTeam team) /// /// Returns updated for the current org. /// This endpoint route is deprecated and will be removed from the Teams API. - /// We recommend migrating your existing code to use the new Update a team endpoint + /// We recommend migrating your existing code to use the new Update a team endpoint. + /// . /// /// /// See the API documentation @@ -252,6 +253,7 @@ public IObservable Delete(string org, string teamSlug) /// Delete a team - must have owner permissions to do this /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. + /// . /// /// /// See the API documentation diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 2840811dd4..9507c125e4 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -139,7 +139,8 @@ public interface ITeamsClient /// /// Returns updated for the current org. /// This endpoint route is deprecated and will be removed from the Teams API. - /// We recommend migrating your existing code to use the new Update a team endpoint + /// We recommend migrating your existing code to use the new Update a team endpoint. + /// . /// /// /// See the API documentation @@ -166,6 +167,7 @@ public interface ITeamsClient /// Delete a team - must have owner permissions to do this /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. + /// . /// /// /// See the API documentation diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index e41d057330..aa62fe80e6 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -251,7 +251,8 @@ public Task Update(string org, string teamSlug, UpdateTeam team) /// /// Returns updated for the current org. /// This endpoint route is deprecated and will be removed from the Teams API. - /// We recommend migrating your existing code to use the new Update a team endpoint + /// We recommend migrating your existing code to use the new Update a team endpoint. + /// . /// /// /// See the API documentation @@ -294,6 +295,7 @@ public Task Delete(string org, string teamSlug) /// Delete a team - must have owner permissions to do this /// This endpoint route is deprecated and will be removed from the Teams API. /// We recommend migrating your existing code to use the new Delete a team endpoint. + /// . /// /// /// See the API documentation From 62de913e0d3c37cc0796f7beff6bbc94ddcaf7dd Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 16 Dec 2022 20:52:54 +0600 Subject: [PATCH 34/39] remove editorconfig file --- .editorconfig | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index d605dc22d8..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -root = true -[*.cs] -end_of_line = lf From 4e2c83383fd98fa2ba3e4424e509e02ce0d657c4 Mon Sep 17 00:00:00 2001 From: notauserx <82922717+notauserx@users.noreply.github.com> Date: Fri, 6 Jan 2023 08:21:18 +0600 Subject: [PATCH 35/39] Update Octokit.Tests/Clients/TeamsClientTests.cs Co-authored-by: Keegan Campbell --- Octokit.Tests/Clients/TeamsClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs index dbca008032..b29e921c07 100644 --- a/Octokit.Tests/Clients/TeamsClientTests.cs +++ b/Octokit.Tests/Clients/TeamsClientTests.cs @@ -244,7 +244,7 @@ public async Task EnsuresNonNullArguments() } } - public class TheDeleteTeamLegacuMethod + public class TheDeleteTeamLegacyMethod { [Fact] public void RequestsTheCorrectUrl() From aa6788f52cbd4e772d8b616ba08bc1aa84b3a7db Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 6 Jan 2023 08:38:27 +0600 Subject: [PATCH 36/39] remove unused line --- Octokit/Clients/TeamsClient.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index aa62fe80e6..af41cc3119 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -245,7 +245,6 @@ public Task Update(string org, string teamSlug, UpdateTeam team) var endpoint = ApiUrls.TeamsByOrganizationAndSlug(org, teamSlug); return ApiConnection.Patch(endpoint, team); - throw new NotImplementedException(); } /// From ca7de3b0176b79f31acc57c592e4cca1ae4a808a Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 6 Jan 2023 08:39:15 +0600 Subject: [PATCH 37/39] rename variable based on review --- Octokit/Models/Response/Team.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs index bff651938e..f15e2c0d1f 100644 --- a/Octokit/Models/Response/Team.cs +++ b/Octokit/Models/Response/Team.cs @@ -12,7 +12,7 @@ public class Team { public Team() { } - public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, string permission, TeamRepositoryPermissions permissions, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) + public Team(string url, string htmlUrl, int id, string nodeId, string slug, string name, string description, TeamPrivacy privacy, string permission, TeamRepositoryPermissions teamRepositoryPermissions, int membersCount, int reposCount, Organization organization, Team parent, string ldapDistinguishedName) { Url = url; HtmlUrl = htmlUrl; @@ -23,7 +23,7 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri Description = description; Privacy = privacy; Permission = permission; - Permissions = permissions; + Permissions = teamRepositoryPermissions; MembersCount = membersCount; ReposCount = reposCount; Organization = organization; From c73545baf1d714cb7c32b7b45d41008125742fd0 Mon Sep 17 00:00:00 2001 From: notauserx Date: Fri, 6 Jan 2023 09:17:58 +0600 Subject: [PATCH 38/39] rename prop to match constructor param --- Octokit/Models/Response/Team.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs index f15e2c0d1f..4c4be950f6 100644 --- a/Octokit/Models/Response/Team.cs +++ b/Octokit/Models/Response/Team.cs @@ -23,7 +23,7 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri Description = description; Privacy = privacy; Permission = permission; - Permissions = teamRepositoryPermissions; + TeamRepositoryPermissions = teamRepositoryPermissions; MembersCount = membersCount; ReposCount = reposCount; Organization = organization; @@ -79,7 +79,7 @@ public Team(string url, string htmlUrl, int id, string nodeId, string slug, stri /// /// /// - public TeamRepositoryPermissions Permissions { get; private set; } + public TeamRepositoryPermissions TeamRepositoryPermissions { get; private set; } /// /// how many members in this team From 2ec885da00525ee77a0e0a70362293592862297c Mon Sep 17 00:00:00 2001 From: notauserx Date: Sat, 7 Jan 2023 21:43:34 +0600 Subject: [PATCH 39/39] add comment to explain TeamPermission enum values on update --- Octokit/Models/Request/UpdateTeam.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Octokit/Models/Request/UpdateTeam.cs b/Octokit/Models/Request/UpdateTeam.cs index d912e529b6..e9297a2ecf 100644 --- a/Octokit/Models/Request/UpdateTeam.cs +++ b/Octokit/Models/Request/UpdateTeam.cs @@ -36,6 +36,9 @@ public UpdateTeam(string name) /// /// The permission that new repositories will be added to the team with when none is specified (default: Pull) + /// Although permission can be one of : pull, push, or admin based on documentation, passing admin results in an error response. + /// That's why TeamPermission does not contain an admin value. + /// See the issue here https://github.com/github/rest-api-description/issues/1952 /// public TeamPermission? Permission { get; set; }