Merge pull request #3179 from pedroigor/KEYCLOAK-3472

[KEYCLOAK-3472] - Multiple paths with the same name and tests
This commit is contained in:
Pedro Igor 2016-09-01 10:00:33 -03:00 committed by GitHub
commit 43d23835d0
28 changed files with 521 additions and 53 deletions

View file

@ -32,6 +32,7 @@ import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCon
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -55,7 +56,7 @@ public abstract class AbstractPolicyEnforcer {
this.enforcerConfig = policyEnforcer.getEnforcerConfig(); this.enforcerConfig = policyEnforcer.getEnforcerConfig();
this.authzClient = policyEnforcer.getClient(); this.authzClient = policyEnforcer.getClient();
this.pathMatcher = new PathMatcher(); this.pathMatcher = new PathMatcher();
this.paths = policyEnforcer.getPaths(); this.paths = new ArrayList<>(policyEnforcer.getPaths());
} }
public AuthorizationContext authorize(OIDCHttpFacade httpFacade) { public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {

View file

@ -33,8 +33,12 @@ import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCon
import org.keycloak.representations.idm.authorization.Permission; import org.keycloak.representations.idm.authorization.Permission;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -95,8 +99,8 @@ public class PolicyEnforcer {
return authzClient; return authzClient;
} }
List<PathConfig> getPaths() { public List<PathConfig> getPaths() {
return paths; return Collections.unmodifiableList(paths);
} }
KeycloakDeployment getDeployment() { KeycloakDeployment getDeployment() {
@ -154,13 +158,27 @@ public class PolicyEnforcer {
pathConfig.setId(registrationResponse.getId()); pathConfig.setId(registrationResponse.getId());
} else { } 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 { } else {
pathConfig.setId(search.iterator().next()); 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; return paths;

View file

@ -39,6 +39,12 @@
<version>1.0.0.Final</version> <version>1.0.0.Final</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0-SP4</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId> <artifactId>keycloak-authz-client</artifactId>

View file

@ -19,9 +19,8 @@ package org.keycloak.example.photoz.admin;
import org.keycloak.example.photoz.entity.Album; import org.keycloak.example.photoz.entity.Album;
import javax.ejb.Stateless; import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@ -36,12 +35,11 @@ import java.util.List;
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
@Path("/admin/album") @Path("/admin/album")
@Stateless
public class AdminAlbumService { public class AdminAlbumService {
public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage"; public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage";
@PersistenceContext @Inject
private EntityManager entityManager; private EntityManager entityManager;
@Context @Context

View file

@ -7,10 +7,12 @@ import org.keycloak.authorization.client.representation.ScopeRepresentation;
import org.keycloak.authorization.client.resource.ProtectionResource; import org.keycloak.authorization.client.resource.ProtectionResource;
import org.keycloak.example.photoz.ErrorResponse; import org.keycloak.example.photoz.ErrorResponse;
import org.keycloak.example.photoz.entity.Album; import org.keycloak.example.photoz.entity.Album;
import org.keycloak.example.photoz.util.Transaction;
import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import javax.persistence.Query; import javax.persistence.Query;
@ -31,14 +33,14 @@ import java.util.List;
import java.util.Set; import java.util.Set;
@Path("/album") @Path("/album")
@Stateless @Transaction
public class AlbumService { public class AlbumService {
public static final String SCOPE_ALBUM_VIEW = "urn:photoz.com:scopes:album:view"; 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_CREATE = "urn:photoz.com:scopes:album:create";
public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete"; public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete";
@PersistenceContext @Inject
private EntityManager entityManager; private EntityManager entityManager;
@Context @Context

View file

@ -18,6 +18,7 @@
package org.keycloak.example.photoz.album; package org.keycloak.example.photoz.album;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -34,12 +35,11 @@ import java.util.List;
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
@Path("/profile") @Path("/profile")
@Stateless
public class ProfileService { public class ProfileService {
private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view"; private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view";
@PersistenceContext @Inject
private EntityManager entityManager; private EntityManager entityManager;
@GET @GET

View file

@ -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();
}
}

View file

@ -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 {
}

View file

@ -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();
}
}
}

View file

@ -3,5 +3,7 @@
xsi:schemaLocation=" xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>org.keycloak.example.photoz.util.TransactionInterceptor</class>
</interceptors>
</beans> </beans>

View file

@ -4,14 +4,18 @@
xsi:schemaLocation=" xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary"> <persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:jboss/datasources/PhotozDS</non-jta-data-source> <provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.example.photoz.entity.Album</class> <class>org.keycloak.example.photoz.entity.Album</class>
<class>org.keycloak.example.photoz.entity.Photo</class> <class>org.keycloak.example.photoz.entity.Photo</class>
<properties> <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.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" /> <property name="hibernate.show_sql" value="false" />
</properties> </properties>

View file

@ -20,6 +20,7 @@
<deployment> <deployment>
<dependencies> <dependencies>
<module name="org.keycloak.keycloak-authz-client" services="import"/> <module name="org.keycloak.keycloak-authz-client" services="import"/>
<module name="com.h2database.h2" services="import"/>
</dependencies> </dependencies>
</deployment> </deployment>
</jboss-deployment-structure> </jboss-deployment-structure>

View file

@ -1,12 +0,0 @@
<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
<datasource jndi-name="java:jboss/datasources/PhotozDS" pool-name="PhotozDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:${jboss.server.data.dir}/kc-authz-photo;AUTO_SERVER=TRUE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
</datasources>

View file

@ -39,6 +39,12 @@
<version>1.0.0.Final</version> <version>1.0.0.Final</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0-SP4</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId> <artifactId>keycloak-authz-client</artifactId>

View file

@ -19,9 +19,8 @@ package org.keycloak.example.photoz.admin;
import org.keycloak.example.photoz.entity.Album; import org.keycloak.example.photoz.entity.Album;
import javax.ejb.Stateless; import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@ -36,12 +35,11 @@ import java.util.List;
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
@Path("/admin/album") @Path("/admin/album")
@Stateless
public class AdminAlbumService { public class AdminAlbumService {
public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage"; public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage";
@PersistenceContext @Inject
private EntityManager entityManager; private EntityManager entityManager;
@Context @Context

View file

@ -7,10 +7,12 @@ import org.keycloak.authorization.client.representation.ScopeRepresentation;
import org.keycloak.authorization.client.resource.ProtectionResource; import org.keycloak.authorization.client.resource.ProtectionResource;
import org.keycloak.example.photoz.ErrorResponse; import org.keycloak.example.photoz.ErrorResponse;
import org.keycloak.example.photoz.entity.Album; import org.keycloak.example.photoz.entity.Album;
import org.keycloak.example.photoz.util.Transaction;
import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import javax.persistence.Query; import javax.persistence.Query;
@ -31,14 +33,14 @@ import java.util.List;
import java.util.Set; import java.util.Set;
@Path("/album") @Path("/album")
@Stateless @Transaction
public class AlbumService { public class AlbumService {
public static final String SCOPE_ALBUM_VIEW = "urn:photoz.com:scopes:album:view"; 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_CREATE = "urn:photoz.com:scopes:album:create";
public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete"; public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete";
@PersistenceContext @Inject
private EntityManager entityManager; private EntityManager entityManager;
@Context @Context

View file

@ -18,6 +18,7 @@
package org.keycloak.example.photoz.album; package org.keycloak.example.photoz.album;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -34,12 +35,11 @@ import java.util.List;
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/ */
@Path("/profile") @Path("/profile")
@Stateless
public class ProfileService { public class ProfileService {
private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view"; private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view";
@PersistenceContext @Inject
private EntityManager entityManager; private EntityManager entityManager;
@GET @GET

View file

@ -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();
}
}

View file

@ -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 {
}

View file

@ -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();
}
}
}

View file

@ -3,5 +3,7 @@
xsi:schemaLocation=" xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>org.keycloak.example.photoz.util.TransactionInterceptor</class>
</interceptors>
</beans> </beans>

View file

@ -4,14 +4,18 @@
xsi:schemaLocation=" xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary"> <persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:jboss/datasources/PhotozDS</non-jta-data-source> <provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.example.photoz.entity.Album</class> <class>org.keycloak.example.photoz.entity.Album</class>
<class>org.keycloak.example.photoz.entity.Photo</class> <class>org.keycloak.example.photoz.entity.Photo</class>
<properties> <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.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" /> <property name="hibernate.show_sql" value="false" />
</properties> </properties>

View file

@ -20,6 +20,7 @@
<deployment> <deployment>
<dependencies> <dependencies>
<module name="org.keycloak.keycloak-authz-client" services="import"/> <module name="org.keycloak.keycloak-authz-client" services="import"/>
<module name="com.h2database.h2" services="import"/>
</dependencies> </dependencies>
</deployment> </deployment>
</jboss-deployment-structure> </jboss-deployment-structure>

View file

@ -1,12 +0,0 @@
<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
<datasource jndi-name="java:jboss/datasources/PhotozDS" pool-name="PhotozDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:${jboss.server.data.dir}/kc-authz-photo;AUTO_SERVER=TRUE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
</datasources>

View file

@ -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());
}
}

View file

@ -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"
]
}
]
}
]
}
}

View file

@ -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"
}
]
}

View file

@ -784,6 +784,10 @@
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-adapter-api-public</artifactId> <artifactId>keycloak-saml-adapter-api-public</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId>
</dependency>
<!--UNDERTOW--> <!--UNDERTOW-->