From 32de22a08197484b602580d9200fd9fe31b6b499 Mon Sep 17 00:00:00 2001 From: Pedro Igor Date: Wed, 13 Mar 2024 18:54:23 -0300 Subject: [PATCH] Introducing the extensions/organization Signed-off-by: Pedro Igor --- extensions/organization/pom.xml | 55 ++++++++++++ .../OrganizationRepresentation.java | 40 +++++++++ .../resource/OrganizationAdminResource.java | 68 +++++++++++++++ .../OrganizationAdminResourceFactory.java | 54 ++++++++++++ .../OrganizationAdminResourceProvider.java | 37 ++++++++ .../src/main/resources/META-INF/beans.xml | 0 ...dmin.ext.AdminRealmResourceProviderFactory | 19 ++++ .../src/test/java/KeycloakTest.java | 27 ++++++ .../OrganizationAdminRestApiTest.java | 87 +++++++++++++++++++ .../resource/OrganizationTestProvider.java | 42 +++++++++ ...dmin.ext.AdminRealmResourceProviderFactory | 19 ++++ extensions/pom.xml | 37 ++++++++ pom.xml | 12 +++ 13 files changed, 497 insertions(+) create mode 100755 extensions/organization/pom.xml create mode 100644 extensions/organization/src/main/java/org/keycloak/organization/OrganizationRepresentation.java create mode 100644 extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResource.java create mode 100644 extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceFactory.java create mode 100644 extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceProvider.java create mode 100644 extensions/organization/src/main/resources/META-INF/beans.xml create mode 100644 extensions/organization/src/main/resources/META-INF/services/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory create mode 100644 extensions/organization/src/test/java/KeycloakTest.java create mode 100644 extensions/organization/src/test/java/org/keycloak/organization/OrganizationAdminRestApiTest.java create mode 100644 extensions/organization/src/test/java/org/keycloak/organization/admin/resource/OrganizationTestProvider.java create mode 100644 extensions/organization/src/test/resources/org/keycloak/organization/admin/resource/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory create mode 100755 extensions/pom.xml diff --git a/extensions/organization/pom.xml b/extensions/organization/pom.xml new file mode 100755 index 000000000000..999a5e81777c --- /dev/null +++ b/extensions/organization/pom.xml @@ -0,0 +1,55 @@ + + + + + keycloak-parent + org.keycloak + 999.0.0-SNAPSHOT + ../pom.xml + + + Keycloak Organization Extension + 4.0.0 + + keycloak-organization + jar + + + + org.keycloak + keycloak-services + + + org.keycloak + keycloak-junit5 + + + + + io.rest-assured + rest-assured + test + + + org.keycloak + keycloak-admin-client + test + + + diff --git a/extensions/organization/src/main/java/org/keycloak/organization/OrganizationRepresentation.java b/extensions/organization/src/main/java/org/keycloak/organization/OrganizationRepresentation.java new file mode 100644 index 000000000000..b18aa370f2bb --- /dev/null +++ b/extensions/organization/src/main/java/org/keycloak/organization/OrganizationRepresentation.java @@ -0,0 +1,40 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.organization; + +public class OrganizationRepresentation { + + private String name; + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResource.java b/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResource.java new file mode 100644 index 000000000000..64741d24daf3 --- /dev/null +++ b/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResource.java @@ -0,0 +1,68 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.organization.admin.resource; + +import java.util.stream.Stream; + +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.Status; +import org.keycloak.organization.OrganizationRepresentation; +import org.keycloak.utils.StringUtil; + +@Path("/") +public class OrganizationAdminResource { + + public OrganizationAdminResource() {} + + @POST + @Consumes(MediaType.APPLICATION_JSON) + public Response create(OrganizationRepresentation organizaiton) { + return Response.status(Status.CREATED).build(); + } + + @Path("{id}") + @DELETE + @Consumes(MediaType.APPLICATION_JSON) + public Response delete(@PathParam("id") String id) { + if (StringUtil.isBlank(id)) { + throw new BadRequestException(); + } + return Response.noContent().build(); + } + + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Stream get(@PathParam("id") String id) { + OrganizationRepresentation organization = new OrganizationRepresentation(); + + organization.setId("1"); + organization.setName("acme"); + + return Stream.of(organization); + } +} diff --git a/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceFactory.java b/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceFactory.java new file mode 100644 index 000000000000..69f66209a587 --- /dev/null +++ b/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceFactory.java @@ -0,0 +1,54 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.organization.admin.resource; + +import org.keycloak.Config.Scope; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.services.resources.admin.ext.AdminRealmResourceProvider; +import org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory; + +public class OrganizationAdminResourceFactory implements AdminRealmResourceProviderFactory { + + private OrganizationAdminResourceProvider PROVIDER_INSTANCE; + + @Override + public AdminRealmResourceProvider create(KeycloakSession session) { + return PROVIDER_INSTANCE; + } + + @Override + public void init(Scope config) { + + } + + @Override + public void postInit(KeycloakSessionFactory factory) { + PROVIDER_INSTANCE = new OrganizationAdminResourceProvider(); + } + + @Override + public void close() { + + } + + @Override + public String getId() { + return "organization"; + } +} diff --git a/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceProvider.java b/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceProvider.java new file mode 100644 index 000000000000..eb0358b627fb --- /dev/null +++ b/extensions/organization/src/main/java/org/keycloak/organization/admin/resource/OrganizationAdminResourceProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.organization.admin.resource; + +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.RealmModel; +import org.keycloak.services.resources.admin.AdminEventBuilder; +import org.keycloak.services.resources.admin.ext.AdminRealmResourceProvider; +import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; + +public class OrganizationAdminResourceProvider implements AdminRealmResourceProvider { + + @Override + public Object getResource(KeycloakSession session, RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) { + return new OrganizationAdminResource(); + } + + @Override + public void close() { + + } +} diff --git a/extensions/organization/src/main/resources/META-INF/beans.xml b/extensions/organization/src/main/resources/META-INF/beans.xml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/extensions/organization/src/main/resources/META-INF/services/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory b/extensions/organization/src/main/resources/META-INF/services/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory new file mode 100644 index 000000000000..c79290221fcf --- /dev/null +++ b/extensions/organization/src/main/resources/META-INF/services/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory @@ -0,0 +1,19 @@ +# +# /* +# * Copyright 2024 Red Hat, Inc. and/or its affiliates +# * and other contributors as indicated by the @author tags. +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# */ +# +org.keycloak.organization.admin.resource.OrganizationAdminResourceFactory \ No newline at end of file diff --git a/extensions/organization/src/test/java/KeycloakTest.java b/extensions/organization/src/test/java/KeycloakTest.java new file mode 100644 index 000000000000..cd7b2bad20ae --- /dev/null +++ b/extensions/organization/src/test/java/KeycloakTest.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.keycloak.Keycloak; + +public class KeycloakTest { + + public static void main(String[] args) { + Keycloak.builder() + .addDependency("org.keycloak", "keycloak-organization", "999.0.0-SNAPSHOT") + .start(args); + } +} diff --git a/extensions/organization/src/test/java/org/keycloak/organization/OrganizationAdminRestApiTest.java b/extensions/organization/src/test/java/org/keycloak/organization/OrganizationAdminRestApiTest.java new file mode 100644 index 000000000000..42eb72fa4397 --- /dev/null +++ b/extensions/organization/src/test/java/org/keycloak/organization/OrganizationAdminRestApiTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.organization; + +import java.util.List; + +import io.restassured.RestAssured; +import io.restassured.common.mapper.TypeRef; +import io.restassured.specification.RequestSpecification; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response.Status; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.keycloak.admin.client.Keycloak; + +public class OrganizationAdminRestApiTest { + + private static final TypeRef> ORGANIZATION_LIST_TYPE_DEF = new TypeRef>() {}; + private static final String BASE_SERVER_URL = "http://localhost:8180"; + + private Keycloak kcClient; + private String accessToken; + private RequestSpecification restAssured; + + @BeforeEach + public void onBefore() { + kcClient = Keycloak.getInstance(BASE_SERVER_URL, "master", "admin", "admin", "admin-cli"); + accessToken = kcClient.tokenManager().getAccessTokenString(); + restAssured = RestAssured.given().auth().oauth2(accessToken); + } + + @AfterEach + public void onAfter() { + if (kcClient != null) { + kcClient.close(); + } + } + + @Test + public void testCreate() { + OrganizationRepresentation org = new OrganizationRepresentation(); + + org.setName("acme"); + + restAssured.body(org) + .contentType(MediaType.APPLICATION_JSON) + .post(BASE_SERVER_URL.concat("/admin/realms/master/organization")) + .then() + .statusCode(Status.CREATED.getStatusCode()); + } + + @Test + public void testDelete() { + OrganizationRepresentation org = new OrganizationRepresentation(); + + org.setId("1"); + + restAssured.delete(BASE_SERVER_URL.concat("/admin/realms/master/organization/{id}"), org.getId()) + .then() + .statusCode(Status.NO_CONTENT.getStatusCode()); + } + + @Test + public void testGet() { + List organizations = restAssured + .get(BASE_SERVER_URL.concat("/admin/realms/master/organization")) + .as(ORGANIZATION_LIST_TYPE_DEF); + Assertions.assertFalse(organizations.isEmpty()); + } +} diff --git a/extensions/organization/src/test/java/org/keycloak/organization/admin/resource/OrganizationTestProvider.java b/extensions/organization/src/test/java/org/keycloak/organization/admin/resource/OrganizationTestProvider.java new file mode 100644 index 000000000000..f62367e3532d --- /dev/null +++ b/extensions/organization/src/test/java/org/keycloak/organization/admin/resource/OrganizationTestProvider.java @@ -0,0 +1,42 @@ +/* + * Copyright 2024 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.organization.admin.resource; + +import java.util.Collections; +import java.util.Map; + +import org.keycloak.it.TestProvider; +import org.keycloak.organization.OrganizationRepresentation; + +public class OrganizationTestProvider implements TestProvider { + + @Override + public Class[] getClasses() { + return new Class[] { + OrganizationAdminResource.class, + OrganizationRepresentation.class, + OrganizationAdminResourceProvider.class, + OrganizationAdminResourceFactory.class + }; + } + + @Override + public Map getManifestResources() { + return Collections.singletonMap("org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory", "services/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory"); + } +} diff --git a/extensions/organization/src/test/resources/org/keycloak/organization/admin/resource/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory b/extensions/organization/src/test/resources/org/keycloak/organization/admin/resource/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory new file mode 100644 index 000000000000..c79290221fcf --- /dev/null +++ b/extensions/organization/src/test/resources/org/keycloak/organization/admin/resource/org.keycloak.services.resources.admin.ext.AdminRealmResourceProviderFactory @@ -0,0 +1,19 @@ +# +# /* +# * Copyright 2024 Red Hat, Inc. and/or its affiliates +# * and other contributors as indicated by the @author tags. +# * +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# */ +# +org.keycloak.organization.admin.resource.OrganizationAdminResourceFactory \ No newline at end of file diff --git a/extensions/pom.xml b/extensions/pom.xml new file mode 100755 index 000000000000..89e1f8ab6478 --- /dev/null +++ b/extensions/pom.xml @@ -0,0 +1,37 @@ + + + + + keycloak-parent + org.keycloak + 999.0.0-SNAPSHOT + ../pom.xml + + + Keycloak Extension Parent + + 4.0.0 + + keycloak-extension-parent + pom + + + organization + + diff --git a/pom.xml b/pom.xml index 42945c7691a9..b15b608d948d 100644 --- a/pom.xml +++ b/pom.xml @@ -2080,5 +2080,17 @@ + + extensions + + + extensions + + + + extensions + + +