You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2016/04/01 18:28:20 UTC

cxf git commit: Starting working on JPA persistence support for OAuth2 model

Repository: cxf
Updated Branches:
  refs/heads/master 281b4e9d9 -> d25ca92d1


Starting working on JPA persistence support for OAuth2 model


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/d25ca92d
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/d25ca92d
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/d25ca92d

Branch: refs/heads/master
Commit: d25ca92d11e4b273022a54210ffd2d805c22a41e
Parents: 281b4e9
Author: Sergey Beryozkin <sb...@gmail.com>
Authored: Fri Apr 1 17:28:04 2016 +0100
Committer: Sergey Beryozkin <sb...@gmail.com>
Committed: Fri Apr 1 17:28:04 2016 +0100

----------------------------------------------------------------------
 rt/rs/security/oauth-parent/oauth2/pom.xml      |  36 ++++++
 .../cxf/rs/security/oauth2/common/Client.java   |  15 +++
 .../rs/security/oauth2/common/UserSubject.java  |   5 +
 .../oauth2/grants/code/JPACodeDataProvider.java |  51 ++++++++
 .../oauth2/provider/JPAOAuthDataProvider.java   | 115 +++++++++++++++++++
 .../grants/code/JPACodeDataProviderTest.java    |  99 ++++++++++++++++
 .../src/test/resources/META-INF/persistence.xml |  32 ++++++
 7 files changed, 353 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/d25ca92d/rt/rs/security/oauth-parent/oauth2/pom.xml
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/pom.xml b/rt/rs/security/oauth-parent/oauth2/pom.xml
index 84af41c..2642684 100644
--- a/rt/rs/security/oauth-parent/oauth2/pom.xml
+++ b/rt/rs/security/oauth-parent/oauth2/pom.xml
@@ -35,6 +35,8 @@
             net.sf.ehcache*;resolution:=optional;version="[2.5, 3.0.0)",
             javax.servlet*;version="${cxf.osgi.javax.servlet.version}"
         </cxf.osgi.import>
+        <hibernate.em.version>4.1.0.Final</hibernate.em.version>
+        <hsqldb.version>1.8.0.10</hsqldb.version>
     </properties>
     <dependencies>
         <dependency>
@@ -66,6 +68,13 @@
             <optional>true</optional>
         </dependency>
         <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jpa_2.0_spec</artifactId>
+            <version>${cxf.geronimo.jpa.version}</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
             <groupId>org.codehaus.jettison</groupId>
             <artifactId>jettison</artifactId>
             <scope>test</scope>
@@ -86,5 +95,32 @@
             <artifactId>easymock</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+            <version>${hibernate.em.version}</version>
+            <scope>test</scope>
+            <!-- Conflicts with Apache Tika dependencies -->
+            <exclusions>
+                <exclusion>
+                    <groupId>xml-apis</groupId>
+                    <artifactId>xml-apis</artifactId>                
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>hsqldb</groupId>
+            <artifactId>hsqldb</artifactId>
+            <version>${hsqldb.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <!--
+           <dependency>
+             <groupId>org.apache.openjpa</groupId>
+             <artifactId>openjpa</artifactId>
+             <version>2.2.0</version>
+             <scope>test</scope>
+           </dependency>
+        -->
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/cxf/blob/d25ca92d/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
index fbd9e3f..ec54db4 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/Client.java
@@ -24,9 +24,16 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.MapKeyColumn;
+
+
 /**
  * Represents a registered third-party Client application
  */
+@Entity
 public class Client implements Serializable {
     
     private static final long serialVersionUID = -5550840247125850922L;
@@ -85,6 +92,7 @@ public class Client implements Serializable {
      * Get the client registration id
      * @return the consumer key
      */
+    @Id
     public String getClientId() {
         return clientId;
     }
@@ -204,6 +212,7 @@ public class Client implements Serializable {
      * may return the authorization code to
      * @return the redirect uris
      */
+    @ElementCollection
     public List<String> getRedirectUris() {
         return redirectUris;
     }
@@ -222,6 +231,7 @@ public class Client implements Serializable {
      * can use to obtain the access tokens.
      * @return the list of grant types
      */
+    @ElementCollection
     public List<String> getAllowedGrantTypes() {
         return allowedGrantTypes;
     }
@@ -274,6 +284,8 @@ public class Client implements Serializable {
      * Get the list of additional client properties
      * @return the list of properties
      */
+    @ElementCollection
+    @MapKeyColumn(name = "name")
     public Map<String, String> getProperties() {
         return properties;
     }
@@ -290,6 +302,7 @@ public class Client implements Serializable {
      * Get the list of registered scopes
      * @return scopes
      */
+    @ElementCollection
     public List<String> getRegisteredScopes() {
         return registeredScopes;
     }
@@ -307,6 +320,7 @@ public class Client implements Serializable {
         this.registeredScopes = registeredScopes;
     }
 
+    @ElementCollection
     public List<String> getRegisteredAudiences() {
         return registeredAudiences;
     }
@@ -319,6 +333,7 @@ public class Client implements Serializable {
         this.registeredAudiences = registeredAudiences;
     }
 
+    @ElementCollection
     public List<String> getApplicationCertificates() {
         return applicationCertificates;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/d25ca92d/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java
index ec4f4b6..7ad88fb 100644
--- a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/common/UserSubject.java
@@ -24,6 +24,8 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import javax.persistence.ElementCollection;
+import javax.persistence.MapKeyColumn;
 import javax.xml.bind.annotation.XmlRootElement;
 
 /**
@@ -92,6 +94,7 @@ public class UserSubject implements Serializable {
      * been captured during the authentication process 
      * @return the list of roles
      */
+    @ElementCollection
     public List<String> getRoles() {
         return roles;
     }
@@ -109,6 +112,8 @@ public class UserSubject implements Serializable {
      * Get the list of additional user subject properties
      * @return the list of properties
      */
+    @ElementCollection
+    @MapKeyColumn(name = "name")
     public Map<String, String> getProperties() {
         return properties;
     }

http://git-wip-us.apache.org/repos/asf/cxf/blob/d25ca92d/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java
new file mode 100644
index 0000000..55b7de2
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProvider.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.rs.security.oauth2.grants.code;
+
+import java.util.List;
+
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.provider.JPAOAuthDataProvider;
+import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException;
+
+public class JPACodeDataProvider extends JPAOAuthDataProvider 
+    implements AuthorizationCodeDataProvider {
+
+    @Override
+    public ServerAuthorizationCodeGrant createCodeGrant(AuthorizationCodeRegistration reg)
+        throws OAuthServiceException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public ServerAuthorizationCodeGrant removeCodeGrant(String code) throws OAuthServiceException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<ServerAuthorizationCodeGrant> getCodeGrants(Client c, UserSubject subject)
+        throws OAuthServiceException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/d25ca92d/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java
new file mode 100644
index 0000000..aa565a4
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/main/java/org/apache/cxf/rs/security/oauth2/provider/JPAOAuthDataProvider.java
@@ -0,0 +1,115 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.rs.security.oauth2.provider;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+import org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken;
+
+public class JPAOAuthDataProvider extends AbstractOAuthDataProvider {
+    private static final String CLIENT_TABLE_NAME = Client.class.getSimpleName();
+    private EntityManager entityManager;
+    
+    public JPAOAuthDataProvider() {
+    }
+    
+    @Override
+    public Client getClient(String clientId) throws OAuthServiceException {
+        try {
+            TypedQuery<Client> query = entityManager.createQuery(
+                "SELECT c FROM " + CLIENT_TABLE_NAME + " c WHERE c.clientId = '" + clientId + "'", Client.class);
+            return query.getSingleResult();
+        } catch (NoResultException ex) {
+            return null;
+        }
+    }
+    
+    public void setClient(Client client) {
+        persistEntity(client);
+    }
+    
+    @Override
+    protected void doRemoveClient(Client c) {
+        removeEntity(c);
+    }
+
+    @Override
+    public List<Client> getClients(UserSubject resourceOwner) {
+        return null;
+    }
+
+    @Override
+    public List<ServerAccessToken> getAccessTokens(Client c, UserSubject sub) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<RefreshToken> getRefreshTokens(Client c, UserSubject sub) {
+        return Collections.emptyList();
+    }
+    
+    @Override
+    public ServerAccessToken getAccessToken(String accessToken) throws OAuthServiceException {
+        return null;
+    }
+    @Override
+    protected void doRevokeAccessToken(ServerAccessToken at) {
+    }
+    @Override
+    protected RefreshToken getRefreshToken(String refreshTokenKey) { 
+        return null;
+    }
+    @Override
+    protected void doRevokeRefreshToken(RefreshToken rt) { 
+    }
+    
+    protected void saveAccessToken(ServerAccessToken serverToken) {
+        persistEntity(serverToken);
+    }
+    
+    protected void saveRefreshToken(ServerAccessToken at, RefreshToken refreshToken) {
+    }
+    
+    protected void persistEntity(Object entity) {
+        entityManager.getTransaction().begin();
+        entityManager.persist(entity);
+        entityManager.getTransaction().commit();
+    }
+    protected void removeEntity(Object entity) {
+        entityManager.getTransaction().begin();
+        entityManager.remove(entity);
+        entityManager.getTransaction().commit();
+    }
+
+    public void setEntityManager(EntityManager entityManager) {
+        this.entityManager = entityManager;
+    }
+    @Override
+    public void close() {
+        entityManager.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/d25ca92d/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java
new file mode 100644
index 0000000..4463b9d
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/java/org/apache/cxf/rs/security/oauth2/grants/code/JPACodeDataProviderTest.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.cxf.rs.security.oauth2.grants.code;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Collections;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+import org.apache.cxf.rs.security.oauth2.common.Client;
+import org.apache.cxf.rs.security.oauth2.common.UserSubject;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JPACodeDataProviderTest extends Assert {
+    private EntityManagerFactory emFactory;
+    private Connection connection;
+    private JPACodeDataProvider provider;
+    @Before
+    public void setUp() throws Exception {
+        try {
+            Class.forName("org.hsqldb.jdbcDriver");
+            connection = DriverManager.getConnection("jdbc:hsqldb:mem:oauth-jpa", "sa", "");
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            fail("Exception during HSQL database init.");
+        }
+        try {
+            emFactory = Persistence.createEntityManagerFactory("testUnitHibernate");
+            EntityManager em = emFactory.createEntityManager();
+            provider = new JPACodeDataProvider();
+            provider.setEntityManager(em);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            fail("Exception during JPA EntityManager creation.");
+        }
+    }
+
+    @Test
+    public void testAddGetDeleteClient() {
+        Client c = new Client();
+        c.setRedirectUris(Collections.singletonList("http://client/redirect"));
+        c.setClientId("12345");
+        c.setResourceOwnerSubject(new UserSubject("alice"));
+        provider.setClient(c);
+        Client c2 = provider.getClient(c.getClientId());
+        assertNotNull(c2);
+        assertEquals(c.getClientId(), c2.getClientId());
+        assertEquals(c.getRedirectUris(), c.getRedirectUris());
+        assertEquals("alice", c.getResourceOwnerSubject().getLogin());
+        
+        provider.removeClient(c.getClientId());
+        Client c3 = provider.getClient(c.getClientId());
+        assertNull(c3);
+    }
+    
+    @After
+    public void tearDown() throws Exception {
+        try {
+            if (provider != null) {
+                provider.close();
+            }
+            if (emFactory != null) {
+                emFactory.close();
+            }
+        } catch (Throwable ex) {
+            ex.printStackTrace();    
+        } finally {    
+            try {
+                connection.createStatement().execute("SHUTDOWN");
+            } catch (Throwable ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/d25ca92d/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml b/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..2e63a46
--- /dev/null
+++ b/rt/rs/security/oauth-parent/oauth2/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,32 @@
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+             version="2.0">
+   <persistence-unit name="testUnitHibernate" transaction-type="RESOURCE_LOCAL">
+     <provider>org.hibernate.ejb.HibernatePersistence</provider>
+     <class>org.apache.cxf.rs.security.oauth2.common.Client</class>
+     <exclude-unlisted-classes>true</exclude-unlisted-classes>
+     <properties>
+        <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:oauth-jpa"/>
+        <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
+        <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
+        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
+        <property name="hibernate.connection.username" value="sa"/>
+        <property name="hibernate.connection.password" value=""/>
+        <property name="javax.persistence.validation.mode" value="none"/>
+     </properties>
+   </persistence-unit>
+   <persistence-unit name="testUnitOpenJPA" transaction-type="RESOURCE_LOCAL">
+     <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
+     <class>org.apache.cxf.rs.security.oauth2.common.Client</class>
+     <exclude-unlisted-classes>true</exclude-unlisted-classes>
+     <properties>
+        <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:mem:oauth-jpa"/>
+        <property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbcDriver"/>
+        <property name="openjpa.jdbc.DBDictionary" value="hsql" />
+        <property name="openjpa.ConnectionUserName" value="sa"/>
+        <property name="openjpa.ConnectionPassword" value=""/>
+        <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
+     </properties>
+    </persistence-unit>
+</persistence>
\ No newline at end of file