Skip to content

Commit a11c815

Browse files
committed
fix: return new API keys from create/rotateApiKey methods
1 parent 51f7011 commit a11c815

8 files changed

Lines changed: 58 additions & 43 deletions

File tree

src/it/java/io/weaviate/containers/Weaviate.java

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,15 @@ public class Weaviate extends WeaviateContainer {
2121

2222
private volatile SharedClient clientInstance;
2323

24-
public WeaviateClient getClient() {
25-
return getClient(ObjectBuilder.identity());
26-
}
27-
2824
/**
2925
* Create a new instance of WeaviateClient connected to this container if none
3026
* exist. Get an existing client otherwise.
3127
*
3228
* The lifetime of this client is tied to that of its container, which means
3329
* that you do not need to {@code close} it manually. It will only truly close
3430
* after the parent Testcontainer is stopped.
35-
*
36-
* FIXME: we cannot return the same client for 2 different sets of
37-
* configurations.
38-
* What we should do is: {@link #getClient()} returns the shared client, while
39-
* this one always constructs a new instance.
40-
* Otherwise we'll get a race condition once the tests are parallelized.
4131
*/
42-
public WeaviateClient getClient(Function<Config.Custom, ObjectBuilder<Config>> fn) {
32+
public WeaviateClient getClient() {
4333
if (!isRunning()) {
4434
start();
4535
}
@@ -49,19 +39,8 @@ public WeaviateClient getClient(Function<Config.Custom, ObjectBuilder<Config>> f
4939

5040
synchronized (this) {
5141
if (clientInstance == null) {
52-
var host = getHost();
53-
var customFn = ObjectBuilder.partial(fn,
54-
conn -> conn
55-
.scheme("http")
56-
.httpHost(host)
57-
.grpcHost(host)
58-
.httpPort(getMappedPort(8080))
59-
.grpcPort(getMappedPort(50051)));
60-
var config = customFn.apply(new Config.Custom()).build();
61-
if (config.authentication() != null) {
62-
}
6342
try {
64-
clientInstance = new SharedClient(config, this);
43+
clientInstance = new SharedClient(Config.of(defaultConfigFn()), this);
6544
} catch (Exception e) {
6645
throw new RuntimeException("create WeaviateClient for Weaviate container", e);
6746
}
@@ -75,19 +54,26 @@ public WeaviateClient getClient(Function<Config.Custom, ObjectBuilder<Config>> f
7554
* Prefer using {@link #getClient} unless your test needs the initialization
7655
* steps to run, e.g. OIDC authorization grant exchange.
7756
*/
78-
public WeaviateClient getNewClient(Function<Config.Custom, ObjectBuilder<Config>> fn) {
57+
public WeaviateClient getClient(Function<Config.Custom, ObjectBuilder<Config>> fn) {
7958
if (!isRunning()) {
8059
start();
8160
}
61+
62+
var customFn = ObjectBuilder.partial(fn, defaultConfigFn());
63+
var config = customFn.apply(new Config.Custom()).build();
64+
try {
65+
return new WeaviateClient(config);
66+
} catch (Exception e) {
67+
throw new RuntimeException("create WeaviateClient for Weaviate container", e);
68+
}
69+
}
70+
71+
private Function<Config.Custom, ObjectBuilder<Config>> defaultConfigFn() {
8272
var host = getHost();
83-
var customFn = ObjectBuilder.partial(fn,
84-
conn -> conn
85-
.scheme("http")
86-
.httpHost(host)
87-
.grpcHost(host)
88-
.httpPort(getMappedPort(8080))
89-
.grpcPort(getMappedPort(50051)));
90-
return WeaviateClient.connectToCustom(customFn);
73+
return conn -> conn
74+
.scheme("http")
75+
.httpHost(host).httpPort(getMappedPort(8080))
76+
.grpcHost(host).grpcPort(getMappedPort(50051));
9177
}
9278

9379
public static Weaviate createDefault() {

src/it/java/io/weaviate/integration/OIDCSupportITest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public void test_clientCredentials() throws Exception {
128128

129129
/** Send an HTTP and gRPC requests using a "sync" client. */
130130
private static void pingWeaviate(final Weaviate container, Authentication auth) throws Exception {
131-
try (final var client = container.getNewClient(conn -> conn.authentication(auth))) {
131+
try (final var client = container.getClient(conn -> conn.authentication(auth))) {
132132
// Make an authenticated HTTP call
133133
Assertions.assertThat(client.isLive()).isTrue();
134134

@@ -143,7 +143,7 @@ private static void pingWeaviate(final Weaviate container, Authentication auth)
143143

144144
/** Send an HTTP and gRPC requests using an "async" client. */
145145
private static void pingWeaviateAsync(final Weaviate container, Authentication auth) throws Exception {
146-
try (final var client = container.getNewClient(conn -> conn.authentication(auth))) {
146+
try (final var client = container.getClient(conn -> conn.authentication(auth))) {
147147
try (final var async = client.async()) {
148148
// Make an authenticated HTTP call
149149
Assertions.assertThat(async.isLive().join()).isTrue();

src/it/java/io/weaviate/integration/RbacITest.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class RbacITest extends ConcurrentTest {
4444
/** Name of the viewer role, which exists by default. */
4545
private static final String VIEWER_ROLE = "viewer";
4646

47-
private static final WeaviateClient client = Weaviate.custom()
47+
private static final Weaviate container = Weaviate.custom()
4848
.withAdminUsers(ADMIN_USER)
4949
.withApiKeys(API_KEY)
5050
.withRbac()
@@ -53,7 +53,9 @@ public class RbacITest extends ConcurrentTest {
5353
"https://auth.wcs.api.weaviate.io/auth/realms/SeMI",
5454
"email",
5555
"groups")
56-
.build()
56+
.build();
57+
58+
private static final WeaviateClient client = container
5759
.getClient(fn -> fn.authentication(Authentication.apiKey(API_KEY)));
5860

5961
@Test
@@ -187,7 +189,9 @@ public void test_users_db() throws IOException {
187189
var userId = ns("user");
188190
var roleName = ns("rock-n-role");
189191

190-
client.users.db.create(userId);
192+
var apiKey = client.users.db.create(userId);
193+
assertValidApiKey(apiKey);
194+
191195
client.roles.create(roleName);
192196

193197
client.users.db.assignRoles(userId, roleName);
@@ -207,6 +211,9 @@ public void test_users_db() throws IOException {
207211
.as("user is activated")
208212
.returns(true, DbUser::active);
209213

214+
apiKey = client.users.db.rotateKey(userId);
215+
assertValidApiKey(apiKey);
216+
210217
client.users.db.deactivate(userId);
211218
Assertions.assertThat(client.users.db.byName(userId)).get()
212219
.as("user is deactivated")
@@ -244,4 +251,16 @@ public void test_users_oidc() throws IOException {
244251
.extracting(Role::name)
245252
.doesNotContain(roleName);
246253
}
254+
255+
/**
256+
* Create a new client with API-key authentication
257+
* and check that it can make authenticated requests.
258+
*/
259+
private void assertValidApiKey(String apiKey) {
260+
try (final var c = container.getClient(cfg -> cfg.authentication(Authentication.apiKey(apiKey)))) {
261+
Assertions.assertThatCode(() -> c.isLive()).as("check API key is valid").doesNotThrowAnyException();
262+
} catch (Exception e) {
263+
throw new AssertionError(e);
264+
}
265+
}
247266
}

src/main/java/io/weaviate/client6/v1/api/rbac/users/CreateDbUserRequest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22

33
import java.util.Collections;
44

5+
import io.weaviate.client6.v1.internal.json.JSON;
56
import io.weaviate.client6.v1.internal.rest.Endpoint;
67
import io.weaviate.client6.v1.internal.rest.SimpleEndpoint;
78
import io.weaviate.client6.v1.internal.rest.UrlEncoder;
89

910
public record CreateDbUserRequest(String userId) {
1011

11-
public static final Endpoint<CreateDbUserRequest, Void> _ENDPOINT = SimpleEndpoint.sideEffect(
12+
public static final Endpoint<CreateDbUserRequest, String> _ENDPOINT = SimpleEndpoint.noBody(
1213
__ -> "POST",
1314
request -> "/users/db/" + UrlEncoder.encodeValue(request.userId),
14-
request -> Collections.emptyMap());
15+
request -> Collections.emptyMap(),
16+
(statusCode, response) -> JSON.deserialize(response, CreateDbUserResponse.class).apiKey());
1517
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.weaviate.client6.v1.api.rbac.users;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
5+
public record CreateDbUserResponse(@SerializedName("apikey") String apiKey) {
6+
}

src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClient.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ public DbUsersClient(RestTransport restTransport) {
1919
* Create a new "db" user.
2020
*
2121
* @param userId User ID.
22+
* @return API key for the created user.
2223
* @throws WeaviateApiException in case the server returned with an
2324
* error status code.
2425
* @throws IOException in case the request was not sent successfully
2526
* due to a malformed request, a networking error
2627
* or the server being unavailable.
2728
*/
28-
public void create(String userId) throws IOException {
29-
this.restTransport.performRequest(new CreateDbUserRequest(userId), CreateDbUserRequest._ENDPOINT);
29+
public String create(String userId) throws IOException {
30+
return this.restTransport.performRequest(new CreateDbUserRequest(userId), CreateDbUserRequest._ENDPOINT);
3031
}
3132

3233
/**

src/main/java/io/weaviate/client6/v1/api/rbac/users/DbUsersClientAsync.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ public DbUsersClientAsync(RestTransport restTransport) {
1919
* Create a new "db" user.
2020
*
2121
* @param userId User ID.
22+
* @return API key for the created user.
2223
*/
23-
public CompletableFuture<Void> create(String userId) throws IOException {
24+
public CompletableFuture<String> create(String userId) throws IOException {
2425
return this.restTransport.performRequestAsync(new CreateDbUserRequest(userId), CreateDbUserRequest._ENDPOINT);
2526
}
2627

src/main/java/io/weaviate/client6/v1/api/rbac/users/RotateDbUserKeyResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
import com.google.gson.annotations.SerializedName;
44

5-
public record RotateDbUserKeyResponse(@SerializedName("apiKey") String apiKey) {
5+
public record RotateDbUserKeyResponse(@SerializedName("apikey") String apiKey) {
66
}

0 commit comments

Comments
 (0)