diff --git a/src/main/java/com/meilisearch/sdk/Client.java b/src/main/java/com/meilisearch/sdk/Client.java index 936a9719..768ae872 100644 --- a/src/main/java/com/meilisearch/sdk/Client.java +++ b/src/main/java/com/meilisearch/sdk/Client.java @@ -8,6 +8,8 @@ import com.meilisearch.sdk.exceptions.MeilisearchException; import com.meilisearch.sdk.json.JsonHandler; import com.meilisearch.sdk.model.Key; +import com.meilisearch.sdk.model.KeyUpdate; +import com.meilisearch.sdk.model.KeysQuery; import com.meilisearch.sdk.model.Results; import com.meilisearch.sdk.model.Stats; import com.meilisearch.sdk.model.Task; @@ -263,7 +265,7 @@ public void waitForTask(int uid) throws MeilisearchException { * https://docs.meilisearch.com/reference/api/keys.html#get-one-key * * @param uid Identifier of the requested Key - * @return Key Instance + * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs */ public Key getKey(String uid) throws MeilisearchException { @@ -273,18 +275,29 @@ public Key getKey(String uid) throws MeilisearchException { /** * Retrieves list of keys https://docs.meilisearch.com/reference/api/keys.html#get-all-keys * - * @return List of keys in the Meilisearch client + * @return Results containing a list of Key from the Meilisearch API * @throws MeilisearchException if an error occurs */ public Results getKeys() throws MeilisearchException { return this.keysHandler.getKeys(); } + /** + * Get list of all API keys https://docs.meilisearch.com/reference/api/keys.html#get-all-keys + * + * @param params query parameters accepted by the get keys route + * @return Results containing a list of Key from the Meilisearch API + * @throws MeilisearchException if an error occurs + */ + public Results getKeys(KeysQuery params) throws MeilisearchException { + return this.keysHandler.getKeys(params); + } + /** * Creates a key https://docs.meilisearch.com/reference/api/keys.html#create-a-key * * @param options Key containing the options of the key - * @return Key Instance + * @return Meilisearch API response as Key Instance * @throws MeilisearchException if an error occurs */ public Key createKey(Key options) throws MeilisearchException { @@ -296,10 +309,10 @@ public Key createKey(Key options) throws MeilisearchException { * * @param key String containing the key * @param options String containing the options to update - * @return Key Instance - * @throws Exception if client request causes an error + * @return Meilisearch API response as Key Instance + * @throws MeilisearchException if an error occurs */ - public Key updateKey(String key, Key options) throws Exception { + public Key updateKey(String key, KeyUpdate options) throws MeilisearchException { return this.keysHandler.updateKey(key, options); } diff --git a/src/main/java/com/meilisearch/sdk/KeysHandler.java b/src/main/java/com/meilisearch/sdk/KeysHandler.java index d3d52f8f..9ffa47e5 100644 --- a/src/main/java/com/meilisearch/sdk/KeysHandler.java +++ b/src/main/java/com/meilisearch/sdk/KeysHandler.java @@ -2,6 +2,8 @@ import com.meilisearch.sdk.exceptions.MeilisearchException; import com.meilisearch.sdk.model.Key; +import com.meilisearch.sdk.model.KeyUpdate; +import com.meilisearch.sdk.model.KeysQuery; import com.meilisearch.sdk.model.Results; /** @@ -29,20 +31,29 @@ public class KeysHandler { * @throws MeilisearchException if client request causes an error */ Key getKey(String uid) throws MeilisearchException { - String urlPath = "/keys/" + uid; - return httpClient.get(urlPath, Key.class); + return httpClient.get(new KeysQuery().toQuery(uid), Key.class); } /** * Retrieves keys from the client * - * @return List of key instance + * @return Results containing a list of Key instance * @throws MeilisearchException if client request causes an error */ Results getKeys() throws MeilisearchException { String urlPath = "/keys"; - Results result = httpClient.get(urlPath, Results.class, Key.class); - return result; + return httpClient.get(urlPath, Results.class, Key.class); + } + + /** + * Retrieves keys from the client + * + * @param params accept by the keys route + * @return Results containing a list of Key instance + * @throws MeilisearchException if client request causes an error + */ + Results getKeys(KeysQuery params) throws MeilisearchException { + return httpClient.get(params.toQuery(params), Results.class, Key.class); } /** @@ -63,11 +74,10 @@ Key createKey(Key options) throws MeilisearchException { * @param key String containing the key * @param options String containing the options of the key * @return Key Instance - * @throws Exception if client request causes an error + * @throws MeilisearchException if client request causes an error */ - Key updateKey(String key, Key options) throws Exception { - String urlPath = "/keys/" + key; - return httpClient.patch(urlPath, options, Key.class); + Key updateKey(String key, KeyUpdate options) throws MeilisearchException { + return httpClient.patch(new KeysQuery().toQuery(key), options, Key.class); } /** @@ -77,7 +87,6 @@ Key updateKey(String key, Key options) throws Exception { * @throws MeilisearchException if client request causes an error */ void deleteKey(String key) throws MeilisearchException { - String urlPath = "/keys/" + key; - httpClient.delete(urlPath, String.class); + httpClient.delete(new KeysQuery().toQuery(key), String.class); } } diff --git a/src/main/java/com/meilisearch/sdk/json/GsonJsonHandler.java b/src/main/java/com/meilisearch/sdk/json/GsonJsonHandler.java index 3c9eeee5..10cbf1e4 100644 --- a/src/main/java/com/meilisearch/sdk/json/GsonJsonHandler.java +++ b/src/main/java/com/meilisearch/sdk/json/GsonJsonHandler.java @@ -2,6 +2,9 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; import com.meilisearch.sdk.exceptions.JsonDecodingException; @@ -26,9 +29,20 @@ public String encode(Object o) throws MeilisearchException { return (String) o; } // TODO: review later + // This is a workaround to encode the Key class properly if (o != null && o.getClass() == Key.class) { GsonBuilder builder = new GsonBuilder(); - this.gson = builder.serializeNulls().setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").create(); + this.gson = builder.setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").create(); + + Key key = (Key) o; + if (key.getExpiresAt() == null) { + JsonElement jsonElement = gson.toJsonTree(o); + JsonObject jsonObject = jsonElement.getAsJsonObject(); + jsonObject.add("expiresAt", JsonNull.INSTANCE); + o = jsonObject; + this.gson = + builder.serializeNulls().setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").create(); + } } try { return gson.toJson(o); @@ -52,7 +66,7 @@ public T decode(Object o, Class targetClass, Class... parameters) return gson.fromJson((String) o, targetClass); } else { TypeToken parameterized = TypeToken.getParameterized(targetClass, parameters); - return gson.fromJson((String) o, parameterized.getType()); + return gson.fromJson((String) o, parameterized.getType()); } } catch (JsonSyntaxException e) { throw new JsonDecodingException(e); diff --git a/src/main/java/com/meilisearch/sdk/model/Key.java b/src/main/java/com/meilisearch/sdk/model/Key.java index 110a91ea..7a3d8a8e 100644 --- a/src/main/java/com/meilisearch/sdk/model/Key.java +++ b/src/main/java/com/meilisearch/sdk/model/Key.java @@ -12,11 +12,17 @@ */ @Getter public class Key { + @Setter + @Accessors(chain = true) + protected String name = null; + @Setter @Accessors(chain = true) protected String description = null; - protected String key = ""; + protected String uid = null; + + protected String key = null; @Setter @Accessors(chain = true) diff --git a/src/main/java/com/meilisearch/sdk/model/KeyUpdate.java b/src/main/java/com/meilisearch/sdk/model/KeyUpdate.java new file mode 100644 index 00000000..42c02802 --- /dev/null +++ b/src/main/java/com/meilisearch/sdk/model/KeyUpdate.java @@ -0,0 +1,23 @@ +package com.meilisearch.sdk.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + * Data structure for updating a Key + * + *

https://docs.meilisearch.com/reference/api/keys.html + */ +@Getter +public class KeyUpdate { + @Setter + @Accessors(chain = true) + protected String name = null; + + @Setter + @Accessors(chain = true) + protected String description = null; + + public KeyUpdate() {} +} diff --git a/src/main/java/com/meilisearch/sdk/model/KeysQuery.java b/src/main/java/com/meilisearch/sdk/model/KeysQuery.java new file mode 100644 index 00000000..0b22c199 --- /dev/null +++ b/src/main/java/com/meilisearch/sdk/model/KeysQuery.java @@ -0,0 +1,35 @@ +package com.meilisearch.sdk.model; + +import com.meilisearch.sdk.http.URLBuilder; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + * Data structure of the query parameters for the keys routes + * + *

https://docs.meilisearch.com/reference/api/keys.html#query-parameters + */ +@Setter +@Getter +@Accessors(chain = true) +public class KeysQuery { + private int offset = -1; + private int limit = -1; + + public KeysQuery() {} + + public String toQuery(String key) { + URLBuilder urlb = new URLBuilder(); + urlb.addSubroute("keys").addSubroute(key); + return urlb.getURL(); + } + + public String toQuery(KeysQuery param) { + URLBuilder urlb = new URLBuilder(); + urlb.addSubroute("keys") + .addParameter("limit", param.getLimit()) + .addParameter("offset", param.getOffset()); + return urlb.getURL(); + } +} diff --git a/src/test/java/com/meilisearch/integration/KeysTest.java b/src/test/java/com/meilisearch/integration/KeysTest.java index 4b0bbd30..a2c3d4b6 100644 --- a/src/test/java/com/meilisearch/integration/KeysTest.java +++ b/src/test/java/com/meilisearch/integration/KeysTest.java @@ -3,7 +3,10 @@ import static org.junit.jupiter.api.Assertions.*; import com.meilisearch.integration.classes.AbstractIT; +import com.meilisearch.sdk.exceptions.MeilisearchApiException; import com.meilisearch.sdk.model.Key; +import com.meilisearch.sdk.model.KeyUpdate; +import com.meilisearch.sdk.model.KeysQuery; import com.meilisearch.sdk.model.Results; import java.text.SimpleDateFormat; import java.util.Date; @@ -19,6 +22,8 @@ public class KeysTest extends AbstractIT { public void initialize() { this.setUp(); this.setUpJacksonClient(); + cleanup(); + deleteAllKeys(); } @AfterAll @@ -37,6 +42,7 @@ public void testClientGetKeys() throws Exception { for (Key key : keys) { assertNotNull(key.getKey()); + assertNotNull(key.getUid()); assertNotNull(key.getActions()); assertNotNull(key.getIndexes()); assertNotNull(key.getDescription()); @@ -52,7 +58,7 @@ public void testClientGetKeysWithJacksonJsonHandler() throws Exception { Results result = clientJackson.getKeys(); Key[] keys = result.getResults(); - assertEquals(5, keys.length); + assertEquals(2, keys.length); for (Key key : keys) { assertNotNull(key.getKey()); @@ -63,36 +69,104 @@ public void testClientGetKeysWithJacksonJsonHandler() throws Exception { } } + /** Test Get Keys With Limit */ + @Test + public void testClientGetKeysLimit() throws Exception { + int limit = 24; + KeysQuery query = new KeysQuery().setLimit(limit); + + Results result = client.getKeys(query); + + assertEquals(limit, result.getLimit()); + assertNotNull(result.getOffset()); + assertNotNull(result.getTotal()); + assertNotNull(result.getResults().length); + } + + /** Test Get Keys With Limit and Offset */ + @Test + public void testClientGetKeysLimitAndOffset() throws Exception { + int limit = 24; + int offset = 2; + KeysQuery query = new KeysQuery().setLimit(limit).setOffset(offset); + + Results result = client.getKeys(query); + + assertEquals(limit, result.getLimit()); + assertEquals(offset, result.getOffset()); + assertNotNull(result.getTotal()); + assertNotNull(result.getResults().length); + } + /** Test Get Key */ @Test public void testClientGetKey() throws Exception { + Results result = client.getKeys(); + Key[] keys = result.getResults(); + + Key key = client.getKey(keys[0].getKey()); + + assertTrue(key instanceof Key); + assertNotNull(key.getKey()); + assertNotNull(key.getActions()); + assertNotNull(key.getIndexes()); + assertNotNull(key.getDescription()); + assertNotNull(key.getCreatedAt()); + assertNotNull(key.getUpdatedAt()); + } + + /** Test Get Key With Uid */ + @Test + public void testClientGetKeyWithUid() throws Exception { + Results result = client.getKeys(); + Key[] keys = result.getResults(); + + Key key = client.getKey(keys[0].getUid()); + + assertTrue(key instanceof Key); + assertNotNull(key.getKey()); + assertNotNull(key.getActions()); + assertNotNull(key.getIndexes()); + assertNotNull(key.getDescription()); + assertNotNull(key.getCreatedAt()); + assertNotNull(key.getUpdatedAt()); + } + + /** Test Get Key when the key does not exist */ + @Test + public void testClientGetKeyDoesNotExist() throws Exception { + assertThrows(MeilisearchApiException.class, () -> client.getKey("KeyDoesNotExist")); + } + + /** Test Create a simple API Key without description */ + @Test + public void testClientCreateDefaultKey() throws Exception { Key keyInfo = new Key(); keyInfo.setIndexes(new String[] {"*"}); keyInfo.setActions(new String[] {"*"}); keyInfo.setExpiresAt(null); - Key createKey = client.createKey(keyInfo); - Key key = client.getKey(createKey.getKey()); + Key key = client.createKey(keyInfo); assertTrue(key instanceof Key); assertNotNull(key.getKey()); - assertNotNull(key.getActions()); - assertNotNull(key.getIndexes()); + assertEquals("*", key.getActions()[0]); + assertEquals("*", key.getIndexes()[0]); assertNull(key.getDescription()); assertNull(key.getExpiresAt()); assertNotNull(key.getCreatedAt()); assertNotNull(key.getUpdatedAt()); } - /** Test Create a simple API Key without description */ + /** Test Create a simple API Key without description with Jackson Json Handler */ @Test - public void testClientCreateDefaultKey() throws Exception { + public void testClientCreateDefaultKeyWithJacksonJsonHandler() throws Exception { Key keyInfo = new Key(); keyInfo.setIndexes(new String[] {"*"}); keyInfo.setActions(new String[] {"*"}); keyInfo.setExpiresAt(null); - Key key = client.createKey(keyInfo); + Key key = clientJackson.createKey(keyInfo); assertTrue(key instanceof Key); assertNotNull(key.getKey()); @@ -155,13 +229,15 @@ public void testClientUpdateKey() throws Exception { Date dateParsed = format.parse("2042-01-30T00:00:00Z"); Key keyInfo = new Key(); + keyInfo.setName("Key"); + keyInfo.setDescription("Description Key To Update - test"); keyInfo.setIndexes(new String[] {"*"}); - keyInfo.setActions(new String[] {"*"}); + keyInfo.setActions(new String[] {"search"}); + keyInfo.setExpiresAt(dateParsed); - Key keyChanges = new Key(); - keyChanges.setIndexes(new String[] {"testUpdateKey"}); - keyChanges.setActions(new String[] {"search"}); - keyChanges.setExpiresAt(dateParsed); + KeyUpdate keyChanges = new KeyUpdate(); + keyInfo.setName("Key After Update"); + keyInfo.setDescription("Description Key After Update - test"); Key createKey = client.createKey(keyInfo); Key updateKey = client.updateKey(createKey.getKey(), keyChanges); @@ -169,11 +245,46 @@ public void testClientUpdateKey() throws Exception { assertTrue(createKey instanceof Key); assertTrue(updateKey instanceof Key); assertNotNull(updateKey.getKey()); - assertEquals("*", createKey.getActions()[0]); - assertEquals("search", updateKey.getActions()[0]); assertEquals("*", createKey.getIndexes()[0]); - assertEquals("testUpdateKey", updateKey.getIndexes()[0]); - assertNull(createKey.getExpiresAt()); + assertEquals("search", createKey.getActions()[0]); + assertEquals("Key After Update", createKey.getName()); + assertEquals("Description Key After Update - test", updateKey.getDescription()); + assertEquals(createKey.getIndexes()[0], updateKey.getIndexes()[0]); + assertEquals(createKey.getActions()[0], updateKey.getActions()[0]); + assertEquals(dateParsed, updateKey.getExpiresAt()); + assertNotNull(updateKey.getCreatedAt()); + assertNotNull(updateKey.getUpdatedAt()); + } + + /** Test Update an API Key with Jackson Json Handler */ + @Test + public void testClientUpdateKeyWithJacksonJsonHandler() throws Exception { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + Date dateParsed = format.parse("2042-01-30T00:00:00Z"); + + Key keyInfo = new Key(); + keyInfo.setName("Key"); + keyInfo.setDescription("Description Key To Update - test"); + keyInfo.setIndexes(new String[] {"*"}); + keyInfo.setActions(new String[] {"search"}); + keyInfo.setExpiresAt(dateParsed); + + KeyUpdate keyChanges = new KeyUpdate(); + keyInfo.setName("Key After Update"); + keyInfo.setDescription("Description Key After Update - test"); + + Key createKey = clientJackson.createKey(keyInfo); + Key updateKey = clientJackson.updateKey(createKey.getKey(), keyChanges); + + assertTrue(createKey instanceof Key); + assertTrue(updateKey instanceof Key); + assertNotNull(updateKey.getKey()); + assertEquals("*", createKey.getIndexes()[0]); + assertEquals("search", createKey.getActions()[0]); + assertEquals("Key After Update", createKey.getName()); + assertEquals("Description Key After Update - test", updateKey.getDescription()); + assertEquals(createKey.getIndexes()[0], updateKey.getIndexes()[0]); + assertEquals(createKey.getActions()[0], updateKey.getActions()[0]); assertEquals(dateParsed, updateKey.getExpiresAt()); assertNotNull(updateKey.getCreatedAt()); assertNotNull(updateKey.getUpdatedAt()); @@ -192,4 +303,18 @@ public void testClientDeleteKey() throws Exception { assertThrows(Exception.class, () -> client.getKey(createKey.getKey())); } + + /** Test Delete an API Key With Uid */ + @Test + public void testClientDeleteKeyWithUid() throws Exception { + Key keyInfo = new Key(); + keyInfo.setIndexes(new String[] {"*"}); + keyInfo.setActions(new String[] {"*"}); + keyInfo.setExpiresAt(null); + + Key createKey = client.createKey(keyInfo); + client.deleteKey(createKey.getUid()); + + assertThrows(Exception.class, () -> client.getKey(createKey.getUid())); + } }