diff --git a/src/main/java/rs/iggy/clients/blocking/IggyClient.java b/src/main/java/rs/iggy/clients/blocking/IggyClient.java index 8844b4c..e1ea4c2 100644 --- a/src/main/java/rs/iggy/clients/blocking/IggyClient.java +++ b/src/main/java/rs/iggy/clients/blocking/IggyClient.java @@ -18,4 +18,6 @@ public interface IggyClient { MessagesClient messages(); + PersonalAccessTokensClient personalAccessTokens(); + } diff --git a/src/main/java/rs/iggy/clients/blocking/PersonalAccessTokensClient.java b/src/main/java/rs/iggy/clients/blocking/PersonalAccessTokensClient.java new file mode 100644 index 0000000..bcca66c --- /dev/null +++ b/src/main/java/rs/iggy/clients/blocking/PersonalAccessTokensClient.java @@ -0,0 +1,19 @@ +package rs.iggy.clients.blocking; + +import rs.iggy.personalaccesstoken.PersonalAccessTokenInfo; +import rs.iggy.personalaccesstoken.RawPersonalAccessToken; +import rs.iggy.user.IdentityInfo; +import java.math.BigInteger; +import java.util.List; + +public interface PersonalAccessTokensClient { + + RawPersonalAccessToken createPersonalAccessToken(String name, BigInteger expiry); + + List getPersonalAccessTokens(); + + void deletePersonalAccessToken(String name); + + IdentityInfo loginWithPersonalAccessToken(String token); + +} diff --git a/src/main/java/rs/iggy/clients/blocking/http/IggyHttpClient.java b/src/main/java/rs/iggy/clients/blocking/http/IggyHttpClient.java index d6f9da2..b0d3fd9 100644 --- a/src/main/java/rs/iggy/clients/blocking/http/IggyHttpClient.java +++ b/src/main/java/rs/iggy/clients/blocking/http/IggyHttpClient.java @@ -12,6 +12,7 @@ public class IggyHttpClient implements IggyClient { private final ConsumerGroupsHttpClient consumerGroupsClient; private final ConsumerOffsetsHttpClient consumerOffsetsClient; private final MessagesHttpClient messagesClient; + private final PersonalAccessTokensHttpClient personalAccessTokensHttpClient; public IggyHttpClient(String url) { HttpClient httpClient = new HttpClient(url); @@ -23,6 +24,7 @@ public IggyHttpClient(String url) { consumerGroupsClient = new ConsumerGroupsHttpClient(httpClient); consumerOffsetsClient = new ConsumerOffsetsHttpClient(httpClient); messagesClient = new MessagesHttpClient(httpClient); + personalAccessTokensHttpClient = new PersonalAccessTokensHttpClient(httpClient); } @Override @@ -65,4 +67,9 @@ public MessagesClient messages() { return messagesClient; } + @Override + public PersonalAccessTokensClient personalAccessTokens() { + return personalAccessTokensHttpClient; + } + } diff --git a/src/main/java/rs/iggy/clients/blocking/http/PersonalAccessTokensHttpClient.java b/src/main/java/rs/iggy/clients/blocking/http/PersonalAccessTokensHttpClient.java new file mode 100644 index 0000000..a899e77 --- /dev/null +++ b/src/main/java/rs/iggy/clients/blocking/http/PersonalAccessTokensHttpClient.java @@ -0,0 +1,57 @@ +package rs.iggy.clients.blocking.http; + +import com.fasterxml.jackson.core.type.TypeReference; +import rs.iggy.clients.blocking.PersonalAccessTokensClient; +import rs.iggy.personalaccesstoken.PersonalAccessTokenInfo; +import rs.iggy.personalaccesstoken.RawPersonalAccessToken; +import rs.iggy.user.IdentityInfo; +import rs.iggy.user.TokenInfo; +import java.math.BigInteger; +import java.util.List; + +class PersonalAccessTokensHttpClient implements PersonalAccessTokensClient { + + private static final String PERSONAL_ACCESS_TOKENS = "/personal-access-tokens"; + private final HttpClient httpClient; + + public PersonalAccessTokensHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + @Override + public RawPersonalAccessToken createPersonalAccessToken(String name, BigInteger expiry) { + var request = httpClient.preparePostRequest(PERSONAL_ACCESS_TOKENS, + new CreatePersonalAccessToken(name, expiry)); + return httpClient.execute(request, new TypeReference<>() { + }); + } + + @Override + public List getPersonalAccessTokens() { + var request = httpClient.prepareGetRequest(PERSONAL_ACCESS_TOKENS); + return httpClient.execute(request, new TypeReference<>() { + }); + } + + @Override + public void deletePersonalAccessToken(String name) { + var request = httpClient.prepareDeleteRequest(PERSONAL_ACCESS_TOKENS + "/" + name); + httpClient.execute(request); + } + + @Override + public IdentityInfo loginWithPersonalAccessToken(String token) { + var request = httpClient.preparePostRequest(PERSONAL_ACCESS_TOKENS + "/login", + new LoginWithPersonalAccessToken(token)); + var response = httpClient.execute(request, IdentityInfo.class); + httpClient.setToken(response.accessToken().map(TokenInfo::token)); + return response; + } + + record CreatePersonalAccessToken(String name, BigInteger expiry) { + } + + record LoginWithPersonalAccessToken(String token) { + } + +} diff --git a/src/main/java/rs/iggy/clients/blocking/tcp/IggyTcpClient.java b/src/main/java/rs/iggy/clients/blocking/tcp/IggyTcpClient.java index a82a931..ba1f968 100644 --- a/src/main/java/rs/iggy/clients/blocking/tcp/IggyTcpClient.java +++ b/src/main/java/rs/iggy/clients/blocking/tcp/IggyTcpClient.java @@ -64,4 +64,10 @@ public ConsumerOffsetsClient consumerOffsets() { public MessagesClient messages() { return messagesClient; } + + @Override + public PersonalAccessTokensClient personalAccessTokens() { + throw new UnsupportedOperationException(); + } + } diff --git a/src/main/java/rs/iggy/personalaccesstoken/PersonalAccessTokenInfo.java b/src/main/java/rs/iggy/personalaccesstoken/PersonalAccessTokenInfo.java new file mode 100644 index 0000000..8701582 --- /dev/null +++ b/src/main/java/rs/iggy/personalaccesstoken/PersonalAccessTokenInfo.java @@ -0,0 +1,7 @@ +package rs.iggy.personalaccesstoken; + +import java.math.BigInteger; +import java.util.Optional; + +public record PersonalAccessTokenInfo(String name, Optional expiryAt) { +} diff --git a/src/main/java/rs/iggy/personalaccesstoken/RawPersonalAccessToken.java b/src/main/java/rs/iggy/personalaccesstoken/RawPersonalAccessToken.java new file mode 100644 index 0000000..7aab05a --- /dev/null +++ b/src/main/java/rs/iggy/personalaccesstoken/RawPersonalAccessToken.java @@ -0,0 +1,4 @@ +package rs.iggy.personalaccesstoken; + +public record RawPersonalAccessToken(String token) { +} diff --git a/src/test/java/rs/iggy/clients/blocking/PersonalAccessTokensBaseTest.java b/src/test/java/rs/iggy/clients/blocking/PersonalAccessTokensBaseTest.java new file mode 100644 index 0000000..299402e --- /dev/null +++ b/src/test/java/rs/iggy/clients/blocking/PersonalAccessTokensBaseTest.java @@ -0,0 +1,65 @@ +package rs.iggy.clients.blocking; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import rs.iggy.user.IdentityInfo; +import rs.iggy.user.UserInfoDetails; +import java.math.BigInteger; +import static org.assertj.core.api.Assertions.assertThat; + +public abstract class PersonalAccessTokensBaseTest extends IntegrationTest { + + protected PersonalAccessTokensClient personalAccessTokensClient; + + @BeforeEach + void beforeEachBase() { + personalAccessTokensClient = client.personalAccessTokens(); + + login(); + } + + @Test + void shouldManagePersonalAccessTokens() { + // when + var createdToken = personalAccessTokensClient.createPersonalAccessToken("new-token", + BigInteger.valueOf(50_000)); + + // then + assertThat(createdToken).isNotNull(); + + // when + var tokens = personalAccessTokensClient.getPersonalAccessTokens(); + + // then + assertThat(tokens).isNotNull(); + assertThat(tokens).hasSize(1); + + // when + personalAccessTokensClient.deletePersonalAccessToken("new-token"); + tokens = personalAccessTokensClient.getPersonalAccessTokens(); + + // + assertThat(tokens).hasSize(0); + } + + @Test + void shouldCreateAndLogInWithPersonalAccessToken() { + // given + var createdToken = personalAccessTokensClient.createPersonalAccessToken("new-token", + BigInteger.valueOf(50_000)); + client.users().logout(); + + // when + IdentityInfo identityInfo = personalAccessTokensClient.loginWithPersonalAccessToken(createdToken.token()); + + // then + assertThat(identityInfo).isNotNull(); + + // when + UserInfoDetails user = client.users().getUser(1L); + + // then + assertThat(user).isNotNull(); + } + +} diff --git a/src/test/java/rs/iggy/clients/blocking/http/PersonalAccessTokensHttpClientTest.java b/src/test/java/rs/iggy/clients/blocking/http/PersonalAccessTokensHttpClientTest.java new file mode 100644 index 0000000..b89c9be --- /dev/null +++ b/src/test/java/rs/iggy/clients/blocking/http/PersonalAccessTokensHttpClientTest.java @@ -0,0 +1,13 @@ +package rs.iggy.clients.blocking.http; + +import rs.iggy.clients.blocking.IggyClient; +import rs.iggy.clients.blocking.PersonalAccessTokensBaseTest; + +class PersonalAccessTokensHttpClientTest extends PersonalAccessTokensBaseTest { + + @Override + protected IggyClient getClient() { + return HttpClientFactory.create(iggyServer); + } + +}