Skip to content

Commit db6d6bd

Browse files
committed
feat: add integration test using preshared key
1 parent b961487 commit db6d6bd

1 file changed

Lines changed: 140 additions & 0 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package dev.openfga.sdk.api.client;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import dev.openfga.sdk.api.client.model.ClientListObjectsRequest;
7+
import dev.openfga.sdk.api.client.model.ClientTupleKey;
8+
import dev.openfga.sdk.api.client.model.ClientWriteRequest;
9+
import dev.openfga.sdk.api.configuration.ApiToken;
10+
import dev.openfga.sdk.api.configuration.ClientConfiguration;
11+
import dev.openfga.sdk.api.configuration.Credentials;
12+
import dev.openfga.sdk.api.model.*;
13+
import java.io.IOException;
14+
import java.nio.file.Files;
15+
import java.nio.file.Paths;
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.concurrent.CompletableFuture;
19+
import org.junit.jupiter.api.BeforeAll;
20+
import org.junit.jupiter.api.Test;
21+
import org.junit.jupiter.api.TestInstance;
22+
import org.junit.jupiter.api.TestInstance.Lifecycle;
23+
import org.testcontainers.junit.jupiter.Container;
24+
import org.testcontainers.junit.jupiter.Testcontainers;
25+
import org.testcontainers.openfga.OpenFGAContainer;
26+
27+
/**
28+
* Integration tests verifying that streaming and executor code paths attach
29+
* the Authorization header when credentials are configured.
30+
*
31+
* Uses an OpenFGA container with pre-shared key auth enabled — any request
32+
* missing a valid Authorization header gets a 401.
33+
*/
34+
@TestInstance(Lifecycle.PER_CLASS)
35+
@Testcontainers
36+
public class StreamedListObjectsAuthIntegrationTest {
37+
38+
private static final String PRESHARED_KEY = "integration-test-secret";
39+
40+
@Container
41+
private static final OpenFGAContainer openfga = new OpenFGAContainer("openfga/openfga:v1.10.2")
42+
.withCommand("run", "--authn-method=preshared", "--authn-preshared-keys=" + PRESHARED_KEY);
43+
44+
private static final ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
45+
46+
private OpenFgaClient fga;
47+
48+
@BeforeAll
49+
public void setup() throws Exception {
50+
ClientConfiguration config = new ClientConfiguration()
51+
.apiUrl(openfga.getHttpEndpoint())
52+
.credentials(new Credentials(new ApiToken(PRESHARED_KEY)));
53+
54+
fga = new OpenFgaClient(config);
55+
56+
// Create store
57+
var storeResponse =
58+
fga.createStore(new CreateStoreRequest().name("auth-integration-test")).get();
59+
fga.setStoreId(storeResponse.getId());
60+
61+
// Write authorization model
62+
String authModelJson =
63+
Files.readString(Paths.get("src", "test-integration", "resources", "auth-model.json"));
64+
var authModelRequest = mapper.readValue(authModelJson, WriteAuthorizationModelRequest.class);
65+
var modelResponse = fga.writeAuthorizationModel(authModelRequest).get();
66+
fga.setAuthorizationModelId(modelResponse.getAuthorizationModelId());
67+
68+
// Write tuples
69+
var tuples = List.of(
70+
new ClientTupleKey().user("user:alice").relation("reader")._object("document:doc1"),
71+
new ClientTupleKey().user("user:alice").relation("reader")._object("document:doc2"),
72+
new ClientTupleKey().user("user:alice").relation("reader")._object("document:doc3"));
73+
fga.write(new ClientWriteRequest().writes(tuples)).get();
74+
}
75+
76+
@Test
77+
public void listObjects_succeeds_withAuth() throws Exception {
78+
// Baseline — non-streaming always worked
79+
var response = fga.listObjects(new ClientListObjectsRequest()
80+
.user("user:alice")
81+
.relation("reader")
82+
.type("document"))
83+
.get();
84+
85+
assertEquals(3, response.getObjects().size());
86+
}
87+
88+
@Test
89+
public void streamedListObjects_succeeds_withAuth() throws Exception {
90+
// The reported bug — would get 401 without the fix
91+
List<StreamedListObjectsResponse> received = new ArrayList<>();
92+
93+
fga.streamedListObjects(
94+
new ClientListObjectsRequest()
95+
.user("user:alice")
96+
.relation("reader")
97+
.type("document"),
98+
received::add)
99+
.get();
100+
101+
assertEquals(3, received.size());
102+
}
103+
104+
@Test
105+
public void streamingApiExecutor_succeeds_withAuth() throws Exception {
106+
List<StreamedListObjectsResponse> received = new ArrayList<>();
107+
108+
ApiExecutorRequestBuilder request =
109+
ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/streamed-list-objects")
110+
.body(new ListObjectsRequest()
111+
.user("user:alice")
112+
.relation("reader")
113+
.type("document"))
114+
.build();
115+
116+
fga.streamingApiExecutor(StreamedListObjectsResponse.class)
117+
.stream(request, received::add)
118+
.get();
119+
120+
assertEquals(3, received.size());
121+
}
122+
123+
@Test
124+
public void apiExecutor_succeeds_withAuth() throws Exception {
125+
ApiExecutorRequestBuilder request =
126+
ApiExecutorRequestBuilder.builder(HttpMethod.POST, "/stores/{store_id}/list-objects")
127+
.body(new ListObjectsRequest()
128+
.user("user:alice")
129+
.relation("reader")
130+
.type("document"))
131+
.build();
132+
133+
ApiResponse<ListObjectsResponse> response =
134+
fga.apiExecutor().send(request, ListObjectsResponse.class).get();
135+
136+
assertEquals(200, response.getStatusCode());
137+
assertEquals(3, response.getData().getObjects().size());
138+
}
139+
}
140+

0 commit comments

Comments
 (0)