Skip to content

Commit 2f0dd7d

Browse files
George-iamgeobon
andauthored
feat: add service-account lifecycle helpers to Java SDK (#4)
Add Java client methods for enterprise service-account create/list/get and key create/revoke operations so scoped machine credentials can be managed via SDK calls. Extend test coverage and document the new admin helper surface. Co-authored-by: George-iam <georgeb@gmail.com>
1 parent 0bacfe5 commit 2f0dd7d

3 files changed

Lines changed: 80 additions & 0 deletions

File tree

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,13 @@ public class Quickstart {
5252
```bash
5353
mvn test
5454
```
55+
56+
## Enterprise Admin APIs
57+
58+
Java SDK now includes service-account lifecycle helpers:
59+
60+
- `createServiceAccount`
61+
- `listServiceAccounts`
62+
- `getServiceAccount`
63+
- `createServiceAccountKey`
64+
- `revokeServiceAccountKey`

src/main/java/dev/axme/sdk/AxmeClient.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,44 @@ public Map<String, Object> updateUserProfile(Map<String, Object> payload, Reques
5858
return requestJson("POST", "/v1/users/profile/update", Map.of(), payload, normalizeOptions(options));
5959
}
6060

61+
public Map<String, Object> createServiceAccount(Map<String, Object> payload, RequestOptions options)
62+
throws IOException, InterruptedException {
63+
return requestJson("POST", "/v1/service-accounts", Map.of(), payload, normalizeOptions(options));
64+
}
65+
66+
public Map<String, Object> listServiceAccounts(String orgId, String workspaceId, RequestOptions options)
67+
throws IOException, InterruptedException {
68+
Map<String, String> query = new LinkedHashMap<>();
69+
query.put("org_id", orgId);
70+
query.put("workspace_id", workspaceId);
71+
return requestJson("GET", "/v1/service-accounts", query, null, normalizeOptions(options));
72+
}
73+
74+
public Map<String, Object> getServiceAccount(String serviceAccountId, RequestOptions options)
75+
throws IOException, InterruptedException {
76+
return requestJson("GET", "/v1/service-accounts/" + serviceAccountId, Map.of(), null, normalizeOptions(options));
77+
}
78+
79+
public Map<String, Object> createServiceAccountKey(String serviceAccountId, Map<String, Object> payload, RequestOptions options)
80+
throws IOException, InterruptedException {
81+
return requestJson(
82+
"POST",
83+
"/v1/service-accounts/" + serviceAccountId + "/keys",
84+
Map.of(),
85+
payload,
86+
normalizeOptions(options));
87+
}
88+
89+
public Map<String, Object> revokeServiceAccountKey(String serviceAccountId, String keyId, RequestOptions options)
90+
throws IOException, InterruptedException {
91+
return requestJson(
92+
"POST",
93+
"/v1/service-accounts/" + serviceAccountId + "/keys/" + keyId + "/revoke",
94+
Map.of(),
95+
null,
96+
normalizeOptions(options));
97+
}
98+
6199
private Map<String, Object> requestJson(
62100
String method,
63101
String path,

src/test/java/dev/axme/sdk/AxmeClientTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,36 @@ void updateUserProfileSendsPayloadAndIdempotency() throws Exception {
110110
assertEquals("profile-1", request.getHeader("Idempotency-Key"));
111111
assertEquals("Partner User Updated", response.get("display_name"));
112112
}
113+
114+
@Test
115+
void serviceAccountLifecycleEndpointsAreReachable() throws Exception {
116+
server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"service_account\":{\"service_account_id\":\"sa_123\"}}"));
117+
server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"service_accounts\":[{\"service_account_id\":\"sa_123\"}]}"));
118+
server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"service_account\":{\"service_account_id\":\"sa_123\"}}"));
119+
server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"key\":{\"key_id\":\"sak_123\",\"status\":\"active\"}}"));
120+
server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"ok\":true,\"key\":{\"key_id\":\"sak_123\",\"status\":\"revoked\"}}"));
121+
122+
client.createServiceAccount(
123+
Map.of(
124+
"org_id", "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
125+
"workspace_id", "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
126+
"name", "sdk-runner",
127+
"created_by_actor_id", "actor_java"),
128+
new RequestOptions("sa-create-1", null));
129+
client.listServiceAccounts(
130+
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
131+
"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
132+
RequestOptions.none());
133+
client.getServiceAccount("sa_123", RequestOptions.none());
134+
client.createServiceAccountKey("sa_123", Map.of("created_by_actor_id", "actor_java"), RequestOptions.none());
135+
client.revokeServiceAccountKey("sa_123", "sak_123", RequestOptions.none());
136+
137+
assertEquals("/v1/service-accounts", server.takeRequest().getPath());
138+
assertEquals(
139+
"/v1/service-accounts?org_id=aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa&workspace_id=bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
140+
server.takeRequest().getPath());
141+
assertEquals("/v1/service-accounts/sa_123", server.takeRequest().getPath());
142+
assertEquals("/v1/service-accounts/sa_123/keys", server.takeRequest().getPath());
143+
assertEquals("/v1/service-accounts/sa_123/keys/sak_123/revoke", server.takeRequest().getPath());
144+
}
113145
}

0 commit comments

Comments
 (0)