keycloak-aplcache
Changes
adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java 3(+2 -1)
adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java 26(+22 -4)
examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java 6(+2 -4)
examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java 6(+4 -2)
examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java 4(+2 -2)
examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java 51(+51 -0)
examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java 34(+34 -0)
examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java 56(+56 -0)
examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml 1(+1 -0)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java 6(+2 -4)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java 6(+4 -2)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java 4(+2 -2)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java 51(+51 -0)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java 34(+34 -0)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java 56(+56 -0)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml 4(+3 -1)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml 10(+7 -3)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml 1(+1 -0)
testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml 12(+0 -12)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java 52(+52 -0)
testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json 59(+59 -0)
Details
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 cfe5ff9..bbbf573 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 aa6d3d2..88ef9ce 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<PathConfig> getPaths() {
- return paths;
+ public List<PathConfig> 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 ba7a880..7622af4 100755
--- a/examples/authz/photoz/photoz-restful-api/pom.xml
+++ b/examples/authz/photoz/photoz-restful-api/pom.xml
@@ -40,6 +40,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <version>1.0-SP4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId>
<version>${project.version}</version>
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 b349e02..428ba07 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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@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 a5d7f16..d0e9c2d 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 be638b6..f7b55cb 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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@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 0000000..c917da2
--- /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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@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 0000000..a3caa78
--- /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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@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 0000000..36d35f3
--- /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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@Interceptor
+@Transaction
+public class TransactionInterceptor {
+
+ @Inject
+ private Instance<EntityManager> 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 957dc8a..fbf2a32 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">
-
+ <interceptors>
+ <class>org.keycloak.example.photoz.util.TransactionInterceptor</class>
+ </interceptors>
</beans>
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 9323182..c15d34f 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">
- <persistence-unit name="primary">
- <non-jta-data-source>java:jboss/datasources/PhotozDS</non-jta-data-source>
+ <persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
+ <provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.example.photoz.entity.Album</class>
<class>org.keycloak.example.photoz.entity.Photo</class>
<properties>
- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+ <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
+ <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
+ <property name="hibernate.connection.url" value="jdbc:h2:~/keycloak-photoz-example" />
+ <property name="hibernate.connection.user" value="sa" />
+ <property name="hibernate.flushMode" value="FLUSH_AUTO" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" />
</properties>
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 4b23be6..4553358 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 @@
<deployment>
<dependencies>
<module name="org.keycloak.keycloak-authz-client" services="import"/>
+ <module name="com.h2database.h2" services="import"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
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 7885857..f5e2d4c 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
@@ -40,6 +40,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <version>1.0-SP4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId>
<version>${project.version}</version>
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 b349e02..428ba07 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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@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 a5d7f16..d0e9c2d 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 be638b6..f7b55cb 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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
@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 0000000..c917da2
--- /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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@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 0000000..a3caa78
--- /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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@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 0000000..36d35f3
--- /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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@Interceptor
+@Transaction
+public class TransactionInterceptor {
+
+ @Inject
+ private Instance<EntityManager> 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 957dc8a..fbf2a32 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">
-
+ <interceptors>
+ <class>org.keycloak.example.photoz.util.TransactionInterceptor</class>
+ </interceptors>
</beans>
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 9323182..8b6d226 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">
- <persistence-unit name="primary">
- <non-jta-data-source>java:jboss/datasources/PhotozDS</non-jta-data-source>
+ <persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
+ <provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.example.photoz.entity.Album</class>
<class>org.keycloak.example.photoz.entity.Photo</class>
<properties>
- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+ <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
+ <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
+ <property name="hibernate.connection.url" value="jdbc:h2:mem:test-keycloak-photoz-example" />
+ <property name="hibernate.connection.user" value="sa" />
+ <property name="hibernate.flushMode" value="FLUSH_AUTO" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" />
</properties>
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 4b23be6..4553358 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 @@
<deployment>
<dependencies>
<module name="org.keycloak.keycloak-authz-client" services="import"/>
+ <module name="com.h2database.h2" services="import"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
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 0000000..4236b2e
--- /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 <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class EnforcerConfigTest extends AbstractKeycloakTest {
+
+ @Override
+ public void addTestRealms(List<RealmRepresentation> 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<PolicyEnforcerConfig.PathConfig> 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 0000000..19d8c55
--- /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 0000000..b1a6f5a
--- /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 40e17b5..b2ee848 100755
--- a/testsuite/integration-arquillian/tests/pom.xml
+++ b/testsuite/integration-arquillian/tests/pom.xml
@@ -784,6 +784,10 @@
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-adapter-api-public</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-authz-client</artifactId>
+ </dependency>
<!--UNDERTOW-->