diff --git a/src/it/java/io/weaviate/integration/AliasITest.java b/src/it/java/io/weaviate/integration/AliasITest.java index 0fc40fc6b..ab180d6f0 100644 --- a/src/it/java/io/weaviate/integration/AliasITest.java +++ b/src/it/java/io/weaviate/integration/AliasITest.java @@ -48,9 +48,12 @@ public void test_aliasLifecycle() throws IOException { .returns(nsColsonBaker, Alias::collection); // Act: delete Bono alias - client.alias.delete("Bono"); + var deleted = client.alias.delete("Bono"); + Assertions.assertThat(deleted).as("object was deleted").isTrue(); - // Assert + // Act: delete non-existent alias + deleted = client.alias.delete("Bono"); + Assertions.assertThat(deleted).as("object wasn't deleted").isFalse(); var paulHewsonAliases = client.alias.list(all -> all.collection(nsPaulHewson)); Assertions.assertThat(paulHewsonAliases) .as("no aliases once Bono is deleted") diff --git a/src/it/java/io/weaviate/integration/DataITest.java b/src/it/java/io/weaviate/integration/DataITest.java index ddd34b391..246784cf5 100644 --- a/src/it/java/io/weaviate/integration/DataITest.java +++ b/src/it/java/io/weaviate/integration/DataITest.java @@ -79,9 +79,16 @@ public void testCreateGetDelete() throws IOException { .as("lastUpdateTimeUnix").isNotNull(); }); - artists.data.delete(id); + var deleted = artists.data.deleteById(id); + Assertions.assertThat(deleted) + .as("object was deleted").isTrue(); Assertions.assertThat(artists.data.exists(id)) .as("object not exists after deletion").isFalse(); + + deleted = artists.data.deleteById(id); + // TODO: Change to isFalse() after fixed in Weaviate server + Assertions.assertThat(deleted) + .as("object wasn't deleted").isTrue(); } @Test diff --git a/src/it/java/io/weaviate/integration/RbacITest.java b/src/it/java/io/weaviate/integration/RbacITest.java index 7f3b90ff2..9bdbed2e9 100644 --- a/src/it/java/io/weaviate/integration/RbacITest.java +++ b/src/it/java/io/weaviate/integration/RbacITest.java @@ -206,19 +206,35 @@ public void test_users_db() throws IOException { .extracting(Role::name) .doesNotContain(roleName); - client.users.db.activate(userId); + var deactivated = client.users.db.deactivate(userId); + Assertions.assertThat(deactivated) + .as("user was deactivated") + .isTrue(); + Assertions.assertThat(client.users.db.byName(userId)).get() + .as("user is deactivated") + .returns(false, DbUser::active); + + deactivated = client.users.db.deactivate(userId); + Assertions.assertThat(deactivated) + .as("user was already deactivated") + .isFalse(); + + var activated = client.users.db.activate(userId); + Assertions.assertThat(activated) + .as("user was activated") + .isTrue(); Assertions.assertThat(client.users.db.byName(userId)).get() .as("user is activated") .returns(true, DbUser::active); + activated = client.users.db.activate(userId); + Assertions.assertThat(activated) + .as("user was already active") + .isFalse(); + apiKey = client.users.db.rotateKey(userId); assertValidApiKey(apiKey); - client.users.db.deactivate(userId); - Assertions.assertThat(client.users.db.byName(userId)).get() - .as("user is deactivated") - .returns(false, DbUser::active); - var all = client.users.db.list(users -> users.includeLastUsedAt(true)); Assertions.assertThat(all) .as("list users include lastUsedTime ") @@ -226,10 +242,18 @@ public void test_users_db() throws IOException { .extracting(DbUser::id) .contains(userId, ADMIN_USER); - client.users.db.delete(userId); + var deleted = client.users.db.delete(userId); + Assertions.assertThat(deleted) + .as("user was deleted") + .isTrue(); Assertions.assertThat(client.users.db.byName(userId)) .as("user is deleted") .isEmpty(); + + deleted = client.users.db.delete(userId); + Assertions.assertThat(deleted) + .as("user was already deleted") + .isFalse(); } @Test diff --git a/src/main/java/io/weaviate/client6/v1/api/alias/DeleteAliasRequest.java b/src/main/java/io/weaviate/client6/v1/api/alias/DeleteAliasRequest.java index 4b3ed2d37..c94101258 100644 --- a/src/main/java/io/weaviate/client6/v1/api/alias/DeleteAliasRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/alias/DeleteAliasRequest.java @@ -2,11 +2,11 @@ import java.util.Collections; +import io.weaviate.client6.v1.internal.rest.BooleanEndpoint; import io.weaviate.client6.v1.internal.rest.Endpoint; -import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; public record DeleteAliasRequest(String alias) { - public final static Endpoint _ENDPOINT = SimpleEndpoint.sideEffect( + public final static Endpoint _ENDPOINT = BooleanEndpoint.noBody( __ -> "DELETE", request -> "/aliases/" + request.alias, __ -> Collections.emptyMap()); diff --git a/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClient.java b/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClient.java index 08bcb3843..57c018828 100644 --- a/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClient.java @@ -117,8 +117,11 @@ public void update(String alias, String newTargetCollection) throws IOException * @throws IOException in case the request was not sent successfully * due to a malformed request, a networking error * or the server being unavailable. + * + * @return {@code true} if the alias was deleted, {@code false} if there was no + * alias to delete. */ - public void delete(String alias) throws IOException { - this.restTransport.performRequest(new DeleteAliasRequest(alias), DeleteAliasRequest._ENDPOINT); + public boolean delete(String alias) throws IOException { + return this.restTransport.performRequest(new DeleteAliasRequest(alias), DeleteAliasRequest._ENDPOINT); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClientAsync.java index b7de85a06..00e59729d 100644 --- a/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/alias/WeaviateAliasClientAsync.java @@ -94,7 +94,7 @@ public CompletableFuture update(String alias, String newTargetCollection) * * @return A future holding the server's response. */ - public CompletableFuture delete(String alias) { + public CompletableFuture delete(String alias) { return this.restTransport.performRequestAsync(new DeleteAliasRequest(alias), DeleteAliasRequest._ENDPOINT); } } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java index 0bb205cdd..2788566a9 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/DeleteObjectRequest.java @@ -2,15 +2,15 @@ import io.weaviate.client6.v1.api.collections.CollectionHandleDefaults; import io.weaviate.client6.v1.internal.orm.CollectionDescriptor; +import io.weaviate.client6.v1.internal.rest.BooleanEndpoint; import io.weaviate.client6.v1.internal.rest.Endpoint; -import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; public record DeleteObjectRequest(String uuid) { - public static final Endpoint endpoint( + public static final Endpoint endpoint( CollectionDescriptor collection, CollectionHandleDefaults defaults) { - return SimpleEndpoint.sideEffect( + return BooleanEndpoint.noBody( request -> "DELETE", request -> "/objects/" + collection.collectionName() + "/" + request.uuid, request -> defaults.queryParameters()); diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java index caa55a825..c6eb48fe3 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClient.java @@ -97,8 +97,15 @@ public void replace(String uuid, ReplaceObjectRequest.endpoint(collection, defaults)); } - public void delete(String uuid) throws IOException { - this.restTransport.performRequest(new DeleteObjectRequest(uuid), + /** + * Delete an object by its UUID. + * + * @param uuid The UUID of the object to delete. + * @return {@code true} if the object was deleted, {@code false} if there was no object to delete. + * @throws IOException in case the request was not sent successfully. + */ + public boolean deleteById(String uuid) throws IOException { + return this.restTransport.performRequest(new DeleteObjectRequest(uuid), DeleteObjectRequest.endpoint(collection, defaults)); } diff --git a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java index 8b47d572d..83da338f6 100644 --- a/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/collections/data/WeaviateDataClientAsync.java @@ -92,7 +92,7 @@ public CompletableFuture replace(String uuid, ReplaceObjectRequest.endpoint(collection, defaults)); } - public CompletableFuture delete(String uuid) { + public CompletableFuture delete(String uuid) { return this.restTransport.performRequestAsync(new DeleteObjectRequest(uuid), DeleteObjectRequest.endpoint(collection, defaults)); } diff --git a/src/main/java/io/weaviate/client6/v1/api/rbac/users/ActivateDbUserRequest.java b/src/main/java/io/weaviate/client6/v1/api/rbac/users/ActivateDbUserRequest.java index 5c7ae391a..035f038a2 100644 --- a/src/main/java/io/weaviate/client6/v1/api/rbac/users/ActivateDbUserRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/rbac/users/ActivateDbUserRequest.java @@ -2,13 +2,13 @@ import java.util.Collections; +import io.weaviate.client6.v1.internal.rest.BooleanEndpoint; import io.weaviate.client6.v1.internal.rest.Endpoint; -import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; import io.weaviate.client6.v1.internal.rest.UrlEncoder; public record ActivateDbUserRequest(String userId) { - public static final Endpoint _ENDPOINT = SimpleEndpoint.sideEffect( + public static final Endpoint _ENDPOINT = BooleanEndpoint.noBody( __ -> "POST", request -> "/users/db/" + UrlEncoder.encodeValue(((ActivateDbUserRequest) request).userId) + "/activate", request -> Collections.emptyMap()) diff --git a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClient.java b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClient.java index 4a24472c8..18d77d310 100644 --- a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClient.java +++ b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClient.java @@ -34,42 +34,45 @@ public String create(String userId) throws IOException { * Delete a "db" user. * * @param userId User ID. + * @return {@code true} if the user was deleted, {@code false} if there was no user to delete. * @throws WeaviateApiException in case the server returned with an * error status code. * @throws IOException in case the request was not sent successfully * due to a malformed request, a networking error * or the server being unavailable. */ - public void delete(String userId) throws IOException { - this.restTransport.performRequest(new DeleteDbUserRequest(userId), DeleteDbUserRequest._ENDPOINT); + public boolean delete(String userId) throws IOException { + return this.restTransport.performRequest(new DeleteDbUserRequest(userId), DeleteDbUserRequest._ENDPOINT); } /** * Activate a "db" user. * * @param userId User ID. + * @return {@code true} if the user was activated, {@code false} if the user was already active. * @throws WeaviateApiException in case the server returned with an * error status code. * @throws IOException in case the request was not sent successfully * due to a malformed request, a networking error * or the server being unavailable. */ - public void activate(String userId) throws IOException { - this.restTransport.performRequest(new ActivateDbUserRequest(userId), ActivateDbUserRequest._ENDPOINT); + public boolean activate(String userId) throws IOException { + return this.restTransport.performRequest(new ActivateDbUserRequest(userId), ActivateDbUserRequest._ENDPOINT); } /** * Deactivate a "db" user. * * @param userId User ID. + * @return {@code true} if the user was deactivated, {@code false} if the user was already deactivated. * @throws WeaviateApiException in case the server returned with an * error status code. * @throws IOException in case the request was not sent successfully * due to a malformed request, a networking error * or the server being unavailable. */ - public void deactivate(String userId) throws IOException { - this.restTransport.performRequest(new DeactivateDbUserRequest(userId), DeactivateDbUserRequest._ENDPOINT); + public boolean deactivate(String userId) throws IOException { + return this.restTransport.performRequest(new DeactivateDbUserRequest(userId), DeactivateDbUserRequest._ENDPOINT); } /** diff --git a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClientAsync.java b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClientAsync.java index a315656c9..0d291ca43 100644 --- a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClientAsync.java +++ b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClientAsync.java @@ -30,7 +30,7 @@ public CompletableFuture create(String userId) throws IOException { * * @param userId User ID. */ - public CompletableFuture delete(String userId) throws IOException { + public CompletableFuture delete(String userId) throws IOException { return this.restTransport.performRequestAsync(new DeleteDbUserRequest(userId), DeleteDbUserRequest._ENDPOINT); } @@ -39,7 +39,7 @@ public CompletableFuture delete(String userId) throws IOException { * * @param userId User ID. */ - public CompletableFuture activate(String userId) throws IOException { + public CompletableFuture activate(String userId) throws IOException { return this.restTransport.performRequestAsync(new ActivateDbUserRequest(userId), ActivateDbUserRequest._ENDPOINT); } @@ -48,7 +48,7 @@ public CompletableFuture activate(String userId) throws IOException { * * @param userId User ID. */ - public CompletableFuture deactivate(String userId) throws IOException { + public CompletableFuture deactivate(String userId) throws IOException { return this.restTransport.performRequestAsync(new DeactivateDbUserRequest(userId), DeactivateDbUserRequest._ENDPOINT); } diff --git a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeactivateDbUserRequest.java b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeactivateDbUserRequest.java index dc5ec489e..959f0a5b3 100644 --- a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeactivateDbUserRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeactivateDbUserRequest.java @@ -2,13 +2,13 @@ import java.util.Collections; +import io.weaviate.client6.v1.internal.rest.BooleanEndpoint; import io.weaviate.client6.v1.internal.rest.Endpoint; -import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; import io.weaviate.client6.v1.internal.rest.UrlEncoder; public record DeactivateDbUserRequest(String userId) { - public static final Endpoint _ENDPOINT = SimpleEndpoint.sideEffect( + public static final Endpoint _ENDPOINT = BooleanEndpoint.noBody( __ -> "POST", request -> "/users/db/" + UrlEncoder.encodeValue(((DeactivateDbUserRequest) request).userId) + "/deactivate", request -> Collections.emptyMap()) diff --git a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeleteDbUserRequest.java b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeleteDbUserRequest.java index d34636d5c..ad9caf592 100644 --- a/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeleteDbUserRequest.java +++ b/src/main/java/io/weaviate/client6/v1/api/rbac/users/DeleteDbUserRequest.java @@ -2,13 +2,13 @@ import java.util.Collections; +import io.weaviate.client6.v1.internal.rest.BooleanEndpoint; import io.weaviate.client6.v1.internal.rest.Endpoint; -import io.weaviate.client6.v1.internal.rest.SimpleEndpoint; import io.weaviate.client6.v1.internal.rest.UrlEncoder; public record DeleteDbUserRequest(String userId) { - public static final Endpoint _ENDPOINT = SimpleEndpoint.sideEffect( + public static final Endpoint _ENDPOINT = BooleanEndpoint.noBody( __ -> "DELETE", request -> "/users/db/" + UrlEncoder.encodeValue(request.userId), request -> Collections.emptyMap()); diff --git a/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java b/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java index 2efc2abee..64b85a0e6 100644 --- a/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java +++ b/src/main/java/io/weaviate/client6/v1/internal/rest/BooleanEndpoint.java @@ -20,6 +20,12 @@ public BooleanEndpoint( super(method, requestUrl, queryParameters, body); } + @SuppressWarnings("unchecked") + public BooleanEndpoint allowStatus(Integer... statusCodes) { + super._allowStatusCodes(statusCodes); + return (BooleanEndpoint) this; + } + @Override public boolean isError(int statusCode) { return statusCode != 404 && super.isError(statusCode); diff --git a/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleTest.java b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleTest.java index 9e6e93a1a..e775e92cf 100644 --- a/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleTest.java +++ b/src/test/java/io/weaviate/client6/v1/api/collections/CollectionHandleTest.java @@ -80,7 +80,7 @@ public static Object[][] restTestCases() { "data::delete by id", ConsistencyLevel.ONE, Location.QUERY, "john_doe", Location.QUERY, - (Act) c -> c.data.delete("test-uuid"), + (Act) c -> c.data.deleteById("test-uuid"), }, { "data::add reference", diff --git a/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java b/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java index 1ae6c4498..587cb2548 100644 --- a/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java +++ b/src/test/java/io/weaviate/testutil/transport/MockRestTransport.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; +import io.weaviate.client6.v1.internal.rest.BooleanEndpoint; import io.weaviate.client6.v1.internal.rest.Endpoint; import io.weaviate.client6.v1.internal.rest.RestTransport; @@ -38,10 +39,14 @@ public void assertNext(AssertFunction... assertions) { } } + @SuppressWarnings("unchecked") @Override public ResponseT performRequest(RequestT request, Endpoint endpoint) throws IOException { requests.add(new Request<>(request, endpoint)); + if (endpoint instanceof BooleanEndpoint) { + return (ResponseT) Boolean.TRUE; + } return null; }