From ce78cc1d1c753c0d5c84e427ae0ead185eb8c221 Mon Sep 17 00:00:00 2001 From: Pedro Igor Date: Wed, 31 Aug 2016 21:04:36 -0300 Subject: [PATCH] [KEYCLOAK-3472] - Multiple paths with the same name and tests --- .../authorization/AbstractPolicyEnforcer.java | 3 +- .../authorization/PolicyEnforcer.java | 26 ++++++-- .../authz/photoz/photoz-restful-api/pom.xml | 6 ++ .../photoz/admin/AdminAlbumService.java | 6 +- .../example/photoz/album/AlbumService.java | 6 +- .../example/photoz/album/ProfileService.java | 4 +- .../example/photoz/util/Resources.java | 51 ++++++++++++++++ .../example/photoz/util/Transaction.java | 34 +++++++++++ .../photoz/util/TransactionInterceptor.java | 56 ++++++++++++++++++ .../src/main/resources/META-INF/beans.xml | 4 +- .../main/resources/META-INF/persistence.xml | 10 +++- .../META-INF/jboss-deployment-structure.xml | 1 + .../src/main/webapp/WEB-INF/photoz-ds.xml | 12 ---- .../photoz/photoz-restful-api/pom.xml | 6 ++ .../photoz/admin/AdminAlbumService.java | 6 +- .../example/photoz/album/AlbumService.java | 6 +- .../example/photoz/album/ProfileService.java | 4 +- .../example/photoz/util/Resources.java | 51 ++++++++++++++++ .../example/photoz/util/Transaction.java | 34 +++++++++++ .../photoz/util/TransactionInterceptor.java | 56 ++++++++++++++++++ .../src/main/resources/META-INF/beans.xml | 4 +- .../main/resources/META-INF/persistence.xml | 10 +++- .../META-INF/jboss-deployment-structure.xml | 1 + .../src/main/webapp/WEB-INF/photoz-ds.xml | 12 ---- .../authorization/EnforcerConfigTest.java | 52 ++++++++++++++++ .../enforcer-config-paths-same-name.json | 59 +++++++++++++++++++ .../authorization-test/test-authz-realm.json | 50 ++++++++++++++++ .../integration-arquillian/tests/pom.xml | 4 ++ 28 files changed, 521 insertions(+), 53 deletions(-) create mode 100644 examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java create mode 100644 examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java create mode 100644 examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java delete mode 100644 examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml create mode 100644 testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java create mode 100644 testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java create mode 100644 testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java delete mode 100644 testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml create mode 100644 testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java create mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json create mode 100644 testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java index cfe5ff9a97..bbbf573e34 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java @@ -32,6 +32,7 @@ import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCon import org.keycloak.representations.idm.authorization.Permission; import java.net.URI; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -55,7 +56,7 @@ public abstract class AbstractPolicyEnforcer { this.enforcerConfig = policyEnforcer.getEnforcerConfig(); this.authzClient = policyEnforcer.getClient(); this.pathMatcher = new PathMatcher(); - this.paths = policyEnforcer.getPaths(); + this.paths = new ArrayList<>(policyEnforcer.getPaths()); } public AuthorizationContext authorize(OIDCHttpFacade httpFacade) { diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java index aa6d3d25d0..88ef9ce00e 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java @@ -33,8 +33,12 @@ import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCon import org.keycloak.representations.idm.authorization.Permission; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -95,8 +99,8 @@ public class PolicyEnforcer { return authzClient; } - List getPaths() { - return paths; + public List getPaths() { + return Collections.unmodifiableList(paths); } KeycloakDeployment getDeployment() { @@ -154,13 +158,27 @@ public class PolicyEnforcer { pathConfig.setId(registrationResponse.getId()); } else { - throw new RuntimeException("Could not find matching resource on server with uri [" + path + "] or name [" + resourceName + ". Make sure you have created a resource on the server that matches with the path configuration."); + throw new RuntimeException("Could not find matching resource on server with uri [" + path + "] or name [" + resourceName + "]. Make sure you have created a resource on the server that matches with the path configuration."); } } else { pathConfig.setId(search.iterator().next()); } - paths.add(pathConfig); + PathConfig existingPath = null; + + for (PathConfig current : paths) { + if (current.getId().equals(pathConfig.getId()) && current.getPath().equals(pathConfig.getPath())) { + existingPath = current; + break; + } + } + + if (existingPath == null) { + paths.add(pathConfig); + } else { + existingPath.getMethods().addAll(pathConfig.getMethods()); + existingPath.getScopes().addAll(pathConfig.getScopes()); + } } return paths; diff --git a/examples/authz/photoz/photoz-restful-api/pom.xml b/examples/authz/photoz/photoz-restful-api/pom.xml index ba7a88079f..7622af4f85 100755 --- a/examples/authz/photoz/photoz-restful-api/pom.xml +++ b/examples/authz/photoz/photoz-restful-api/pom.xml @@ -39,6 +39,12 @@ 1.0.0.Final provided + + javax.enterprise + cdi-api + 1.0-SP4 + provided + org.keycloak keycloak-authz-client diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java index b349e026d4..428ba078bd 100644 --- a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java +++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java @@ -19,9 +19,8 @@ package org.keycloak.example.photoz.admin; import org.keycloak.example.photoz.entity.Album; -import javax.ejb.Stateless; +import javax.inject.Inject; import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -36,12 +35,11 @@ import java.util.List; * @author Pedro Igor */ @Path("/admin/album") -@Stateless public class AdminAlbumService { public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage"; - @PersistenceContext + @Inject private EntityManager entityManager; @Context diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java index a5d7f161b4..d0e9c2d5c5 100644 --- a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java +++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java @@ -7,10 +7,12 @@ import org.keycloak.authorization.client.representation.ScopeRepresentation; import org.keycloak.authorization.client.resource.ProtectionResource; import org.keycloak.example.photoz.ErrorResponse; import org.keycloak.example.photoz.entity.Album; +import org.keycloak.example.photoz.util.Transaction; import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.util.JsonSerialization; import javax.ejb.Stateless; +import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; @@ -31,14 +33,14 @@ import java.util.List; import java.util.Set; @Path("/album") -@Stateless +@Transaction public class AlbumService { public static final String SCOPE_ALBUM_VIEW = "urn:photoz.com:scopes:album:view"; public static final String SCOPE_ALBUM_CREATE = "urn:photoz.com:scopes:album:create"; public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete"; - @PersistenceContext + @Inject private EntityManager entityManager; @Context diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java index be638b602e..f7b55cbc33 100644 --- a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java +++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java @@ -18,6 +18,7 @@ package org.keycloak.example.photoz.album; import javax.ejb.Stateless; +import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.servlet.http.HttpServletRequest; @@ -34,12 +35,11 @@ import java.util.List; * @author Pedro Igor */ @Path("/profile") -@Stateless public class ProfileService { private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view"; - @PersistenceContext + @Inject private EntityManager entityManager; @GET diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java new file mode 100644 index 0000000000..c917da24db --- /dev/null +++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java @@ -0,0 +1,51 @@ +/* + * Copyright 2016 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.example.photoz.util; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Produces; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +/** + * @author Pedro Igor + */ +@ApplicationScoped +public class Resources { + + private EntityManagerFactory entityManagerFactory; + + @PostConstruct + public void init() { + entityManagerFactory = Persistence.createEntityManagerFactory("primary"); + } + + @PreDestroy + public void dispose() { + entityManagerFactory.close(); + } + + @RequestScoped + @Produces + public EntityManager createEntityManager() { + return entityManagerFactory.createEntityManager(); + } +} diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java new file mode 100644 index 0000000000..a3caa780a8 --- /dev/null +++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016 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.example.photoz.util; + +import javax.interceptor.InterceptorBinding; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * @author Pedro Igor + */ +@InterceptorBinding +@Target({ TYPE }) +@Retention(RUNTIME) +public @interface Transaction { +} diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java new file mode 100644 index 0000000000..36d35f319b --- /dev/null +++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016 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.example.photoz.util; + +import javax.enterprise.inject.Instance; +import javax.inject.Inject; +import javax.interceptor.AroundInvoke; +import javax.interceptor.Interceptor; +import javax.interceptor.InvocationContext; +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; + +/** + * @author Pedro Igor + */ +@Interceptor +@Transaction +public class TransactionInterceptor { + + @Inject + private Instance entityManager; + + @AroundInvoke + public Object aroundInvoke(InvocationContext context) { + EntityManager entityManager = this.entityManager.get(); + EntityTransaction transaction = entityManager.getTransaction(); + + try { + transaction.begin(); + Object proceed = context.proceed(); + transaction.commit(); + return proceed; + } catch (Exception cause) { + if (transaction != null && transaction.isActive()) { + transaction.rollback(); + } + throw new RuntimeException(cause); + } finally { + entityManager.close(); + } + } +} diff --git a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml index 957dc8ac43..fbf2a32edf 100644 --- a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml +++ b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml @@ -3,5 +3,7 @@ xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> - + + org.keycloak.example.photoz.util.TransactionInterceptor + diff --git a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml index 9323182405..c15d34f449 100644 --- a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml +++ b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml @@ -4,14 +4,18 @@ xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> - - java:jboss/datasources/PhotozDS + + org.hibernate.ejb.HibernatePersistence org.keycloak.example.photoz.entity.Album org.keycloak.example.photoz.entity.Photo - + + + + + diff --git a/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml b/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml index 4b23be62d7..455335898f 100644 --- a/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml +++ b/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml @@ -20,6 +20,7 @@ + diff --git a/examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml b/examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml deleted file mode 100644 index 247448f2ae..0000000000 --- a/examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - jdbc:h2:${jboss.server.data.dir}/kc-authz-photo;AUTO_SERVER=TRUE - h2 - - sa - sa - - - \ No newline at end of file diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml index 7885857cdd..f5e2d4c2b9 100755 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml @@ -39,6 +39,12 @@ 1.0.0.Final provided + + javax.enterprise + cdi-api + 1.0-SP4 + provided + org.keycloak keycloak-authz-client diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java index b349e026d4..428ba078bd 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java @@ -19,9 +19,8 @@ package org.keycloak.example.photoz.admin; import org.keycloak.example.photoz.entity.Album; -import javax.ejb.Stateless; +import javax.inject.Inject; import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -36,12 +35,11 @@ import java.util.List; * @author Pedro Igor */ @Path("/admin/album") -@Stateless public class AdminAlbumService { public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage"; - @PersistenceContext + @Inject private EntityManager entityManager; @Context diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java index a5d7f161b4..d0e9c2d5c5 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java @@ -7,10 +7,12 @@ import org.keycloak.authorization.client.representation.ScopeRepresentation; import org.keycloak.authorization.client.resource.ProtectionResource; import org.keycloak.example.photoz.ErrorResponse; import org.keycloak.example.photoz.entity.Album; +import org.keycloak.example.photoz.util.Transaction; import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.util.JsonSerialization; import javax.ejb.Stateless; +import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; @@ -31,14 +33,14 @@ import java.util.List; import java.util.Set; @Path("/album") -@Stateless +@Transaction public class AlbumService { public static final String SCOPE_ALBUM_VIEW = "urn:photoz.com:scopes:album:view"; public static final String SCOPE_ALBUM_CREATE = "urn:photoz.com:scopes:album:create"; public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete"; - @PersistenceContext + @Inject private EntityManager entityManager; @Context diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java index be638b602e..f7b55cbc33 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java @@ -18,6 +18,7 @@ package org.keycloak.example.photoz.album; import javax.ejb.Stateless; +import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.servlet.http.HttpServletRequest; @@ -34,12 +35,11 @@ import java.util.List; * @author Pedro Igor */ @Path("/profile") -@Stateless public class ProfileService { private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view"; - @PersistenceContext + @Inject private EntityManager entityManager; @GET diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java new file mode 100644 index 0000000000..c917da24db --- /dev/null +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java @@ -0,0 +1,51 @@ +/* + * Copyright 2016 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.example.photoz.util; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Produces; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +/** + * @author Pedro Igor + */ +@ApplicationScoped +public class Resources { + + private EntityManagerFactory entityManagerFactory; + + @PostConstruct + public void init() { + entityManagerFactory = Persistence.createEntityManagerFactory("primary"); + } + + @PreDestroy + public void dispose() { + entityManagerFactory.close(); + } + + @RequestScoped + @Produces + public EntityManager createEntityManager() { + return entityManagerFactory.createEntityManager(); + } +} diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java new file mode 100644 index 0000000000..a3caa780a8 --- /dev/null +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java @@ -0,0 +1,34 @@ +/* + * Copyright 2016 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.example.photoz.util; + +import javax.interceptor.InterceptorBinding; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * @author Pedro Igor + */ +@InterceptorBinding +@Target({ TYPE }) +@Retention(RUNTIME) +public @interface Transaction { +} diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java new file mode 100644 index 0000000000..36d35f319b --- /dev/null +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016 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.example.photoz.util; + +import javax.enterprise.inject.Instance; +import javax.inject.Inject; +import javax.interceptor.AroundInvoke; +import javax.interceptor.Interceptor; +import javax.interceptor.InvocationContext; +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; + +/** + * @author Pedro Igor + */ +@Interceptor +@Transaction +public class TransactionInterceptor { + + @Inject + private Instance entityManager; + + @AroundInvoke + public Object aroundInvoke(InvocationContext context) { + EntityManager entityManager = this.entityManager.get(); + EntityTransaction transaction = entityManager.getTransaction(); + + try { + transaction.begin(); + Object proceed = context.proceed(); + transaction.commit(); + return proceed; + } catch (Exception cause) { + if (transaction != null && transaction.isActive()) { + transaction.rollback(); + } + throw new RuntimeException(cause); + } finally { + entityManager.close(); + } + } +} diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml index 957dc8ac43..fbf2a32edf 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml @@ -3,5 +3,7 @@ xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> - + + org.keycloak.example.photoz.util.TransactionInterceptor + diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml index 9323182405..8b6d226720 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml @@ -4,14 +4,18 @@ xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> - - java:jboss/datasources/PhotozDS + + org.hibernate.ejb.HibernatePersistence org.keycloak.example.photoz.entity.Album org.keycloak.example.photoz.entity.Photo - + + + + + diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml index 4b23be62d7..455335898f 100644 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml @@ -20,6 +20,7 @@ + diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml deleted file mode 100644 index 247448f2ae..0000000000 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - jdbc:h2:${jboss.server.data.dir}/kc-authz-photo;AUTO_SERVER=TRUE - h2 - - sa - sa - - - \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java new file mode 100644 index 0000000000..4236b2e14f --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016 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.testsuite.adapter.example.authorization; + +import org.junit.Assert; +import org.junit.Test; +import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.KeycloakDeploymentBuilder; +import org.keycloak.adapters.authorization.PolicyEnforcer; +import org.keycloak.representations.adapters.config.PolicyEnforcerConfig; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.AbstractKeycloakTest; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.keycloak.testsuite.util.IOUtil.loadRealm; + +/** + * @author Pedro Igor + */ +public class EnforcerConfigTest extends AbstractKeycloakTest { + + @Override + public void addTestRealms(List testRealms) { + RealmRepresentation realm = loadRealm(getClass().getResourceAsStream("/authorization-test/test-authz-realm.json")); + testRealms.add(realm); + } + + @Test + public void testMultiplePathsWithSameName() throws Exception{ + KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getClass().getResourceAsStream("/authorization-test/enforcer-config-paths-same-name.json")); + PolicyEnforcer policyEnforcer = deployment.getPolicyEnforcer(); + List paths = policyEnforcer.getPaths(); + assertEquals(1, paths.size()); + assertEquals(4, paths.get(0).getMethods().size()); + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json new file mode 100644 index 0000000000..19d8c55fe5 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json @@ -0,0 +1,59 @@ +{ + "realm": "test-realm-authz", + "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", + "auth-server-url": "http://localhost:8180/auth", + "ssl-required": "external", + "resource": "test-app-authz", + "bearer-only": true, + "credentials": { + "secret": "secret" + }, + "policy-enforcer": { + "paths": [ + { + "path": "/v1/product/*", + "methods": [ + { + "method": "POST", + "scopes": [ + "create" + ] + } + ] + }, + { + "path": "/v1/product/*", + "methods": [ + { + "method": "GET", + "scopes": [ + "view" + ] + } + ] + }, + { + "path": "/v1/product/*", + "methods": [ + { + "method": "PUT", + "scopes": [ + "update" + ] + } + ] + }, + { + "path": "/v1/product/*", + "methods": [ + { + "method": "DELETE", + "scopes": [ + "delete" + ] + } + ] + } + ] + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json new file mode 100644 index 0000000000..b1a6f5a07f --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json @@ -0,0 +1,50 @@ +{ + "id": "test-realm-authz", + "realm": "test-realm-authz", + "enabled": true, + "sslRequired": "external", + "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=", + "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", + "requiredCredentials": [ "password" ], + "users": [ + { + "username": "service-account-test-app-authz", + "enabled": true, + "serviceAccountClientId": "test-app-authz", + "clientRoles": { + "test-app-authz" : ["uma_protection"] + } + } + ], + "clients": [ + { + "clientId": "test-app-authz", + "enabled": true, + "baseUrl": "/test-app-authz", + "adminUrl": "/test-app-authz", + "bearerOnly": false, + "authorizationSettings": { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Product Resource", + "uri": "/v1/product/*", + "scopes": [ + { + "name": "view", + "name": "create", + "name": "delete", + "name": "update" + } + ] + } + ] + }, + "redirectUris": [ + "/test-app-authz/*" + ], + "secret": "secret" + } + ] +} diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index 40e17b5572..b2ee848b26 100755 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -784,6 +784,10 @@ org.keycloak keycloak-saml-adapter-api-public + + org.keycloak + keycloak-authz-client +