From c2aee1ac54083ab51657042bdc245c0ff0b2571c Mon Sep 17 00:00:00 2001 From: Colby Williams Date: Mon, 24 Jun 2024 12:24:45 -0500 Subject: [PATCH] [FEAT]: Create a GitHub App from a manifest * Create a GitHub App from a manifest * Add missing InstallationPermissions * observable and tests * Remove ManualRoute on Observable route --------- Co-authored-by: Nick Floyd <139819+nickfloyd@users.noreply.github.com> --- .../Clients/IObservableGitHubAppsClient.cs | 8 ++ .../Clients/ObservableGitHubAppsClient.cs | 13 +++ .../Clients/GitHubAppsClientTests.cs | 32 ++++++++ .../Models/GitHubAppFromManifestTests.cs | 81 +++++++++++++++++++ .../ObservableGitHubAppsClientTests.cs | 32 ++++++++ Octokit/Clients/GitHubAppsClient.cs | 14 ++++ Octokit/Clients/IGitHubAppsClient.cs | 10 ++- Octokit/Helpers/ApiUrls.cs | 9 +++ Octokit/Models/Response/GitHubApp.cs | 30 ++++--- .../Models/Response/GitHubAppFromManifest.cs | 45 +++++++++++ .../Response/InstallationPermissions.cs | 21 +++++ 11 files changed, 282 insertions(+), 13 deletions(-) create mode 100644 Octokit.Tests/Models/GitHubAppFromManifestTests.cs create mode 100644 Octokit/Models/Response/GitHubAppFromManifest.cs diff --git a/Octokit.Reactive/Clients/IObservableGitHubAppsClient.cs b/Octokit.Reactive/Clients/IObservableGitHubAppsClient.cs index 30a7e70d..089086bc 100644 --- a/Octokit.Reactive/Clients/IObservableGitHubAppsClient.cs +++ b/Octokit.Reactive/Clients/IObservableGitHubAppsClient.cs @@ -110,5 +110,13 @@ namespace Octokit.Reactive /// https://developer.github.com/v3/apps/#find-user-installation /// The name of the user IObservable GetUserInstallationForCurrent(string user); + + /// + /// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow. + /// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest + /// + /// https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest + /// Temporary code in a code parameter. + IObservable CreateAppFromManifest(string code); } } diff --git a/Octokit.Reactive/Clients/ObservableGitHubAppsClient.cs b/Octokit.Reactive/Clients/ObservableGitHubAppsClient.cs index 8179baa5..0077cd68 100644 --- a/Octokit.Reactive/Clients/ObservableGitHubAppsClient.cs +++ b/Octokit.Reactive/Clients/ObservableGitHubAppsClient.cs @@ -175,5 +175,18 @@ namespace Octokit.Reactive return _client.GetUserInstallationForCurrent(user).ToObservable(); } + + /// + /// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow. + /// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest + /// + /// https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest + /// Temporary code in a code parameter. + public IObservable CreateAppFromManifest(string code) + { + Ensure.ArgumentNotNullOrEmptyString(code, nameof(code)); + + return _client.CreateAppFromManifest(code).ToObservable(); + } } } diff --git a/Octokit.Tests/Clients/GitHubAppsClientTests.cs b/Octokit.Tests/Clients/GitHubAppsClientTests.cs index 5647679e..ee68fde3 100644 --- a/Octokit.Tests/Clients/GitHubAppsClientTests.cs +++ b/Octokit.Tests/Clients/GitHubAppsClientTests.cs @@ -273,5 +273,37 @@ namespace Octokit.Tests.Clients connection.Received().Get(Arg.Is(u => u.ToString() == "users/ducks/installation"), null); } } + + public class TheCreateAppFromManifestMethod + { + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new GitHubAppsClient(connection); + + await Assert.ThrowsAsync(() => client.CreateAppFromManifest(null)); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var connection = Substitute.For(); + var client = new GitHubAppsClient(connection); + + await Assert.ThrowsAsync(() => client.CreateAppFromManifest("")); + } + + [Fact] + public void PostsFromCorrectUrl() + { + var connection = Substitute.For(); + var client = new GitHubAppsClient(connection); + + client.CreateAppFromManifest("abc123"); + + connection.Received().Post(Arg.Is(u => u.ToString() == "app-manifests/abc123/conversions")); + } + } } } diff --git a/Octokit.Tests/Models/GitHubAppFromManifestTests.cs b/Octokit.Tests/Models/GitHubAppFromManifestTests.cs new file mode 100644 index 00000000..262a6720 --- /dev/null +++ b/Octokit.Tests/Models/GitHubAppFromManifestTests.cs @@ -0,0 +1,81 @@ +using Octokit.Internal; +using Xunit; + +namespace Octokit.Tests.Models +{ + public class GitHubAppFromManifestTests + { + [Fact] + public void CanBeDeserialized() + { + // from https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest + const string json = @"{ + ""id"": 1, + ""slug"": ""octoapp"", + ""node_id"": ""MDxOkludGVncmF0aW9uMQ=="", + ""owner"": { + ""login"": ""github"", + ""id"": 1, + ""node_id"": ""MDEyOk9yZ2FuaXphdGlvbjE="", + ""url"": ""https://api.github.com/orgs/github"", + ""repos_url"": ""https://api.github.com/orgs/github/repos"", + ""events_url"": ""https://api.github.com/orgs/github/events"", + ""avatar_url"": ""https://github.com/images/error/octocat_happy.gif"", + ""gravatar_id"": """", + ""html_url"": ""https://github.com/octocat"", + ""followers_url"": ""https://api.github.com/users/octocat/followers"", + ""following_url"": ""https://api.github.com/users/octocat/following{/other_user}"", + ""gists_url"": ""https://api.github.com/users/octocat/gists{/gist_id}"", + ""starred_url"": ""https://api.github.com/users/octocat/starred{/owner}{/repo}"", + ""subscriptions_url"": ""https://api.github.com/users/octocat/subscriptions"", + ""organizations_url"": ""https://api.github.com/users/octocat/orgs"", + ""received_events_url"": ""https://api.github.com/users/octocat/received_events"", + ""type"": ""User"", + ""site_admin"": true + }, + ""name"": ""Octocat App"", + ""description"": ""A short description of the app"", + ""external_url"": ""https://example.com"", + ""html_url"": ""https://github.com/apps/octoapp"", + ""created_at"": ""2017-07-08T16:18:44-04:00"", + ""updated_at"": ""2017-07-08T16:18:44-04:00"", + ""permissions"": { + ""metadata"": ""read"", + ""contents"": ""read"", + ""issues"": ""write"", + ""single_file"": ""write"" + }, + ""events"": [ + ""push"", + ""pull_request"" + ], + ""client_id"": ""Iv1.8a61f9b3a7aba766"", + ""client_secret"": ""1726be1638095a19edd134c77bde3aa2ece1e5d8"", + ""webhook_secret"": ""e340154128314309424b7c8e90325147d99fdafa"", + ""pem"": ""-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuEPzOUE+kiEH1WLiMeBytTEF856j0hOVcSUSUkZxKvqczkWM\n9vo1gDyC7ZXhdH9fKh32aapba3RSsp4ke+giSmYTk2mGR538ShSDxh0OgpJmjiKP\nX0Bj4j5sFqfXuCtl9SkH4iueivv4R53ktqM+n6hk98l6hRwC39GVIblAh2lEM4L/\n6WvYwuQXPMM5OG2Ryh2tDZ1WS5RKfgq+9ksNJ5Q9UtqtqHkO+E63N5OK9sbzpUUm\noNaOl3udTlZD3A8iqwMPVxH4SxgATBPAc+bmjk6BMJ0qIzDcVGTrqrzUiywCTLma\nszdk8GjzXtPDmuBgNn+o6s02qVGpyydgEuqmTQIDAQABAoIBACL6AvkjQVVLn8kJ\ndBYznJJ4M8ECo+YEgaFwgAHODT0zRQCCgzd+Vxl4YwHmKV2Lr+y2s0drZt8GvYva\nKOK8NYYZyi15IlwFyRXmvvykF1UBpSXluYFDH7KaVroWMgRreHcIys5LqVSIb6Bo\ngDmK0yBLPp8qR29s2b7ScZRtLaqGJiX+j55rNzrZwxHkxFHyG9OG+u9IsBElcKCP\nkYCVE8ZdYexfnKOZbgn2kZB9qu0T/Mdvki8yk3I2bI6xYO24oQmhnT36qnqWoCBX\nNuCNsBQgpYZeZET8mEAUmo9d+ABmIHIvSs005agK8xRaP4+6jYgy6WwoejJRF5yd\nNBuF7aECgYEA50nZ4FiZYV0vcJDxFYeY3kYOvVuKn8OyW+2rg7JIQTremIjv8FkE\nZnwuF9ZRxgqLxUIfKKfzp/5l5LrycNoj2YKfHKnRejxRWXqG+ZETfxxlmlRns0QG\nJ4+BYL0CoanDSeA4fuyn4Bv7cy/03TDhfg/Uq0Aeg+hhcPE/vx3ebPsCgYEAy/Pv\neDLssOSdeyIxf0Brtocg6aPXIVaLdus+bXmLg77rJIFytAZmTTW8SkkSczWtucI3\nFI1I6sei/8FdPzAl62/JDdlf7Wd9K7JIotY4TzT7Tm7QU7xpfLLYIP1bOFjN81rk\n77oOD4LsXcosB/U6s1blPJMZ6AlO2EKs10UuR1cCgYBipzuJ2ADEaOz9RLWwi0AH\nPza2Sj+c2epQD9ZivD7Zo/Sid3ZwvGeGF13JyR7kLEdmAkgsHUdu1rI7mAolXMaB\n1pdrsHureeLxGbRM6za3tzMXWv1Il7FQWoPC8ZwXvMOR1VQDv4nzq7vbbA8z8c+c\n57+8tALQHOTDOgQIzwK61QKBgERGVc0EJy4Uag+VY8J4m1ZQKBluqo7TfP6DQ7O8\nM5MX73maB/7yAX8pVO39RjrhJlYACRZNMbK+v/ckEQYdJSSKmGCVe0JrGYDuPtic\nI9+IGfSorf7KHPoMmMN6bPYQ7Gjh7a++tgRFTMEc8956Hnt4xGahy9NcglNtBpVN\n6G8jAoGBAMCh028pdzJa/xeBHLLaVB2sc0Fe7993WlsPmnVE779dAz7qMscOtXJK\nfgtriltLSSD6rTA9hUAsL/X62rY0wdXuNdijjBb/qvrx7CAV6i37NK1CjABNjsfG\nZM372Ac6zc1EqSrid2IjET1YqyIW2KGLI1R2xbQc98UGlt48OdWu\n-----END RSA PRIVATE KEY-----\n"" +}"; + + var app = new SimpleJsonSerializer().Deserialize(json); + + Assert.Equal(1, app.Id); + Assert.Equal("octoapp", app.Slug); + Assert.Equal("MDxOkludGVncmF0aW9uMQ==", app.NodeId); + Assert.Equal("Octocat App", app.Name); + Assert.Equal("A short description of the app", app.Description); + Assert.Equal("https://example.com", app.ExternalUrl); + Assert.Equal("https://github.com/apps/octoapp", app.HtmlUrl); + Assert.Equal(InstallationReadWritePermissionLevel.Write, app.Permissions.SingleFile); + Assert.Contains("push", app.Events); + + Assert.Equal("Iv1.8a61f9b3a7aba766", app.ClientId); + Assert.Equal("1726be1638095a19edd134c77bde3aa2ece1e5d8", app.ClientSecret); + Assert.Equal("e340154128314309424b7c8e90325147d99fdafa", app.WebhookSecret); + Assert.Equal("-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAuEPzOUE+kiEH1WLiMeBytTEF856j0hOVcSUSUkZxKvqczkWM\n9vo1gDyC7ZXhdH9fKh32aapba3RSsp4ke+giSmYTk2mGR538ShSDxh0OgpJmjiKP\nX0Bj4j5sFqfXuCtl9SkH4iueivv4R53ktqM+n6hk98l6hRwC39GVIblAh2lEM4L/\n6WvYwuQXPMM5OG2Ryh2tDZ1WS5RKfgq+9ksNJ5Q9UtqtqHkO+E63N5OK9sbzpUUm\noNaOl3udTlZD3A8iqwMPVxH4SxgATBPAc+bmjk6BMJ0qIzDcVGTrqrzUiywCTLma\nszdk8GjzXtPDmuBgNn+o6s02qVGpyydgEuqmTQIDAQABAoIBACL6AvkjQVVLn8kJ\ndBYznJJ4M8ECo+YEgaFwgAHODT0zRQCCgzd+Vxl4YwHmKV2Lr+y2s0drZt8GvYva\nKOK8NYYZyi15IlwFyRXmvvykF1UBpSXluYFDH7KaVroWMgRreHcIys5LqVSIb6Bo\ngDmK0yBLPp8qR29s2b7ScZRtLaqGJiX+j55rNzrZwxHkxFHyG9OG+u9IsBElcKCP\nkYCVE8ZdYexfnKOZbgn2kZB9qu0T/Mdvki8yk3I2bI6xYO24oQmhnT36qnqWoCBX\nNuCNsBQgpYZeZET8mEAUmo9d+ABmIHIvSs005agK8xRaP4+6jYgy6WwoejJRF5yd\nNBuF7aECgYEA50nZ4FiZYV0vcJDxFYeY3kYOvVuKn8OyW+2rg7JIQTremIjv8FkE\nZnwuF9ZRxgqLxUIfKKfzp/5l5LrycNoj2YKfHKnRejxRWXqG+ZETfxxlmlRns0QG\nJ4+BYL0CoanDSeA4fuyn4Bv7cy/03TDhfg/Uq0Aeg+hhcPE/vx3ebPsCgYEAy/Pv\neDLssOSdeyIxf0Brtocg6aPXIVaLdus+bXmLg77rJIFytAZmTTW8SkkSczWtucI3\nFI1I6sei/8FdPzAl62/JDdlf7Wd9K7JIotY4TzT7Tm7QU7xpfLLYIP1bOFjN81rk\n77oOD4LsXcosB/U6s1blPJMZ6AlO2EKs10UuR1cCgYBipzuJ2ADEaOz9RLWwi0AH\nPza2Sj+c2epQD9ZivD7Zo/Sid3ZwvGeGF13JyR7kLEdmAkgsHUdu1rI7mAolXMaB\n1pdrsHureeLxGbRM6za3tzMXWv1Il7FQWoPC8ZwXvMOR1VQDv4nzq7vbbA8z8c+c\n57+8tALQHOTDOgQIzwK61QKBgERGVc0EJy4Uag+VY8J4m1ZQKBluqo7TfP6DQ7O8\nM5MX73maB/7yAX8pVO39RjrhJlYACRZNMbK+v/ckEQYdJSSKmGCVe0JrGYDuPtic\nI9+IGfSorf7KHPoMmMN6bPYQ7Gjh7a++tgRFTMEc8956Hnt4xGahy9NcglNtBpVN\n6G8jAoGBAMCh028pdzJa/xeBHLLaVB2sc0Fe7993WlsPmnVE779dAz7qMscOtXJK\nfgtriltLSSD6rTA9hUAsL/X62rY0wdXuNdijjBb/qvrx7CAV6i37NK1CjABNjsfG\nZM372Ac6zc1EqSrid2IjET1YqyIW2KGLI1R2xbQc98UGlt48OdWu\n-----END RSA PRIVATE KEY-----\n", app.Pem); + + Assert.Equal(1, app.Owner.Id); + Assert.Equal("github", app.Owner.Login); + Assert.Equal("https://api.github.com/orgs/github", app.Owner.Url); + Assert.Equal(AccountType.User, app.Owner.Type); + } + } +} diff --git a/Octokit.Tests/Reactive/ObservableGitHubAppsClientTests.cs b/Octokit.Tests/Reactive/ObservableGitHubAppsClientTests.cs index ca6f27ff..12758acd 100644 --- a/Octokit.Tests/Reactive/ObservableGitHubAppsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableGitHubAppsClientTests.cs @@ -287,5 +287,37 @@ namespace Octokit.Tests.Clients gitHubClient.GitHubApps.Received().GetUserInstallationForCurrent("ducks"); } } + + public class TheCreateAppFromManifestMethod + { + [Fact] + public void EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableGitHubAppsClient(gitHubClient); + + Assert.Throws(() => client.CreateAppFromManifest(null)); + } + + [Fact] + public void EnsuresNonEmptyArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableGitHubAppsClient(gitHubClient); + + Assert.Throws(() => client.CreateAppFromManifest("")); + } + + [Fact] + public void GetsFromCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableGitHubAppsClient(gitHubClient); + + client.CreateAppFromManifest("abc123"); + + gitHubClient.GitHubApps.Received().CreateAppFromManifest("abc123"); + } + } } } diff --git a/Octokit/Clients/GitHubAppsClient.cs b/Octokit/Clients/GitHubAppsClient.cs index e9ee0ad2..4896c086 100644 --- a/Octokit/Clients/GitHubAppsClient.cs +++ b/Octokit/Clients/GitHubAppsClient.cs @@ -192,5 +192,19 @@ namespace Octokit return ApiConnection.Get(ApiUrls.UserInstallation(user), null); } + + /// + /// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow. + /// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest + /// + /// https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest + /// Temporary code in a code parameter. + [ManualRoute("POST", "/app-manifests/{code}/conversions")] + public Task CreateAppFromManifest(string code) + { + Ensure.ArgumentNotNullOrEmptyString(code, nameof(code)); + + return ApiConnection.Post(ApiUrls.AppManifestConversions(code)); + } } } diff --git a/Octokit/Clients/IGitHubAppsClient.cs b/Octokit/Clients/IGitHubAppsClient.cs index 4906a4fe..974e99ca 100644 --- a/Octokit/Clients/IGitHubAppsClient.cs +++ b/Octokit/Clients/IGitHubAppsClient.cs @@ -112,5 +112,13 @@ namespace Octokit /// https://developer.github.com/v3/apps/#find-user-installation /// The name of the user Task GetUserInstallationForCurrent(string user); + + /// + /// Creates a GitHub app by completing the handshake necessary when implementing the GitHub App Manifest flow. + /// https://docs.github.com/apps/sharing-github-apps/registering-a-github-app-from-a-manifest + /// + /// https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest + /// Temporary code in a code parameter. + Task CreateAppFromManifest(string code); } -} \ No newline at end of file +} diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 3e147ac7..1ca4b9c0 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -403,6 +403,15 @@ namespace Octokit return "notifications/threads/{0}/subscription".FormatUri(notificationId); } + /// + /// Returns the to complete the handshake necessary when implementing the GitHub App Manifest flow. + /// + /// Temporary code in a code parameter. + public static Uri AppManifestConversions(string code) + { + return "app-manifests/{0}/conversions".FormatUri(code); + } + /// /// Returns the for creating a new installation token. /// diff --git a/Octokit/Models/Response/GitHubApp.cs b/Octokit/Models/Response/GitHubApp.cs index f1dbc49c..d9c817cb 100644 --- a/Octokit/Models/Response/GitHubApp.cs +++ b/Octokit/Models/Response/GitHubApp.cs @@ -13,10 +13,11 @@ namespace Octokit { public GitHubApp() { } - public GitHubApp(long id, string slug, string name, User owner, string description, string externalUrl, string htmlUrl, DateTimeOffset createdAt, DateTimeOffset updatedAt, InstallationPermissions permissions, IReadOnlyList events) + public GitHubApp(long id, string slug, string nodeId, string name, User owner, string description, string externalUrl, string htmlUrl, DateTimeOffset createdAt, DateTimeOffset updatedAt, InstallationPermissions permissions, IReadOnlyList events) { Id = id; Slug = slug; + NodeId = nodeId; Name = name; Owner = owner; Description = description; @@ -31,57 +32,62 @@ namespace Octokit /// /// The Id of the GitHub App. /// - public long Id { get; private set; } + public long Id { get; protected set; } /// /// The url-friendly version of the GitHub App name. /// - public string Slug { get; private set; } + public string Slug { get; protected set; } + + /// + /// GraphQL Node Id + /// + public string NodeId { get; protected set; } /// /// The Name of the GitHub App. /// - public string Name { get; private set; } + public string Name { get; protected set; } /// /// The Owner of the GitHub App. /// - public User Owner { get; private set; } + public User Owner { get; protected set; } /// /// The Description of the GitHub App. /// - public string Description { get; private set; } + public string Description { get; protected set; } /// /// The URL to the GitHub App's external website. /// - public string ExternalUrl { get; private set; } + public string ExternalUrl { get; protected set; } /// /// The URL to view the GitHub App on GitHub. /// - public string HtmlUrl { get; private set; } + public string HtmlUrl { get; protected set; } /// /// Date the GitHub App was created. /// - public DateTimeOffset CreatedAt { get; private set; } + public DateTimeOffset CreatedAt { get; protected set; } /// /// Date the GitHub App was last updated. /// - public DateTimeOffset UpdatedAt { get; private set; } + public DateTimeOffset UpdatedAt { get; protected set; } /// /// The Permissions granted to the Installation /// - public InstallationPermissions Permissions { get; private set; } + public InstallationPermissions Permissions { get; protected set; } /// /// The Events subscribed to by the Installation /// - public IReadOnlyList Events { get; private set; } + public IReadOnlyList Events { get; protected set; } internal string DebuggerDisplay { diff --git a/Octokit/Models/Response/GitHubAppFromManifest.cs b/Octokit/Models/Response/GitHubAppFromManifest.cs new file mode 100644 index 00000000..8783d90f --- /dev/null +++ b/Octokit/Models/Response/GitHubAppFromManifest.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Octokit +{ + /// + /// Represents a GitHub application from a manifest. + /// https://docs.github.com/rest/apps/apps#create-a-github-app-from-a-manifest + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class GitHubAppFromManifest : GitHubApp + { + public GitHubAppFromManifest() { } + + public GitHubAppFromManifest(long id, string slug, string nodeId, string name, User owner, string description, string externalUrl, string htmlUrl, DateTimeOffset createdAt, DateTimeOffset updatedAt, InstallationPermissions permissions, IReadOnlyList events, string clientId, string clientSecret, string webhookSecret, string pem) + : base(id, slug, nodeId, name, owner, description, externalUrl, htmlUrl, createdAt, updatedAt, permissions, events) + { + ClientId = clientId; + ClientSecret = clientSecret; + WebhookSecret = webhookSecret; + Pem = pem; + } + + /// + /// The Client Id of the GitHub App. + /// + public string ClientId { get; private set; } + + /// + /// The Client Secret of the GitHub App. + /// + public string ClientSecret { get; private set; } + + /// + /// The Webhook Secret of the GitHub App. + /// + public string WebhookSecret { get; private set; } + + /// + /// The PEM of the GitHub App. + /// + public string Pem { get; private set; } + } +} diff --git a/Octokit/Models/Response/InstallationPermissions.cs b/Octokit/Models/Response/InstallationPermissions.cs index 5e4baf38..bdd8fdce 100644 --- a/Octokit/Models/Response/InstallationPermissions.cs +++ b/Octokit/Models/Response/InstallationPermissions.cs @@ -24,6 +24,7 @@ namespace Octokit InstallationReadWritePermissionLevel? pages, InstallationReadWritePermissionLevel? pullRequests, InstallationReadWritePermissionLevel? repositoryAnnouncementBanners, + InstallationReadWritePermissionLevel? repositoryCustomProperties, InstallationReadWritePermissionLevel? repositoryHooks, InstallationReadWriteAdminPermissionLevel? repositoryProjects, InstallationReadWritePermissionLevel? secretScanningAlerts, @@ -35,6 +36,8 @@ namespace Octokit InstallationWritePermissionLevel? workflows, InstallationReadWritePermissionLevel? members, InstallationReadWritePermissionLevel? organizationAdministration, + InstallationReadWritePermissionLevel? organizationCopilotSeatManagement, + InstallationReadWriteAdminPermissionLevel? organizationCustomProperties, InstallationReadWritePermissionLevel? organizationCustomRoles, InstallationReadWritePermissionLevel? organizationAnnouncementBanners, InstallationReadWritePermissionLevel? organizationHooks, @@ -59,6 +62,7 @@ namespace Octokit Pages = pages; PullRequests = pullRequests; RepositoryAnnouncementBanners = repositoryAnnouncementBanners; + RepositoryCustomProperties = repositoryCustomProperties; RepositoryHooks = repositoryHooks; RepositoryProjects = repositoryProjects; SecretScanningAlerts = secretScanningAlerts; @@ -70,6 +74,8 @@ namespace Octokit Workflows = workflows; Members = members; OrganizationAdministration = organizationAdministration; + OrganizationCopilotSeatManagement = organizationCopilotSeatManagement; + OrganizationCustomProperties = organizationCustomProperties; OrganizationCustomRoles = organizationCustomRoles; OrganizationAnnouncementBanners = organizationAnnouncementBanners; OrganizationHooks = organizationHooks; @@ -142,6 +148,11 @@ namespace Octokit /// public StringEnum? RepositoryAnnouncementBanners { get; private set; } + /// + /// The level of permission to grant the access token to view and set values for a repository's custom properties, when allowed by the property. + /// + public StringEnum? RepositoryCustomProperties { get; private set; } + /// /// The level of permission to grant the access token to manage the post-receive hooks for a repository. /// @@ -197,6 +208,16 @@ namespace Octokit /// public StringEnum? OrganizationAdministration { get; private set; } + /// + /// The level of permission to grant the access token to manage access Copilot Business seats and settings. + /// + public StringEnum? OrganizationCopilotSeatManagement { get; private set; } + + /// + /// The level of permission to grant the access token to view custom properties, write repository values, and administer definitions. + /// + public StringEnum? OrganizationCustomProperties { get; private set; } + /// /// The level of permission to grant the access token for custom roles management. This property is in beta and is subject to change. ///