From a6dbb890742bb780675564ae05f9e91fff52ece1 Mon Sep 17 00:00:00 2001 From: Jonas van Vliet Date: Tue, 21 Feb 2023 12:43:09 +0100 Subject: [PATCH] feat(deploy key): Added additional fields to deploykey object feat(personal SSH key): Added method to allow adding/deleting public keys on a user Added test cases to cover all new functionality. --- pom.xml | 6 + .../java/org/kohsuke/github/GHDeployKey.java | 58 ++++++- src/main/java/org/kohsuke/github/GHKey.java | 12 ++ .../java/org/kohsuke/github/GHMyself.java | 22 +++ .../java/org/kohsuke/github/ArchTests.java | 1 + .../org/kohsuke/github/GHDeployKeyTest.java | 81 ++++++++++ .../org/kohsuke/github/GHPublicKeyTest.java | 33 ++++ ...epos_hub4j-test-org_ghdeploykeytest-2.json | 149 ++++++++++++++++++ ...hub4j-test-org_ghdeploykeytest_keys-3.json | 24 +++ .../testGetDeployKeys/__files/user-1.json | 46 ++++++ ...epos_hub4j-test-org_ghdeploykeytest-2.json | 51 ++++++ ...hub4j-test-org_ghdeploykeytest_keys-3.json | 50 ++++++ .../testGetDeployKeys/mappings/user-1.json | 51 ++++++ .../testAddPublicKey/__files/user-1.json | 46 ++++++ .../testAddPublicKey/__files/user_keys-2.json | 9 ++ .../testAddPublicKey/mappings/user-1.json | 49 ++++++ .../mappings/user_keys-2.json | 56 +++++++ .../mappings/user_keys_77080429-3.json | 41 +++++ 18 files changed, 784 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/kohsuke/github/GHDeployKeyTest.java create mode 100644 src/test/java/org/kohsuke/github/GHPublicKeyTest.java create mode 100644 src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest-2.json create mode 100644 src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest_keys-3.json create mode 100644 src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/user-1.json create mode 100644 src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest-2.json create mode 100644 src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest_keys-3.json create mode 100644 src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/user-1.json create mode 100644 src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user-1.json create mode 100644 src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user_keys-2.json create mode 100644 src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user-1.json create mode 100644 src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys-2.json create mode 100644 src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys_77080429-3.json diff --git a/pom.xml b/pom.xml index 3230acc6fb..65724a04fc 100644 --- a/pom.xml +++ b/pom.xml @@ -453,6 +453,12 @@ ${hamcrest.version} test + + com.github.npathai + hamcrest-optional + 2.0.0 + test + junit junit diff --git a/src/main/java/org/kohsuke/github/GHDeployKey.java b/src/main/java/org/kohsuke/github/GHDeployKey.java index e49579ee03..2af3b9d7ee 100644 --- a/src/main/java/org/kohsuke/github/GHDeployKey.java +++ b/src/main/java/org/kohsuke/github/GHDeployKey.java @@ -3,6 +3,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder; import java.io.IOException; +import java.util.Date; // TODO: Auto-generated Javadoc /** @@ -20,6 +21,18 @@ public class GHDeployKey { protected long id; private GHRepository owner; + /** Creation date of the deploy key */ + private String created_at; + + /** Last used date of the deploy key */ + private String last_used; + + /** Name of user that added the deploy key */ + private String added_by; + + /** Whether the deploykey has readonly permission or full access */ + private boolean read_only; + /** * Gets id. * @@ -65,6 +78,42 @@ public boolean isVerified() { return verified; } + /** + * Gets created_at. + * + * @return the created_at + */ + public Date getCreatedAt() { + return GitHubClient.parseDate(created_at); + } + + /** + * Gets last_used. + * + * @return the last_used + */ + public Date getLastUsedAt() { + return GitHubClient.parseDate(last_used); + } + + /** + * Gets added_by + * + * @return the added_by + */ + public String getAdded_by() { + return added_by; + } + + /** + * Is read_only + * + * @return true if the key can only read. False if the key has write permission as well. + */ + public boolean isRead_only() { + return read_only; + } + /** * Wrap gh deploy key. * @@ -95,7 +144,14 @@ GHDeployKey lateBind(GHRepository repo) { * @return the string */ public String toString() { - return new ToStringBuilder(this).append("title", title).append("id", id).append("key", key).toString(); + return new ToStringBuilder(this).append("title", title) + .append("id", id) + .append("key", key) + .append("created_at", created_at) + .append("last_used", last_used) + .append("added_by", added_by) + .append("read_only", read_only) + .toString(); } /** diff --git a/src/main/java/org/kohsuke/github/GHKey.java b/src/main/java/org/kohsuke/github/GHKey.java index a60717e661..01c73819b2 100644 --- a/src/main/java/org/kohsuke/github/GHKey.java +++ b/src/main/java/org/kohsuke/github/GHKey.java @@ -3,6 +3,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.builder.ToStringBuilder; +import java.io.IOException; + // TODO: Auto-generated Javadoc /** * SSH public key. @@ -74,4 +76,14 @@ public boolean isVerified() { public String toString() { return new ToStringBuilder(this).append("title", title).append("id", id).append("key", key).toString(); } + + /** + * Delete the GHKey + * + * @throws IOException + * the io exception + */ + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(String.format("/user/keys/%d", id)).send(); + } } diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index ea3dd5f3d7..43914f2bd2 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -83,6 +83,28 @@ public List getPublicKeys() throws IOException { return root().createRequest().withUrlPath("/user/keys").toIterable(GHKey[].class, null).toList(); } + /** + * Add public SSH key for the user. + *

+ * https://docs.github.com/en/rest/users/keys?apiVersion=2022-11-28#create-a-public-ssh-key-for-the-authenticated-user + * + * @param title + * Title of the SSH key + * @param key + * the public key + * @return the newly created Github key + * @throws IOException + * the io exception + */ + public GHKey addPublicKey(String title, String key) throws IOException { + return root().createRequest() + .withUrlPath("/user/keys") + .method("POST") + .with("title", title) + .with("key", key) + .fetch(GHKey.class); + } + /** * Returns the read-only list of all the public verified keys of the current user. *

diff --git a/src/test/java/org/kohsuke/github/ArchTests.java b/src/test/java/org/kohsuke/github/ArchTests.java index 598b6383d4..72a6b9c267 100644 --- a/src/test/java/org/kohsuke/github/ArchTests.java +++ b/src/test/java/org/kohsuke/github/ArchTests.java @@ -128,6 +128,7 @@ public void testRequireUseOfOnlySpecificApacheCommons() { targetMethodIs(ToStringBuilder.class, "append", String.class, Object.class), targetMethodIs(ToStringBuilder.class, "append", String.class, long.class), targetMethodIs(ToStringBuilder.class, "append", String.class, int.class), + targetMethodIs(ToStringBuilder.class, "append", String.class, boolean.class), targetMethodIs(ToStringBuilder.class, "isEmpty"), targetMethodIs(ToStringBuilder.class, "equals"), targetMethodIs(ToStringBuilder.class, "capitalize"), diff --git a/src/test/java/org/kohsuke/github/GHDeployKeyTest.java b/src/test/java/org/kohsuke/github/GHDeployKeyTest.java new file mode 100644 index 0000000000..35d321888c --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHDeployKeyTest.java @@ -0,0 +1,81 @@ +package org.kohsuke.github; + +import org.junit.Test; + +import java.io.IOException; +import java.time.Instant; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import static com.github.npathai.hamcrestopt.OptionalMatchers.isPresent; +import static org.hamcrest.Matchers.*; + +/** + * The Class GHDeployKeyTest. + * + * @author Jonas van Vliet + */ +public class GHDeployKeyTest extends AbstractGitHubWireMockTest { + private static final String DEPLOY_KEY_TEST_REPO_NAME = "hub4j-test-org/GHDeployKeyTest"; + private static final String ED_25519_READONLY = "DeployKey - ed25519 - readonly"; + private static final String RSA_4096_READWRITE = "Deploykey - rsa4096 - readwrite"; + private static final String KEY_CREATOR_USERNAME = "van-vliet"; + + /** + * Test get deploymentkeys. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testGetDeployKeys() throws IOException { + final GHRepository repo = getRepository(); + final List deployKeys = repo.getDeployKeys(); + assertThat("There should be 2 deploykeys in " + DEPLOY_KEY_TEST_REPO_NAME, deployKeys, hasSize(2)); + + Optional ed25519Key = deployKeys.stream() + .filter(key -> key.getTitle().equals(ED_25519_READONLY)) + .findAny(); + assertThat("The key exists", ed25519Key, isPresent()); + assertThat("The key was created at the specified date", + ed25519Key.get().getCreatedAt(), + is(Date.from(Instant.parse("2023-02-08T10:00:15.00Z")))); + assertThat("The key is created by " + KEY_CREATOR_USERNAME, + ed25519Key.get().getAdded_by(), + is(KEY_CREATOR_USERNAME)); + assertThat("The key has a last_used value", + ed25519Key.get().getLastUsedAt(), + is(Date.from(Instant.parse("2023-02-08T10:02:11.00Z")))); + assertThat("The key only has read access", ed25519Key.get().isRead_only(), is(true)); + assertThat("Object has a toString()", ed25519Key.get().toString(), is(notNullValue())); + + Optional rsa_4096Key = deployKeys.stream() + .filter(key -> key.getTitle().equals(RSA_4096_READWRITE)) + .findAny(); + assertThat("The key exists", rsa_4096Key, isPresent()); + assertThat("The key was created at the specified date", + rsa_4096Key.get().getCreatedAt(), + is(Date.from(Instant.parse("2023-01-26T14:12:12.00Z")))); + assertThat("The key is created by " + KEY_CREATOR_USERNAME, + rsa_4096Key.get().getAdded_by(), + is(KEY_CREATOR_USERNAME)); + assertThat("The key has never been used", rsa_4096Key.get().getLastUsedAt(), is(nullValue())); + assertThat("The key only has read/write access", rsa_4096Key.get().isRead_only(), is(false)); + } + + /** + * Gets the repository. + * + * @return the repository + * @throws IOException + * Signals that an I/O exception has occurred. + */ + protected GHRepository getRepository() throws IOException { + return getRepository(gitHub); + } + + private GHRepository getRepository(final GitHub gitHub) throws IOException { + return gitHub.getRepository(DEPLOY_KEY_TEST_REPO_NAME); + } +} diff --git a/src/test/java/org/kohsuke/github/GHPublicKeyTest.java b/src/test/java/org/kohsuke/github/GHPublicKeyTest.java new file mode 100644 index 0000000000..4bd505b168 --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHPublicKeyTest.java @@ -0,0 +1,33 @@ +package org.kohsuke.github; + +import org.junit.Test; + +/** + * The Class GHPublicKeyTest. + * + * @author Jonas van Vliet + */ +public class GHPublicKeyTest extends AbstractGitHubWireMockTest { + + private static final String TMP_KEY_NAME = "Temporary user key"; + private static final String WIREMOCK_SSH_PUBLIC_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDepW2/BSVFM2AfuGGsvi+vjQzC0EBD3R+/7PNEvP0/nvTWxiC/tthfvvCJR6TKrsprCir5tiJFm73gX+K18W0RKYpkyg8H6d1eZu3q/JOiGvoDPeN8Oe9hOGeeexw1WOiz7ESPHzZYXI981evzHAzxxn8zibr2EryopVNsXyoenw=="; + + /** + * Test adding a public key to the user + * + * @throws Exception + * the exception + */ + @Test + public void testAddPublicKey() throws Exception { + GHKey newPublicKey = null; + try { + GHMyself me = gitHub.getMyself(); + newPublicKey = me.addPublicKey(TMP_KEY_NAME, WIREMOCK_SSH_PUBLIC_KEY); + } finally { + if (newPublicKey != null) { + newPublicKey.delete(); + } + } + } +} diff --git a/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest-2.json b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest-2.json new file mode 100644 index 0000000000..cb09c0dd19 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest-2.json @@ -0,0 +1,149 @@ +{ + "id": 593636170, + "node_id": "R_kgDOI2IrSg", + "name": "GHDeployKeyTest", + "full_name": "hub4j-test-org/GHDeployKeyTest", + "private": false, + "owner": { + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j-test-org", + "html_url": "https://github.com/hub4j-test-org", + "followers_url": "https://api.github.com/users/hub4j-test-org/followers", + "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", + "repos_url": "https://api.github.com/users/hub4j-test-org/repos", + "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/hub4j-test-org/GHDeployKeyTest", + "description": "Repository used by GHDeployKeyTest", + "fork": false, + "url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest", + "forks_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/forks", + "keys_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/teams", + "hooks_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/hooks", + "issue_events_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/issues/events{/number}", + "events_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/events", + "assignees_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/assignees{/user}", + "branches_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/branches{/branch}", + "tags_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/tags", + "blobs_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/statuses/{sha}", + "languages_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/languages", + "stargazers_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/stargazers", + "contributors_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/contributors", + "subscribers_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/subscribers", + "subscription_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/subscription", + "commits_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/contents/{+path}", + "compare_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/merges", + "archive_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/downloads", + "issues_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/issues{/number}", + "pulls_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/pulls{/number}", + "milestones_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/milestones{/number}", + "notifications_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/labels{/name}", + "releases_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/releases{/id}", + "deployments_url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/deployments", + "created_at": "2023-01-26T13:58:23Z", + "updated_at": "2023-01-26T13:58:23Z", + "pushed_at": "2023-01-26T13:58:25Z", + "git_url": "git://github.com/hub4j-test-org/GHDeployKeyTest.git", + "ssh_url": "git@github.com:hub4j-test-org/GHDeployKeyTest.git", + "clone_url": "https://github.com/hub4j-test-org/GHDeployKeyTest.git", + "svn_url": "https://github.com/hub4j-test-org/GHDeployKeyTest", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "main", + "permissions": { + "admin": true, + "maintain": true, + "push": true, + "triage": true, + "pull": true + }, + "temp_clone_token": "", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE", + "organization": { + "login": "hub4j-test-org", + "id": 7544739, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", + "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/hub4j-test-org", + "html_url": "https://github.com/hub4j-test-org", + "followers_url": "https://api.github.com/users/hub4j-test-org/followers", + "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", + "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", + "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", + "repos_url": "https://api.github.com/users/hub4j-test-org/repos", + "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", + "type": "Organization", + "site_admin": false + }, + "security_and_analysis": { + "secret_scanning": { + "status": "disabled" + }, + "secret_scanning_push_protection": { + "status": "disabled" + } + }, + "network_count": 0, + "subscribers_count": 16 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest_keys-3.json b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest_keys-3.json new file mode 100644 index 0000000000..95120e92c0 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/repos_hub4j-test-org_ghdeploykeytest_keys-3.json @@ -0,0 +1,24 @@ +[ + { + "id": 76924278, + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBO4AyE/CjnMt0YeJ4QFnU87qr4u534Q5FHRZmTUP7Ixi/ks6iMVJAU71GltuP1NIUynOTTA+Y+XNHfCp+/wNCi6B6o63Ouk2Debx7cf3ufFXM7G48iTG3ULK2qfPzm8OkfRP4urg+AmdrQAUuH3Wx3CinqlGt8phJECsRkQqdoYoikOrRtx9iNx0Cz45xD4JyRBOjZix0kZTqQy8LKnpxXA8nIzJJoh9eYTOPT3Pf3X3qeOUpN2QTSH7ya9xvE+lCxEMqP6m/vnA1tm5Vzso53bU/pG/SZwNESpafD9Dkry8AiCg9zfzFnzikwWHhrPRqCjIwYuMdaXbBtQBknPx62nDkpS/b0iFvdIoRmWTNbTng38urH5lFRLE7y13WW1GWYPeiSF3zY6B0B+rdNJm2RNrZtvtbQ0e3ruWVR8ZIVtQysT0/ueGO0g2pmodY0lB2Z6EidOx4F46i8mitUgABwhnlrzfki/nO/K0voIUh48D5M8tJsR7kCj+G0e1zXoTl7OF7/g8br8zYlSDczIZBgjORT+XBOr5My6cbSFYRratR2cy1ZB7XpcolCp89mPY3MTQOTOrNIE4BhoJHS6ws7rIv/ZNQeW+4lktPq0x59Tdcv5vgYAdAiu3qpjTcaVxxkAVE8AxNz237+CRs4+jWCsGHl2BAHCEtM9KVqLR77w==", + "url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/keys/76924278", + "title": "Deploykey - rsa4096 - readwrite", + "verified": true, + "created_at": "2023-01-26T14:12:12Z", + "read_only": false, + "last_used": null, + "added_by": "van-vliet" + }, + { + "id": 77542797, + "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIINaSsehgTpibnTTtH4kKohPhwfzqo0OvfwP4w8qZfPp", + "url": "https://api.github.com/repos/hub4j-test-org/GHDeployKeyTest/keys/77542797", + "title": "DeployKey - ed25519 - readonly", + "verified": true, + "created_at": "2023-02-08T10:00:15Z", + "read_only": true, + "last_used": "2023-02-08T10:02:11Z", + "added_by": "van-vliet" + } +] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/user-1.json b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/user-1.json new file mode 100644 index 0000000000..c47cc37804 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/__files/user-1.json @@ -0,0 +1,46 @@ +{ + "login": "van-vliet", + "id": 11989400, + "node_id": "MDQ6VXNlcjExOTg5NDAw", + "avatar_url": "https://avatars.githubusercontent.com/u/11989400?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/van-vliet", + "html_url": "https://github.com/van-vliet", + "followers_url": "https://api.github.com/users/van-vliet/followers", + "following_url": "https://api.github.com/users/van-vliet/following{/other_user}", + "gists_url": "https://api.github.com/users/van-vliet/gists{/gist_id}", + "starred_url": "https://api.github.com/users/van-vliet/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/van-vliet/subscriptions", + "organizations_url": "https://api.github.com/users/van-vliet/orgs", + "repos_url": "https://api.github.com/users/van-vliet/repos", + "events_url": "https://api.github.com/users/van-vliet/events{/privacy}", + "received_events_url": "https://api.github.com/users/van-vliet/received_events", + "type": "User", + "site_admin": false, + "name": "Jonas van Vliet", + "company": null, + "blog": "", + "location": null, + "email": null, + "hireable": null, + "bio": null, + "twitter_username": null, + "public_repos": 1, + "public_gists": 0, + "followers": 1, + "following": 1, + "created_at": "2015-04-17T05:56:56Z", + "updated_at": "2022-11-04T06:44:42Z", + "private_gists": 0, + "total_private_repos": 0, + "owned_private_repos": 0, + "disk_usage": 0, + "collaborators": 0, + "two_factor_authentication": true, + "plan": { + "name": "free", + "space": 976562499, + "collaborators": 0, + "private_repos": 10000 + } +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest-2.json b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest-2.json new file mode 100644 index 0000000000..a3a920349a --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest-2.json @@ -0,0 +1,51 @@ +{ + "id": "86196b46-7963-4ade-8331-f6b8677ebb56", + "name": "repos_hub4j-test-org_ghdeploykeytest", + "request": { + "url": "/repos/hub4j-test-org/GHDeployKeyTest", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "repos_hub4j-test-org_ghdeploykeytest-2.json", + "headers": { + "Server": "GitHub.com", + "Date": "Wed, 08 Feb 2023 10:16:06 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": [ + "Accept, Authorization, Cookie, X-GitHub-OTP", + "Accept-Encoding, Accept, X-Requested-With" + ], + "ETag": "W/\"ccb5e13d45de3c0541c6be0f53bb4bffb08cf1dcb916a2eeb417a2d162181d25\"", + "Last-Modified": "Thu, 26 Jan 2023 13:58:23 GMT", + "X-OAuth-Scopes": "read:user, repo", + "X-Accepted-OAuth-Scopes": "repo", + "github-authentication-token-expiration": "2023-02-15 10:03:43 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4983", + "X-RateLimit-Reset": "1675854466", + "X-RateLimit-Used": "17", + "X-RateLimit-Resource": "core", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "E1B8:4352:46E1A3:481D53:63E37666" + } + }, + "uuid": "86196b46-7963-4ade-8331-f6b8677ebb56", + "persistent": true, + "insertionIndex": 2 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest_keys-3.json b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest_keys-3.json new file mode 100644 index 0000000000..6854466d66 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/repos_hub4j-test-org_ghdeploykeytest_keys-3.json @@ -0,0 +1,50 @@ +{ + "id": "49bb1666-7758-49de-9134-f0735a9a235d", + "name": "repos_hub4j-test-org_ghdeploykeytest_keys", + "request": { + "url": "/repos/hub4j-test-org/GHDeployKeyTest/keys", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "repos_hub4j-test-org_ghdeploykeytest_keys-3.json", + "headers": { + "Server": "GitHub.com", + "Date": "Wed, 08 Feb 2023 10:16:07 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": [ + "Accept, Authorization, Cookie, X-GitHub-OTP", + "Accept-Encoding, Accept, X-Requested-With" + ], + "ETag": "W/\"9bc942dbeacfdba2d3174c5da85d7e37a3d600068bea67c0e8e789201c7a9c90\"", + "X-OAuth-Scopes": "read:user, repo", + "X-Accepted-OAuth-Scopes": "", + "github-authentication-token-expiration": "2023-02-15 10:03:43 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4982", + "X-RateLimit-Reset": "1675854466", + "X-RateLimit-Used": "18", + "X-RateLimit-Resource": "core", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "E1B9:672E:49A60B:4AE64E:63E37667" + } + }, + "uuid": "49bb1666-7758-49de-9134-f0735a9a235d", + "persistent": true, + "insertionIndex": 3 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/user-1.json b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/user-1.json new file mode 100644 index 0000000000..fb3aea41e6 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHDeployKeyTest/wiremock/testGetDeployKeys/mappings/user-1.json @@ -0,0 +1,51 @@ +{ + "id": "ffe193ff-1772-4bdb-a87d-f09d73a55e9c", + "name": "user", + "request": { + "url": "/user", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "user-1.json", + "headers": { + "Server": "GitHub.com", + "Date": "Wed, 08 Feb 2023 10:16:06 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": [ + "Accept, Authorization, Cookie, X-GitHub-OTP", + "Accept-Encoding, Accept, X-Requested-With" + ], + "ETag": "W/\"d886bab2c0d06ed3ad08a6e1296c04c22f9a975d735ded6a05ba24cf69cee315\"", + "Last-Modified": "Fri, 04 Nov 2022 06:44:42 GMT", + "X-OAuth-Scopes": "read:user, repo", + "X-Accepted-OAuth-Scopes": "", + "github-authentication-token-expiration": "2023-02-15 10:03:43 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4985", + "X-RateLimit-Reset": "1675854466", + "X-RateLimit-Used": "15", + "X-RateLimit-Resource": "core", + "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "Access-Control-Allow-Origin": "*", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "E1B6:4092:490FCD:4A4F75:63E37665" + } + }, + "uuid": "ffe193ff-1772-4bdb-a87d-f09d73a55e9c", + "persistent": true, + "insertionIndex": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user-1.json b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user-1.json new file mode 100644 index 0000000000..3e646ff910 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user-1.json @@ -0,0 +1,46 @@ +{ + "login": "jvv-test-2", + "id": 123935167, + "node_id": "U_kgDOB2MZvw", + "avatar_url": "https://avatars.githubusercontent.com/u/123935167?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jvv-test-2", + "html_url": "https://github.com/jvv-test-2", + "followers_url": "https://api.github.com/users/jvv-test-2/followers", + "following_url": "https://api.github.com/users/jvv-test-2/following{/other_user}", + "gists_url": "https://api.github.com/users/jvv-test-2/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jvv-test-2/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jvv-test-2/subscriptions", + "organizations_url": "https://api.github.com/users/jvv-test-2/orgs", + "repos_url": "https://api.github.com/users/jvv-test-2/repos", + "events_url": "https://api.github.com/users/jvv-test-2/events{/privacy}", + "received_events_url": "https://api.github.com/users/jvv-test-2/received_events", + "type": "User", + "site_admin": false, + "name": null, + "company": null, + "blog": "", + "location": null, + "email": null, + "hireable": null, + "bio": null, + "twitter_username": null, + "public_repos": 0, + "public_gists": 0, + "followers": 0, + "following": 0, + "created_at": "2023-01-30T08:21:43Z", + "updated_at": "2023-01-30T08:21:43Z", + "private_gists": 0, + "total_private_repos": 0, + "owned_private_repos": 0, + "disk_usage": 0, + "collaborators": 0, + "two_factor_authentication": false, + "plan": { + "name": "free", + "space": 976562499, + "collaborators": 0, + "private_repos": 10000 + } +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user_keys-2.json b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user_keys-2.json new file mode 100644 index 0000000000..e9656f3793 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/__files/user_keys-2.json @@ -0,0 +1,9 @@ +{ + "id": 77080429, + "key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDepW2/BSVFM2AfuGGsvi+vjQzC0EBD3R+/7PNEvP0/nvTWxiC/tthfvvCJR6TKrsprCir5tiJFm73gX+K18W0RKYpkyg8H6d1eZu3q/JOiGvoDPeN8Oe9hOGeeexw1WOiz7ESPHzZYXI981evzHAzxxn8zibr2EryopVNsXyoenw==", + "url": "https://api.github.com/user/keys/77080429", + "title": "Temporary user key", + "verified": true, + "created_at": "2023-01-30T09:31:56Z", + "read_only": false +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user-1.json b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user-1.json new file mode 100644 index 0000000000..e79a4076e7 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user-1.json @@ -0,0 +1,49 @@ +{ + "id": "67a88087-3119-4e65-8d1e-b642d1e59c4a", + "name": "user", + "request": { + "url": "/user", + "method": "GET", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 200, + "bodyFileName": "user-1.json", + "headers": { + "Server": "GitHub.com", + "Date": "Mon, 30 Jan 2023 09:31:55 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": [ + "Accept, Authorization, Cookie, X-GitHub-OTP", + "Accept-Encoding, Accept, X-Requested-With" + ], + "ETag": "W/\"f9a4696e8778e5018e61274cef95759771cfa9dee3c39b931513a562cf779e80\"", + "Last-Modified": "Mon, 30 Jan 2023 08:21:43 GMT", + "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, delete:packages, delete_repo, gist, notifications, project, repo, user, workflow, write:discussion, write:packages", + "X-Accepted-OAuth-Scopes": "", + "github-authentication-token-expiration": "2023-03-01 08:23:08 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4999", + "X-RateLimit-Reset": "1675074715", + "X-RateLimit-Used": "1", + "X-RateLimit-Resource": "core", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "CAB6:8706:A7B3FF:AAB6FC:63D78E8B" + } + }, + "uuid": "67a88087-3119-4e65-8d1e-b642d1e59c4a", + "persistent": true, + "insertionIndex": 1 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys-2.json b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys-2.json new file mode 100644 index 0000000000..4ef079a7f3 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys-2.json @@ -0,0 +1,56 @@ +{ + "id": "2a67008e-cf5e-4b4c-894a-878f6c718a05", + "name": "user_keys", + "request": { + "url": "/user/keys", + "method": "POST", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + }, + "bodyPatterns": [ + { + "equalToJson": "{\"title\":\"Temporary user key\",\"key\":\"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDepW2/BSVFM2AfuGGsvi+vjQzC0EBD3R+/7PNEvP0/nvTWxiC/tthfvvCJR6TKrsprCir5tiJFm73gX+K18W0RKYpkyg8H6d1eZu3q/JOiGvoDPeN8Oe9hOGeeexw1WOiz7ESPHzZYXI981evzHAzxxn8zibr2EryopVNsXyoenw==\"}", + "ignoreArrayOrder": true, + "ignoreExtraElements": false + } + ] + }, + "response": { + "status": 201, + "bodyFileName": "user_keys-2.json", + "headers": { + "Server": "GitHub.com", + "Date": "Mon, 30 Jan 2023 09:31:56 GMT", + "Content-Type": "application/json; charset=utf-8", + "Cache-Control": "private, max-age=60, s-maxage=60", + "Vary": [ + "Accept, Authorization, Cookie, X-GitHub-OTP", + "Accept-Encoding, Accept, X-Requested-With" + ], + "ETag": "\"6510ce8437cc68cf299fe8f5209abc961b86e6b4d35dfa4ae626ce43b32b2580\"", + "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, delete:packages, delete_repo, gist, notifications, project, repo, user, workflow, write:discussion, write:packages", + "X-Accepted-OAuth-Scopes": "admin:public_key, write:public_key", + "github-authentication-token-expiration": "2023-03-01 08:23:08 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4997", + "X-RateLimit-Reset": "1675074715", + "X-RateLimit-Used": "3", + "X-RateLimit-Resource": "core", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "X-GitHub-Request-Id": "CAB8:5F74:B9E56B:BCE687:63D78E8B", + "Location": "https://api.github.com/user/keys/77080429" + } + }, + "uuid": "2a67008e-cf5e-4b4c-894a-878f6c718a05", + "persistent": true, + "insertionIndex": 2 +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys_77080429-3.json b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys_77080429-3.json new file mode 100644 index 0000000000..2ea399ed41 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHPublicKeyTest/wiremock/testAddPublicKey/mappings/user_keys_77080429-3.json @@ -0,0 +1,41 @@ +{ + "id": "d91a5200-ed4b-4145-be9f-fece79f6f92d", + "name": "user_keys_77080429", + "request": { + "url": "/user/keys/77080429", + "method": "DELETE", + "headers": { + "Accept": { + "equalTo": "application/vnd.github.v3+json" + } + } + }, + "response": { + "status": 204, + "headers": { + "Server": "GitHub.com", + "Date": "Mon, 30 Jan 2023 09:31:56 GMT", + "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, delete:packages, delete_repo, gist, notifications, project, repo, user, workflow, write:discussion, write:packages", + "X-Accepted-OAuth-Scopes": "admin:public_key", + "github-authentication-token-expiration": "2023-03-01 08:23:08 UTC", + "X-GitHub-Media-Type": "github.v3; format=json", + "x-github-api-version-selected": "2022-11-28", + "X-RateLimit-Limit": "5000", + "X-RateLimit-Remaining": "4996", + "X-RateLimit-Reset": "1675074715", + "X-RateLimit-Used": "4", + "X-RateLimit-Resource": "core", + "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", + "X-Frame-Options": "deny", + "X-Content-Type-Options": "nosniff", + "X-XSS-Protection": "0", + "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "Content-Security-Policy": "default-src 'none'", + "Vary": "Accept-Encoding, Accept, X-Requested-With", + "X-GitHub-Request-Id": "CAB9:B29F:A4B977:A7B346:63D78E8C" + } + }, + "uuid": "d91a5200-ed4b-4145-be9f-fece79f6f92d", + "persistent": true, + "insertionIndex": 3 +} \ No newline at end of file