Skip to content

Commit af35f86

Browse files
committed
Add bulk creation and deletion methods
Signed-off-by: Dominika Zemanovicova <dzemanov@redhat.com>
1 parent a780243 commit af35f86

6 files changed

Lines changed: 173 additions & 37 deletions

File tree

docs/api/deployment/keycloak-helper.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,6 @@ async deploy(): Promise<void>
7878

7979
Deploy Keycloak using Bitnami Helm chart.
8080

81-
### `deployAndConfigureForRHDH()`
82-
83-
```typescript
84-
async deployAndConfigureForRHDH(options?: object): Promise<void>
85-
```
86-
87-
Deploy Keycloak and then configure it for RHDH (realm + client + groups + users).
88-
8981
### `configureForRHDH()`
9082

9183
```typescript
@@ -110,6 +102,22 @@ async connect(config: KeycloakConnectionConfig): Promise<void>
110102

111103
Connect to an existing Keycloak instance.
112104

105+
### `createUsersAndGroups()`
106+
107+
```typescript
108+
async createUsersAndGroups(realm: string, options?: { users?: KeycloakUserConfig[]; groups?: KeycloakGroupConfig[]; }): Promise<void>
109+
```
110+
111+
Create new users and groups in a realm.
112+
113+
### `deleteUsersAndGroups()`
114+
115+
```typescript
116+
async deleteUsersAndGroups(realm: string, options?: { users?: Array<KeycloakUserConfig | string>; groups?: Array<KeycloakGroupConfig | string> }): Promise<void>
117+
```
118+
119+
Delete users and groups from a realm.
120+
113121
### `createRealm()`
114122

115123
```typescript

docs/guide/deployment/authentication.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,18 @@ No additional environment variables required.
152152

153153
### Keycloak Auth
154154

155-
These are automatically set by `KeycloakHelper.configureForRHDH()`:
156-
157-
| Variable | Description |
158-
|----------|-------------|
159-
| `KEYCLOAK_BASE_URL` | Keycloak instance URL |
160-
| `KEYCLOAK_REALM` | Realm name |
161-
| `KEYCLOAK_CLIENT_ID` | OIDC client ID |
162-
| `KEYCLOAK_CLIENT_SECRET` | OIDC client secret |
163-
| `KEYCLOAK_METADATA_URL` | OIDC discovery URL |
164-
| `KEYCLOAK_LOGIN_REALM` | Login realm name |
155+
These are automatically set by `KeycloakHelper.configureForRHDH()` or populated from global workspace in the vault:
156+
157+
| Variable | Description |
158+
| ------------------------------- | --------------------- |
159+
| `KEYCLOAK_BASE_URL` | Keycloak instance URL |
160+
| `KEYCLOAK_REALM` | Realm name |
161+
| `KEYCLOAK_CLIENT_ID` | OIDC client ID |
162+
| `KEYCLOAK_CLIENT_SECRET` | OIDC client secret |
163+
| `KEYCLOAK_METADATA_URL` | OIDC discovery URL |
164+
| `KEYCLOAK_LOGIN_REALM` | Login realm name |
165+
| `VAULT_KEYCLOAK_ADMIN_USERNAME` | Admin username |
166+
| `VAULT_KEYCLOAK_ADMIN_PASSWORD` | Admin password |
165167

166168
### GitHub Auth
167169

docs/guide/deployment/keycloak-deployment.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ await keycloak.configureForRHDH({
9292
clientId: "my-client",
9393
clientSecret: "my-secret",
9494
},
95-
groups: ["developers", "admins"],
95+
groups: [{ name: "developers" }, { name: "admins" }],
9696
users: [
9797
{ username: "user1", password: "pass1", groups: ["developers"] },
9898
{ username: "user2", password: "pass2", groups: ["admins"] },
@@ -156,6 +156,18 @@ const users = await keycloak.getUsers("rhdh");
156156

157157
// Delete user
158158
await keycloak.deleteUser("rhdh", "username");
159+
160+
// Create multiple users
161+
await keycloak.createUsersAndGroups("rhdh", {
162+
users: [
163+
{ username: "user1", password: "pass1" },
164+
{ username: "user2", password: "pass2", groups: ["developers"] },
165+
],
166+
});
167+
168+
// Delete multiple users - by objects or by usernames
169+
await keycloak.deleteUsersAndGroups("rhdh", { users });
170+
await keycloak.deleteUsersAndGroups("rhdh", { users: ["user1", "user2"] });
159171
```
160172

161173
### Group Management
@@ -169,6 +181,15 @@ const groups = await keycloak.getGroups("rhdh");
169181

170182
// Delete group
171183
await keycloak.deleteGroup("rhdh", "testers");
184+
185+
// Create multiple groups
186+
await keycloak.createUsersAndGroups("rhdh", {
187+
groups: [{ name: "admins" }, { name: "viewers" }],
188+
});
189+
190+
// Delete multiple groups - by objects or by group names
191+
await keycloak.deleteUsersAndGroups("rhdh", { groups });
192+
await keycloak.deleteUsersAndGroups("rhdh", { groups: ["admins", "viewers"] });
172193
```
173194

174195
### Using getUsers and getGroupsOfUser in tests

docs/tutorials/keycloak-oidc-testing.md

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ test.beforeAll(async ({ rhdh }) => {
6666
// Connect to existing Keycloak
6767
await keycloak.connect({
6868
baseUrl: process.env.KEYCLOAK_BASE_URL!,
69-
username: "admin",
70-
password: "admin123",
69+
username: process.env.VAULT_KEYCLOAK_ADMIN_USERNAME!,
70+
password: process.env.VAULT_KEYCLOAK_ADMIN_PASSWORD!,
7171
});
7272

7373
// Create admin user
@@ -90,6 +90,56 @@ test.beforeAll(async ({ rhdh }) => {
9090
});
9191
```
9292

93+
## Creating Custom Users and Groups in Bulk
94+
95+
```typescript
96+
import { KeycloakHelper } from "@red-hat-developer-hub/e2e-test-utils/keycloak";
97+
import type {
98+
KeycloakGroupConfig,
99+
KeycloakUserConfig,
100+
} from "@red-hat-developer-hub/e2e-test-utils/keycloak";
101+
102+
const TEST_GROUPS: KeycloakGroupConfig[] = [
103+
{ name: "writers" },
104+
{ name: "readers" },
105+
];
106+
107+
const TEST_USERS: Record<string, KeycloakUserConfig> = {
108+
reader: {
109+
username: "catalog-reader",
110+
password: crypto.randomUUID().substring(0, 21).replaceAll("-", "0"),
111+
groups: ["readers"],
112+
},
113+
writer: {
114+
username: "catalog-writer",
115+
password: crypto.randomUUID().substring(0, 21).replaceAll("-", "0"),
116+
groups: ["writers"],
117+
},
118+
};
119+
120+
test.beforeAll(async ({ rhdh }) => {
121+
const keycloak = new KeycloakHelper();
122+
await keycloak.connect({
123+
baseUrl: process.env.KEYCLOAK_BASE_URL!,
124+
username: process.env.VAULT_KEYCLOAK_ADMIN_USERNAME!,
125+
password: process.env.VAULT_KEYCLOAK_ADMIN_PASSWORD!,
126+
});
127+
await keycloak.createUsersAndGroups(process.env.KEYCLOAK_REALM!, {
128+
users: Object.values(TEST_USERS),
129+
groups: TEST_GROUPS,
130+
});
131+
132+
await rhdh.configure({ auth: "keycloak" });
133+
await rhdh.deploy();
134+
});
135+
136+
test.describe("Writer access", () => {
137+
test.beforeEach(async ({ page, loginHelper }) => {
138+
await page.goto("/");
139+
await loginHelper.loginAsKeycloakUser(TEST_USERS.writer.username, TEST_USERS.writer.password);
140+
});
141+
```
142+
93143
## Testing Role-Based Access
94144
95145
```typescript
@@ -160,8 +210,8 @@ test.afterAll(async () => {
160210
const keycloak = new KeycloakHelper();
161211
await keycloak.connect({
162212
baseUrl: process.env.KEYCLOAK_BASE_URL!,
163-
username: "admin",
164-
password: "admin123",
213+
username: process.env.VAULT_KEYCLOAK_ADMIN_USERNAME!,
214+
password: process.env.VAULT_KEYCLOAK_ADMIN_PASSWORD!,
165215
});
166216

167217
// Cleanup custom users
@@ -170,6 +220,27 @@ test.afterAll(async () => {
170220
});
171221
```
172222
223+
## Cleanup in Bulk
224+
225+
```typescript
226+
import { KeycloakHelper } from "@red-hat-developer-hub/e2e-test-utils/keycloak";
227+
228+
test.afterAll(async () => {
229+
const keycloak = new KeycloakHelper();
230+
await keycloak.connect({
231+
baseUrl: process.env.KEYCLOAK_BASE_URL!,
232+
username: process.env.VAULT_KEYCLOAK_ADMIN_USERNAME!,
233+
password: process.env.VAULT_KEYCLOAK_ADMIN_PASSWORD!,
234+
});
235+
236+
// Cleanup custom users and groups
237+
await keycloak.deleteUsersAndGroups("rhdh", {
238+
users: TEST_USERS,
239+
groups: TEST_GROUPS,
240+
});
241+
});
242+
```
243+
173244
## Best Practices
174245
175246
1. **Use default users for simple tests** - `test1`, `test2`

src/deployment/keycloak/deployment.ts

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,6 @@ export class KeycloakHelper {
5050
await this._initializeAdminClient();
5151
}
5252

53-
/**
54-
* Deploy Keycloak configured with realm, client, groups and users for RHDH
55-
*/
56-
async deployAndConfigure(options?: {
57-
realm?: string;
58-
client?: Partial<KeycloakClientConfig>;
59-
groups?: KeycloakGroupConfig[];
60-
users?: KeycloakUserConfig[];
61-
}): Promise<void> {
62-
await this.deploy();
63-
await this.configureForRHDH(options);
64-
}
65-
6653
/**
6754
* Check if Keycloak is already running
6855
*/
@@ -285,6 +272,28 @@ export class KeycloakHelper {
285272
}
286273
}
287274

275+
/**
276+
* Create users and groups in a realm.
277+
*/
278+
async createUsersAndGroups(
279+
realm: string,
280+
options: {
281+
users?: KeycloakUserConfig[];
282+
groups?: KeycloakGroupConfig[];
283+
},
284+
): Promise<void> {
285+
await this._ensureAdminClient();
286+
const { groups = [], users = [] } = options;
287+
288+
for (const group of groups) {
289+
await this.createGroup(realm, group);
290+
}
291+
292+
for (const user of users) {
293+
await this.createUser(realm, user);
294+
}
295+
}
296+
288297
/**
289298
* Get all users in a realm
290299
*/
@@ -364,6 +373,31 @@ export class KeycloakHelper {
364373
}
365374
}
366375

376+
/**
377+
* Delete users and groups from a realm.
378+
*/
379+
async deleteUsersAndGroups(
380+
realm: string,
381+
options: {
382+
users?: Array<KeycloakUserConfig | string>;
383+
groups?: Array<KeycloakGroupConfig | string>;
384+
},
385+
): Promise<void> {
386+
await this._ensureAdminClient();
387+
const { groups = [], users = [] } = options;
388+
389+
const usernames = users.map((u) => (typeof u === "string" ? u : u.username));
390+
const groupNames = groups.map((g) => (typeof g === "string" ? g : g.name));
391+
392+
for (const username of usernames) {
393+
await this.deleteUser(realm, username);
394+
}
395+
396+
for (const groupName of groupNames) {
397+
await this.deleteGroup(realm, groupName);
398+
}
399+
}
400+
367401
/**
368402
* Delete a realm
369403
*/

src/deployment/keycloak/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { KeycloakHelper } from "./deployment.js";
2-
export type { KeycloakUserConfig, KeycloakGroupConfig } from "./types.js";
2+
export type * from "./types.js";

0 commit comments

Comments
 (0)