Skip to content

Commit

Permalink
Merge pull request #1616 from van-vliet/feature/improve-deploy-key-fu…
Browse files Browse the repository at this point in the history
…nctionality

Improve deploy key and  user key handling
  • Loading branch information
bitwiseman committed Feb 26, 2023
2 parents f48169f + 4f1dba4 commit 1dcedba
Show file tree
Hide file tree
Showing 18 changed files with 784 additions and 1 deletion.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,12 @@
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.npathai</groupId>
<artifactId>hamcrest-optional</artifactId>
<version>2.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
58 changes: 57 additions & 1 deletion src/main/java/org/kohsuke/github/GHDeployKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.apache.commons.lang3.builder.ToStringBuilder;

import java.io.IOException;
import java.util.Date;

// TODO: Auto-generated Javadoc
/**
Expand All @@ -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.
*
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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();
}

/**
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/kohsuke/github/GHKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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();
}
}
22 changes: 22 additions & 0 deletions src/main/java/org/kohsuke/github/GHMyself.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,28 @@ public List<GHKey> getPublicKeys() throws IOException {
return root().createRequest().withUrlPath("/user/keys").toIterable(GHKey[].class, null).toList();
}

/**
* Add public SSH key for the user.
* <p>
* 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.
* <p>
Expand Down
1 change: 1 addition & 0 deletions src/test/java/org/kohsuke/github/ArchTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
81 changes: 81 additions & 0 deletions src/test/java/org/kohsuke/github/GHDeployKeyTest.java
Original file line number Diff line number Diff line change
@@ -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<GHDeployKey> deployKeys = repo.getDeployKeys();
assertThat("There should be 2 deploykeys in " + DEPLOY_KEY_TEST_REPO_NAME, deployKeys, hasSize(2));

Optional<GHDeployKey> 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<GHDeployKey> 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);
}
}
33 changes: 33 additions & 0 deletions src/test/java/org/kohsuke/github/GHPublicKeyTest.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
}
Loading

0 comments on commit 1dcedba

Please sign in to comment.