diff --git a/README.md b/README.md index 5a1451a..d9e64a8 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,13 @@ public class Quickstart { ```bash mvn test ``` + +## Enterprise Admin APIs + +Java SDK now includes service-account lifecycle helpers: + +- `createServiceAccount` +- `listServiceAccounts` +- `getServiceAccount` +- `createServiceAccountKey` +- `revokeServiceAccountKey` diff --git a/src/main/java/dev/axme/sdk/AxmeClient.java b/src/main/java/dev/axme/sdk/AxmeClient.java index 2840291..1d2a1df 100644 --- a/src/main/java/dev/axme/sdk/AxmeClient.java +++ b/src/main/java/dev/axme/sdk/AxmeClient.java @@ -58,6 +58,44 @@ public Map updateUserProfile(Map payload, Reques return requestJson("POST", "/v1/users/profile/update", Map.of(), payload, normalizeOptions(options)); } + public Map createServiceAccount(Map payload, RequestOptions options) + throws IOException, InterruptedException { + return requestJson("POST", "/v1/service-accounts", Map.of(), payload, normalizeOptions(options)); + } + + public Map listServiceAccounts(String orgId, String workspaceId, RequestOptions options) + throws IOException, InterruptedException { + Map query = new LinkedHashMap<>(); + query.put("org_id", orgId); + query.put("workspace_id", workspaceId); + return requestJson("GET", "/v1/service-accounts", query, null, normalizeOptions(options)); + } + + public Map getServiceAccount(String serviceAccountId, RequestOptions options) + throws IOException, InterruptedException { + return requestJson("GET", "/v1/service-accounts/" + serviceAccountId, Map.of(), null, normalizeOptions(options)); + } + + public Map createServiceAccountKey(String serviceAccountId, Map payload, RequestOptions options) + throws IOException, InterruptedException { + return requestJson( + "POST", + "/v1/service-accounts/" + serviceAccountId + "/keys", + Map.of(), + payload, + normalizeOptions(options)); + } + + public Map revokeServiceAccountKey(String serviceAccountId, String keyId, RequestOptions options) + throws IOException, InterruptedException { + return requestJson( + "POST", + "/v1/service-accounts/" + serviceAccountId + "/keys/" + keyId + "/revoke", + Map.of(), + null, + normalizeOptions(options)); + } + private Map requestJson( String method, String path, diff --git a/src/test/java/dev/axme/sdk/AxmeClientTest.java b/src/test/java/dev/axme/sdk/AxmeClientTest.java index 62169d9..83dd824 100644 --- a/src/test/java/dev/axme/sdk/AxmeClientTest.java +++ b/src/test/java/dev/axme/sdk/AxmeClientTest.java @@ -110,4 +110,36 @@ void updateUserProfileSendsPayloadAndIdempotency() throws Exception { assertEquals("profile-1", request.getHeader("Idempotency-Key")); assertEquals("Partner User Updated", response.get("display_name")); } + + @Test + void serviceAccountLifecycleEndpointsAreReachable() throws Exception { + server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"service_account\":{\"service_account_id\":\"sa_123\"}}")); + server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"service_accounts\":[{\"service_account_id\":\"sa_123\"}]}")); + server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"service_account\":{\"service_account_id\":\"sa_123\"}}")); + server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"key\":{\"key_id\":\"sak_123\",\"status\":\"active\"}}")); + server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"key\":{\"key_id\":\"sak_123\",\"status\":\"revoked\"}}")); + + client.createServiceAccount( + Map.of( + "org_id", "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", + "workspace_id", "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", + "name", "sdk-runner", + "created_by_actor_id", "actor_java"), + new RequestOptions("sa-create-1", null)); + client.listServiceAccounts( + "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", + "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", + RequestOptions.none()); + client.getServiceAccount("sa_123", RequestOptions.none()); + client.createServiceAccountKey("sa_123", Map.of("created_by_actor_id", "actor_java"), RequestOptions.none()); + client.revokeServiceAccountKey("sa_123", "sak_123", RequestOptions.none()); + + assertEquals("/v1/service-accounts", server.takeRequest().getPath()); + assertEquals( + "/v1/service-accounts?org_id=aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa&workspace_id=bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", + server.takeRequest().getPath()); + assertEquals("/v1/service-accounts/sa_123", server.takeRequest().getPath()); + assertEquals("/v1/service-accounts/sa_123/keys", server.takeRequest().getPath()); + assertEquals("/v1/service-accounts/sa_123/keys/sak_123/revoke", server.takeRequest().getPath()); + } }