Add CRUD for orgainizations to admin client. (#29540)

Signed-off-by: Stan Silvert <ssilvert@redhat.com>
This commit is contained in:
Stan Silvert 2024-05-15 02:03:41 -04:00 committed by GitHub
parent c4760b8188
commit 6b2ba37e9c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 131 additions and 0 deletions

View file

@ -9,6 +9,7 @@ import { Components } from "./resources/components.js";
import { Groups } from "./resources/groups.js"; import { Groups } from "./resources/groups.js";
import { IdentityProviders } from "./resources/identityProviders.js"; import { IdentityProviders } from "./resources/identityProviders.js";
import { Realms } from "./resources/realms.js"; import { Realms } from "./resources/realms.js";
import { Organizations } from "./resources/organizations.js";
import { Roles } from "./resources/roles.js"; import { Roles } from "./resources/roles.js";
import { ServerInfo } from "./resources/serverInfo.js"; import { ServerInfo } from "./resources/serverInfo.js";
import { Users } from "./resources/users.js"; import { Users } from "./resources/users.js";
@ -34,6 +35,7 @@ export class KeycloakAdminClient {
public userStorageProvider: UserStorageProvider; public userStorageProvider: UserStorageProvider;
public groups: Groups; public groups: Groups;
public roles: Roles; public roles: Roles;
public organizations: Organizations;
public clients: Clients; public clients: Clients;
public realms: Realms; public realms: Realms;
public clientScopes: ClientScopes; public clientScopes: ClientScopes;
@ -68,6 +70,7 @@ export class KeycloakAdminClient {
this.userStorageProvider = new UserStorageProvider(this); this.userStorageProvider = new UserStorageProvider(this);
this.groups = new Groups(this); this.groups = new Groups(this);
this.roles = new Roles(this); this.roles = new Roles(this);
this.organizations = new Organizations(this);
this.clients = new Clients(this); this.clients = new Clients(this);
this.realms = new Realms(this); this.realms = new Realms(this);
this.clientScopes = new ClientScopes(this); this.clientScopes = new ClientScopes(this);

View file

@ -0,0 +1,4 @@
export default interface OrganizationDomainRepresentation {
name?: string;
verified?: boolean;
}

View file

@ -0,0 +1,10 @@
import type OrganizationDomainRepresentation from "./organizationDomainRepresentation.js";
export default interface OrganizationRepresentation {
id?: string;
name?: string;
description?: string;
enabled?: boolean;
attributes?: { [index: string]: string[] };
domains?: OrganizationDomainRepresentation[];
}

View file

@ -0,0 +1,58 @@
import Resource from "./resource.js";
import type OrganizationRepresentation from "../defs/organizationRepresentation.js";
import type { KeycloakAdminClient } from "../client.js";
export interface OrganizationQuery {
first?: number; // The position of the first result to be processed (pagination offset)
max?: number; // The maximum number of results to be returned - defaults to 10
search?: string; // A String representing either an organization name or domain
q?: string; // A query to search for custom attributes, in the format 'key1:value2 key2:value2'
exact?: boolean; // Boolean which defines whether the param 'search' must match exactly or not
}
export class Organizations extends Resource<{ realm?: string }> {
/**
* Organizations
*/
constructor(client: KeycloakAdminClient) {
super(client, {
path: "/admin/realms/{realm}",
getUrlParams: () => ({
realm: client.realmName,
}),
getBaseUrl: () => client.baseUrl,
});
}
public find = this.makeRequest<
OrganizationQuery,
OrganizationRepresentation[]
>({
method: "GET",
path: "/organizations",
});
public create = this.makeRequest<OrganizationRepresentation, { id: string }>({
method: "POST",
path: "/organizations",
returnResourceIdInLocationHeader: { field: "id" },
});
public delById = this.makeRequest<{ id: string }, void>({
method: "DELETE",
path: "/organizations/{id}",
urlParamKeys: ["id"],
});
public updateById = this.makeUpdateRequest<
{ id: string },
OrganizationRepresentation,
void
>({
method: "PUT",
path: "/organizations/{id}",
urlParamKeys: ["id"],
});
}

View file

@ -0,0 +1,56 @@
// tslint:disable:no-unused-expression
import * as chai from "chai";
import { KeycloakAdminClient } from "../src/client.js";
import { credentials } from "./constants.js";
const expect = chai.expect;
describe("Organizations", () => {
let kcAdminClient: KeycloakAdminClient;
before(async () => {
kcAdminClient = new KeycloakAdminClient();
await kcAdminClient.auth(credentials);
});
it("retrieves empty organizations list", async () => {
const organizations = await kcAdminClient.organizations.find();
expect(organizations).to.be.ok;
expect(organizations).to.be.empty;
});
it("creates, updates, and removes an organization", async () => {
const myOrganization = {
name: "orga",
enabled: true,
domains: [
{
name: "orga.com",
},
],
};
const org = await kcAdminClient.organizations.create(myOrganization);
let allOrganizations = await kcAdminClient.organizations.find();
expect(allOrganizations).to.be.ok;
expect(allOrganizations).to.be.not.empty;
myOrganization.enabled = false;
await kcAdminClient.organizations.updateById(
{ id: org.id },
myOrganization,
);
allOrganizations = await kcAdminClient.organizations.find();
expect(allOrganizations).to.be.ok;
expect(allOrganizations.length).to.equal(1);
expect(allOrganizations[0].enabled).to.be.false;
await kcAdminClient.organizations.delById({
id: org.id,
});
allOrganizations = await kcAdminClient.organizations.find();
expect(allOrganizations).to.be.ok;
expect(allOrganizations).to.be.empty;
});
});