You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@archiva.apache.org by ma...@apache.org on 2017/05/21 21:46:47 UTC
[02/40] archiva-redback-core git commit: Adding JPA implementation of
users and rbac provider
Adding JPA implementation of users and rbac provider
Uses OpenJPA
Project: http://git-wip-us.apache.org/repos/asf/archiva-redback-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/archiva-redback-core/commit/62efc70b
Tree: http://git-wip-us.apache.org/repos/asf/archiva-redback-core/tree/62efc70b
Diff: http://git-wip-us.apache.org/repos/asf/archiva-redback-core/diff/62efc70b
Branch: refs/heads/master
Commit: 62efc70bd27c0ddb8bd01c0f67b0c96646aaaea5
Parents: d17c6ff
Author: Martin Stockhammer <ma...@apache.org>
Authored: Tue Sep 27 23:13:03 2016 +0200
Committer: Martin Stockhammer <ma...@apache.org>
Committed: Tue Sep 27 23:13:03 2016 +0200
----------------------------------------------------------------------
pom.xml | 14 +-
redback-common/pom.xml | 1 +
redback-common/redback-common-jpa/pom.xml | 57 +++
.../resources/META-INF/persistence-hsqldb.xml | 41 ++
.../src/main/resources/META-INF/persistence.xml | 36 ++
redback-rbac/redback-rbac-providers/pom.xml | 1 +
.../redback-rbac-jpa/pom.xml | 70 +++
.../redback/rbac/jpa/JpaRbacManager.java | 452 +++++++++++++++++++
.../redback/rbac/jpa/model/JpaOperation.java | 91 ++++
.../redback/rbac/jpa/model/JpaPermission.java | 123 +++++
.../redback/rbac/jpa/model/JpaResource.java | 91 ++++
.../archiva/redback/rbac/jpa/model/JpaRole.java | 172 +++++++
.../rbac/jpa/model/JpaUserAssignment.java | 97 ++++
.../redback/rbac/jpa/JpaRbacManagerTest.java | 132 ++++++
.../src/test/resources/spring-context.xml | 40 ++
.../src/test/resources/test.properties | 22 +
redback-users/redback-users-providers/pom.xml | 1 +
.../redback-users-jpa/pom.xml | 68 +++
.../redback/users/jpa/JpaUserManager.java | 307 +++++++++++++
.../archiva/redback/users/jpa/JpaUserQuery.java | 123 +++++
.../redback/users/jpa/model/JpaUser.java | 206 +++++++++
.../redback/users/jpa/JpaUserManagerTest.java | 86 ++++
.../src/test/resources/spring-context.xml | 50 ++
.../src/test/resources/test.properties | 22 +
.../test/AbstractUserManagerTestCase.java | 2 +
25 files changed, 2304 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index fa30ae5..3e218ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<gpg.useagent>true</gpg.useagent>
<cxf.version>3.0.3</cxf.version>
+ <openjpa.version>2.4.1</openjpa.version>
+
<!--
<redbackTestJdbcUrl>jdbc:derby:memory:users-test;create=true</redbackTestJdbcUrl>
<redbackTestJdbcDriver>org.apache.derby.jdbc.EmbeddedDriver</redbackTestJdbcDriver>
@@ -300,6 +302,16 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-common-jpa</artifactId>
+ <version>2.5-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-users-jpa</artifactId>
+ <version>2.5-SNAPSHOT</version>
+ </dependency>
+ <dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
@@ -930,7 +942,7 @@
<descriptorRefs>
<descriptorRef>${sourceReleaseAssemblyDescriptor}</descriptorRef>
</descriptorRefs>
- <tarLongFileFormat>gnu</tarLongFileFormat>
+ <tarLongFileMode>gnu</tarLongFileMode>
</configuration>
</execution>
</executions>
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-common/pom.xml
----------------------------------------------------------------------
diff --git a/redback-common/pom.xml b/redback-common/pom.xml
index 4a68200..9819bb0 100644
--- a/redback-common/pom.xml
+++ b/redback-common/pom.xml
@@ -31,5 +31,6 @@
<module>redback-common-jdo</module>
<module>redback-common-ldap</module>
<module>redback-common-test-resources</module>
+ <module>redback-common-jpa</module>
</modules>
</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-common/redback-common-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/redback-common/redback-common-jpa/pom.xml b/redback-common/redback-common-jpa/pom.xml
new file mode 100644
index 0000000..ca3b942
--- /dev/null
+++ b/redback-common/redback-common-jpa/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>redback-common</artifactId>
+ <groupId>org.apache.archiva.redback</groupId>
+ <version>2.5-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>redback-common-jpa</artifactId>
+ <packaging>jar</packaging>
+ <name>Redback :: JPA Common Package</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-rbac-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-users-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa</artifactId>
+ <version>${openjpa.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence-hsqldb.xml
----------------------------------------------------------------------
diff --git a/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence-hsqldb.xml b/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence-hsqldb.xml
new file mode 100644
index 0000000..a78444e
--- /dev/null
+++ b/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence-hsqldb.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
+ <persistence-unit name="redback-jpa">
+ <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
+ <jta-data-source>java:comp/env/jdbc/redbackjpa</jta-data-source>
+ <class>org.apache.archiva.redback.users.jpa.model.JpaUser</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaOperation</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaResource</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaPermission</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaRole</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaUserAssignment</class>
+ <properties>
+ <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:mem:redback_database"/>
+ <property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbcDriver"/>
+ <property name="openjpa.ConnectionUserName" value="sa"/>
+ <property name="openjpa.ConnectionPassword" value=""/>
+ <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO"/>
+ <property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />
+ <property name="openjpa.jdbc.MappingDefaults"
+ value="ForeignKeyDeleteAction=restrict,JoinForeignKeyDeleteAction=restrict"/>
+ </properties>
+ </persistence-unit>
+</persistence>
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence.xml b/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..46878e8
--- /dev/null
+++ b/redback-common/redback-common-jpa/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
+ <persistence-unit name="redback-jpa">
+ <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
+ <jta-data-source>java:comp/env/jdbc/redbackjpa</jta-data-source>
+ <class>org.apache.archiva.redback.users.jpa.model.JpaUser</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaOperation</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaResource</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaPermission</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaRole</class>
+ <class>org.apache.archiva.redback.rbac.jpa.model.JpaUserAssignment</class>
+ <properties>
+ <property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />
+ <property name="openjpa.jdbc.MappingDefaults"
+ value="ForeignKeyDeleteAction=restrict,JoinForeignKeyDeleteAction=restrict"/>
+ </properties>
+ </persistence-unit>
+</persistence>
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/pom.xml
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/pom.xml b/redback-rbac/redback-rbac-providers/pom.xml
index 0edb497..a94d451 100644
--- a/redback-rbac/redback-rbac-providers/pom.xml
+++ b/redback-rbac/redback-rbac-providers/pom.xml
@@ -32,5 +32,6 @@
<module>redback-rbac-memory</module>
<module>redback-rbac-cached</module>
<module>redback-rbac-ldap</module>
+ <module>redback-rbac-jpa</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml
new file mode 100644
index 0000000..77045ab
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>redback-rbac-providers</artifactId>
+ <groupId>org.apache.archiva.redback</groupId>
+ <version>2.5-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>redback-rbac-jpa</artifactId>
+ <packaging>jar</packaging>
+ <name>Redback :: RBAC Provider :: JPA</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-rbac-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>jsr250-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-rbac-tests</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-common-jpa</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa</artifactId>
+ <version>${openjpa.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java
new file mode 100644
index 0000000..ced9104
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManager.java
@@ -0,0 +1,452 @@
+package org.apache.archiva.redback.rbac.jpa;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.rbac.*;
+import org.apache.archiva.redback.rbac.jpa.model.*;
+import org.apache.openjpa.persistence.Type;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Created by martin on 20.09.16.
+ */
+@Service("rbacManager#jpa")
+public class JpaRbacManager extends AbstractRBACManager {
+
+
+ @PersistenceContext(unitName = "redback-jpa")
+ EntityManager em;
+
+
+ private AtomicBoolean initialized = new AtomicBoolean(false);
+
+
+ public void setEntityManager(EntityManager em) {
+ this.em = em;
+ }
+
+
+
+ @Override
+ public Role createRole(String name) {
+ JpaRole role = new JpaRole();
+ role.setName(name);
+ return role;
+ }
+
+ @Override
+ public Role saveRole(Role role) throws RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid( role );
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ em.persist(role);
+
+ em.getTransaction().commit();
+ fireRbacRoleSaved(role);
+ for (Permission perm : role.getPermissions()) {
+ fireRbacPermissionSaved(perm);
+ }
+ return role;
+ }
+
+ @Override
+ public void saveRoles(Collection<Role> roles) throws RbacObjectInvalidException, RbacManagerException {
+ if ( roles == null )
+ {
+ // Nothing to do.
+ return;
+ }
+
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ for (Role role : roles ) {
+ RBACObjectAssertions.assertValid(role);
+ em.persist(role);
+ }
+ em.getTransaction().commit();
+ for (Role role : roles) {
+ fireRbacRoleSaved(role);
+ }
+ }
+
+ @Override
+ public Role getRole(String roleName) throws RbacObjectNotFoundException, RbacManagerException {
+ final EntityManager em = getEm();
+ TypedQuery<JpaRole> q = em.createQuery("SELECT r FROM JpaRole r WHERE r.name = :rolename", JpaRole.class);
+ q.setParameter("rolename",roleName);
+ return q.getSingleResult();
+ }
+
+ @Override
+ public List<Role> getAllRoles() throws RbacManagerException {
+ final EntityManager em = getEm();
+ Query q = em.createQuery("SELECT r FROM JpaRole r");
+ return q.getResultList();
+ }
+
+ @Override
+ public void removeRole(Role role) throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(role);
+ if (!(role instanceof JpaRole)) {
+ throw new RbacObjectInvalidException("Role object is not instance of JpaRole");
+ }
+ if ( role.isPermanent() )
+ {
+ throw new RbacPermanentException( "Unable to delete permanent role [" + role.getName() + "]" );
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ JpaRole myRole = em.find(JpaRole.class, role.getName());
+ if (myRole == null) {
+ throw new RbacObjectNotFoundException("Role not found "+role.getName());
+ }
+ myRole.setPermissions(new ArrayList<Permission>());
+ em.remove(myRole);
+ em.getTransaction().commit();
+ fireRbacRoleRemoved(myRole);
+ }
+
+ @Override
+ public Permission createPermission(String name) throws RbacManagerException {
+ JpaPermission permission = new JpaPermission();
+ permission.setName(name);
+ return permission;
+ }
+
+ @Override
+ public Permission createPermission(String name, String operationName, String resourceIdentifier) throws RbacManagerException {
+ JpaPermission permission = new JpaPermission();
+ permission.setName(name);
+ Operation op;
+ try {
+ op = getOperation(operationName);
+ } catch (RbacObjectNotFoundException ex) {
+ op = createOperation(operationName);
+ }
+ permission.setOperation(op);
+ Resource res;
+ try {
+ res = getResource(resourceIdentifier);
+ } catch (RbacObjectNotFoundException ex) {
+ res = createResource(resourceIdentifier);
+ }
+ permission.setResource(res);
+ return permission;
+ }
+
+ @Override
+ public Permission savePermission(Permission permission) throws RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(permission);
+ if (!(permission instanceof JpaPermission)) {
+ throw new RbacObjectInvalidException("The permission object ist not instance of JpaPermission");
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ em.persist(permission);
+ em.getTransaction().commit();
+ fireRbacPermissionSaved(permission);
+ return permission;
+ }
+
+ @Override
+ public Permission getPermission(String permissionName) throws RbacObjectNotFoundException, RbacManagerException {
+ final EntityManager em = getEm();
+ TypedQuery<Permission> q = em.createQuery("SELECT p FROM JpaPermission p WHERE p.name=:name", Permission.class);
+ q.setParameter("name",permissionName);
+ Permission res = q.getSingleResult();
+ if (res==null) {
+ throw new RbacObjectNotFoundException("Permission "+permissionName+" not found");
+ }
+ return res;
+ }
+
+ @Override
+ public List<Permission> getAllPermissions() throws RbacManagerException {
+ final EntityManager em = getEm();
+ TypedQuery<JpaPermission> q = em.createQuery("SELECT p FROM JpaPermission p",JpaPermission.class);
+ return (List<Permission>)(List<?>)q.getResultList();
+ }
+
+ @Override
+ public void removePermission(Permission permission) throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(permission);
+ if (!(permission instanceof JpaPermission)) {
+ throw new RbacObjectInvalidException("The permission object is not JpaPermission object");
+ }
+ if ( permission.isPermanent() )
+ {
+ throw new RbacPermanentException( "Unable to delete permanent permission [" + permission.getName() + "]" );
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ Permission p = em.find(JpaPermission.class, permission.getName());
+ if (p == null) {
+ throw new RbacObjectNotFoundException("Permission " + permission.getName() + " not found");
+ }
+ em.remove(p);
+ em.getTransaction().commit();
+ fireRbacPermissionRemoved(p);
+ }
+
+ @Override
+ public Operation createOperation(String name) throws RbacManagerException {
+ JpaOperation op = new JpaOperation();
+ op.setName(name);
+ return op;
+ }
+
+ @Override
+ public Operation saveOperation(Operation operation) throws RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(operation);
+ if (!(operation instanceof JpaOperation)) {
+ throw new RbacObjectInvalidException("Operation is not JpaOperation object");
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ em.persist(operation);
+ em.getTransaction().commit();
+ return operation;
+ }
+
+ @Override
+ public Operation getOperation(String operationName) throws RbacObjectNotFoundException, RbacManagerException {
+ final EntityManager em = getEm();
+ Operation op = em.find(JpaOperation.class,operationName);
+ if(op==null) {
+ throw new RbacObjectNotFoundException("Operation "+operationName+" not found");
+ }
+ return op;
+ }
+
+ @Override
+ public List<Operation> getAllOperations() throws RbacManagerException {
+ final EntityManager em = getEm();
+ Query q = em.createQuery("SELECT o FROM JpaOperation o");
+ return q.getResultList();
+ }
+
+ @Override
+ public void removeOperation(Operation operation) throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(operation);
+ if (!(operation instanceof JpaOperation)) {
+ throw new RbacObjectInvalidException("Operation is not JpaOperation object");
+ }
+ if ( operation.isPermanent() )
+ {
+ throw new RbacPermanentException( "Unable to delete permanent operation [" + operation.getName() + "]" );
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ Operation op = em.find(JpaOperation.class, operation.getName());
+ if (op==null) {
+ throw new RbacObjectNotFoundException("Operation not found "+operation.getName());
+ }
+ em.remove(op);
+ em.getTransaction().commit();
+
+ }
+
+ @Override
+ public Resource createResource(String identifier) throws RbacManagerException {
+ JpaResource resource = new JpaResource();
+ resource.setIdentifier(identifier);
+ return resource;
+ }
+
+ @Override
+ public Resource saveResource(Resource resource) throws RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(resource);
+ if (!(resource instanceof JpaResource)) {
+ throw new RbacObjectInvalidException("Resource is not JpaResource");
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ em.persist(resource);
+ em.getTransaction().commit();
+ return resource;
+ }
+
+ @Override
+ public Resource getResource(String resourceIdentifier) throws RbacObjectNotFoundException, RbacManagerException {
+ final EntityManager em = getEm();
+ Resource r = em.find(JpaResource.class,resourceIdentifier);
+ if (r==null) {
+ throw new RbacObjectNotFoundException("Resource "+resourceIdentifier+" not found");
+ }
+ return r;
+ }
+
+ @Override
+ public List<Resource> getAllResources() throws RbacManagerException {
+ final EntityManager em = getEm();
+ TypedQuery<JpaResource> q = em.createQuery("SELECT r FROM JpaResource r",JpaResource.class);
+ return (List<Resource>)(List<?>)q.getResultList();
+ }
+
+ @Override
+ public void removeResource(Resource resource) throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(resource);
+ if (!(resource instanceof JpaResource)) {
+ throw new RbacObjectInvalidException("Resource is not JpaResource");
+ }
+ if (resource.isPermanent()) {
+ throw new RbacObjectInvalidException("Unable to delete permanent resource ["+resource.getIdentifier()+ "]");
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ Resource res = em.find(JpaResource.class, resource.getIdentifier());
+ if (res==null) {
+ throw new RbacObjectNotFoundException("Resource "+resource.getIdentifier()+" not found");
+ }
+ em.remove(res);
+ em.getTransaction().commit();
+ }
+
+ @Override
+ public UserAssignment createUserAssignment(String principal) throws RbacManagerException {
+ JpaUserAssignment ua = new JpaUserAssignment();
+ ua.setPrincipal(principal);
+ return ua;
+ }
+
+ @Override
+ public UserAssignment saveUserAssignment(UserAssignment userAssignment) throws RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(userAssignment);
+ if (!(userAssignment instanceof JpaUserAssignment)) {
+ throw new RbacObjectInvalidException("Cannto save object that is not JpaUserAssignment");
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ em.persist(userAssignment);
+ em.getTransaction().commit();
+ fireRbacUserAssignmentSaved(userAssignment);
+ return userAssignment;
+ }
+
+ @Override
+ public UserAssignment getUserAssignment(String principal) throws RbacObjectNotFoundException, RbacManagerException {
+ final EntityManager em = getEm();
+ UserAssignment ua = em.find(JpaUserAssignment.class, principal);
+ if (ua==null) {
+ throw new RbacObjectNotFoundException("User assignment not found "+principal);
+ }
+ return ua;
+ }
+
+ @Override
+ public List<UserAssignment> getAllUserAssignments() throws RbacManagerException {
+ final EntityManager em = getEm();
+ Query q = em.createQuery("SELECT ua FROM JpaUserAssignment ua");
+ return q.getResultList();
+ }
+
+ @Override
+ public List<UserAssignment> getUserAssignmentsForRoles(Collection<String> roleNames) throws RbacManagerException {
+ final EntityManager em = getEm();
+ Query q = em.createQuery("SELECT ua FROM JpaUserAssignment ua, ua.roleNames rn WHERE rn IN :rolenames");
+ q.setParameter("rolenames",roleNames);
+ return q.getResultList();
+ }
+
+ @Override
+ public void removeUserAssignment(UserAssignment userAssignment) throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException {
+ RBACObjectAssertions.assertValid(userAssignment);
+ if (userAssignment.isPermanent()) {
+ throw new RbacObjectInvalidException("Cannot remove permanent object "+userAssignment.getPrincipal());
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ UserAssignment ua = em.find(UserAssignment.class, userAssignment.getPrincipal());
+ if (ua==null) {
+ throw new RbacObjectNotFoundException("User assignment not found "+userAssignment.getPrincipal());
+ }
+ em.remove(ua);
+ em.getTransaction().commit();
+ fireRbacUserAssignmentRemoved(userAssignment);
+ }
+
+ @Override
+ public void eraseDatabase() {
+ final EntityManager em = getEm();
+ // Deletion is a bit tricky, because the JPA bulk delete queries do not cascade
+ // or keep foreign keys into account.
+ em.getTransaction().begin();
+ TypedQuery<JpaPermission> tqp = em.createQuery("SELECT r FROM JpaPermission r",JpaPermission.class);
+ for(JpaPermission p : tqp.getResultList()) {
+ p.setOperation(null);
+ p.setResource(null);
+ }
+ TypedQuery<JpaRole> tqr = em.createQuery("SELECT r FROM JpaRole r",JpaRole.class);
+ for (JpaRole r : tqr.getResultList()) {
+ r.getPermissions().clear();
+ }
+ em.flush();
+ TypedQuery<JpaOperation> tqo = em.createQuery("SELECT o FROM JpaOperation o",JpaOperation.class);
+ for(JpaOperation o : tqo.getResultList()) {
+ em.remove(o);
+ }
+ TypedQuery<JpaResource> tqre = em.createQuery("SELECT re FROM JpaResource re",JpaResource.class);
+ for(JpaResource re : tqre.getResultList()) {
+ em.remove(re);
+ }
+ for (JpaPermission p : tqp.getResultList()) {
+ em.remove(p);
+ }
+ for (JpaRole r : tqr.getResultList()) {
+ em.remove(r);
+ }
+ TypedQuery<JpaUserAssignment> tqu = em.createQuery("SELECT ua FROM JpaUserAssignment ua", JpaUserAssignment.class);
+ for(JpaUserAssignment ua : tqu.getResultList()) {
+ em.remove(ua);
+ }
+ em.getTransaction().commit();
+
+
+ }
+
+ @Override
+ public String getDescriptionKey() {
+ return "archiva.redback.rbacmanager.jpa";
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ private EntityManager getEm() {
+ if (initialized.compareAndSet(false, true)) {
+ Query q = em.createQuery("SELECT COUNT(r.name) FROM JpaRole r");
+ boolean dbInit = q.getFirstResult()==0;
+ fireRbacInit(dbInit);
+ }
+ return em;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaOperation.java
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaOperation.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaOperation.java
new file mode 100644
index 0000000..66a41a1
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaOperation.java
@@ -0,0 +1,91 @@
+package org.apache.archiva.redback.rbac.jpa.model;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.rbac.Operation;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * Created by martin on 25.09.16.
+ */
+@Entity
+@Table(name="SECURITY_OPERATIONS")
+public class JpaOperation implements Operation, Serializable {
+
+ @Id
+ @Column(name="NAME")
+ private String name;
+ @Column(name="DESCRIPTION")
+ private String description;
+ @Column(name="PERMANENT")
+ private boolean permanent;
+
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public boolean isPermanent() {
+ return permanent;
+ }
+
+ @Override
+ public void setPermanent(boolean permanent) {
+ this.permanent = permanent;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ JpaOperation that = (JpaOperation) o;
+
+ return name.equals(that.name);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaPermission.java
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaPermission.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaPermission.java
new file mode 100644
index 0000000..4ac6989
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaPermission.java
@@ -0,0 +1,123 @@
+package org.apache.archiva.redback.rbac.jpa.model;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.rbac.Operation;
+import org.apache.archiva.redback.rbac.Permission;
+import org.apache.archiva.redback.rbac.Resource;
+import org.apache.archiva.redback.rbac.jpa.JpaRbacManager;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * Created by martin on 25.09.16.
+ */
+@Entity
+@Table(name="SECURITY_PERMISSIONS")
+public class JpaPermission implements Permission,Serializable {
+
+ @Id
+ @Column(name="NAME")
+ private String name;
+ @Column(name="DESCRIPTION")
+ private String description;
+ @Column(name="PERMANENT")
+ private boolean permanent;
+ @ManyToOne(cascade = CascadeType.PERSIST)
+ @JoinColumn(
+ name="OPERATION_NAME_OID",
+ referencedColumnName = "NAME"
+ )
+ private JpaOperation operation;
+ @ManyToOne(cascade = CascadeType.PERSIST)
+ @JoinColumn(
+ name="RESOURCE_IDENTIFIER_OID",
+ referencedColumnName = "IDENTIFIER"
+ )
+ private JpaResource resource;
+
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public boolean isPermanent() {
+ return permanent;
+ }
+
+ @Override
+ public void setPermanent(boolean permanent) {
+ this.permanent = permanent;
+ }
+
+ @Override
+ public Operation getOperation() {
+ return operation;
+ }
+
+ @Override
+ public void setOperation(Operation operation) {
+ this.operation = (JpaOperation)operation;
+ }
+
+ @Override
+ public Resource getResource() {
+ return resource;
+ }
+
+ @Override
+ public void setResource(Resource resource) {
+ this.resource = (JpaResource)resource;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ JpaPermission that = (JpaPermission) o;
+
+ return name.equals(that.name);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaResource.java
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaResource.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaResource.java
new file mode 100644
index 0000000..fc7ee77
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaResource.java
@@ -0,0 +1,91 @@
+package org.apache.archiva.redback.rbac.jpa.model;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.rbac.Resource;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+/**
+ * Created by martin on 25.09.16.
+ */
+@Entity
+@Table(name="SECURITY_RESOURCES")
+public class JpaResource implements Resource, Serializable {
+
+ @Id
+ @Column(name="IDENTIFIER")
+ private String identifier;
+ @Column(name="PATTERN")
+ private boolean pattern;
+ @Column(name="PERMANENT")
+ private boolean permanent;
+
+
+ @Override
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public void setIdentifier(String identifier) {
+ this.identifier = identifier;
+ }
+
+ @Override
+ public boolean isPattern() {
+ return pattern;
+ }
+
+ @Override
+ public void setPattern(boolean pattern) {
+ this.pattern = pattern;
+ }
+
+ @Override
+ public boolean isPermanent() {
+ return permanent;
+ }
+
+ @Override
+ public void setPermanent(boolean permanent) {
+ this.permanent = permanent;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ JpaResource that = (JpaResource) o;
+
+ return identifier.equals(that.identifier);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return identifier.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java
new file mode 100644
index 0000000..1f8a62c
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaRole.java
@@ -0,0 +1,172 @@
+package org.apache.archiva.redback.rbac.jpa.model;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.rbac.AbstractRole;
+import org.apache.archiva.redback.rbac.Permission;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by martin on 25.09.16.
+ */
+@Entity
+@Table(
+ name="SECURITY_ROLES"
+)
+public class JpaRole extends AbstractRole implements Serializable {
+
+ @Id
+ @Column(name="NAME")
+ private String name;
+ @Column(name="DESCRIPTION")
+ private String description;
+ @Column(name="ASSIGNABLE")
+ private boolean assignable;
+ @Column(name="PERMANENT")
+ private boolean permanent;
+ @ManyToMany(cascade = CascadeType.PERSIST)
+ @JoinTable(
+ name="SECURITY_ROLE_PERMISSION_MAP",
+ joinColumns={ @JoinColumn(name="NAME_OID", referencedColumnName="NAME") },
+ inverseJoinColumns = {
+ @JoinColumn(name="NAME_EID",referencedColumnName = "NAME")
+ }
+ )
+ List<JpaPermission> permissions = new ArrayList<JpaPermission>();
+
+ @ElementCollection
+ @CollectionTable(
+ name="SECURITY_ROLE_CHILDROLE_MAP",
+ joinColumns = {
+ @JoinColumn(name="NAME_OID",referencedColumnName = "NAME")
+ }
+ )
+ List<String> childRoleNames = new ArrayList<String>();
+
+
+
+ @Override
+ public void addPermission(Permission permission) {
+ if (permission instanceof JpaPermission) {
+ this.permissions.add((JpaPermission) permission);
+ }
+
+ }
+
+ @Override
+ public void addChildRoleName(String name) {
+ this.childRoleNames.add(name);
+ }
+
+ @Override
+ public List<String> getChildRoleNames() {
+ return childRoleNames;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public List<Permission> getPermissions() {
+ // Maybe better to create a new list?
+ return (List<Permission>)(List<?>)permissions;
+ }
+
+ @Override
+ public boolean isAssignable() {
+ return assignable;
+ }
+
+ @Override
+ public void removePermission(Permission permission) {
+ this.permissions.remove(permission);
+ }
+
+ @Override
+ public void setAssignable(boolean assignable) {
+ this.assignable=assignable;
+ }
+
+ @Override
+ public void setChildRoleNames(List<String> names) {
+ this.childRoleNames.clear();
+ this.childRoleNames.addAll(names);
+ }
+
+ @Override
+ public void setDescription(String description) {
+ this.description=description;
+
+ }
+
+ @Override
+ public void setName(String name) {
+ this.name=name;
+
+ }
+
+ @Override
+ public void setPermissions(List<Permission> permissions) {
+ this.permissions.clear();
+ for (Permission p : permissions) {
+ if (p instanceof JpaPermission) {
+ permissions.add(p);
+ }
+ }
+ }
+
+ @Override
+ public boolean isPermanent() {
+ return permanent;
+ }
+
+ @Override
+ public void setPermanent(boolean permanent) {
+ this.permanent=permanent;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ JpaRole jpaRole = (JpaRole) o;
+
+ return name.equals(jpaRole.name);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaUserAssignment.java
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaUserAssignment.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaUserAssignment.java
new file mode 100644
index 0000000..39e0b2d
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/main/java/org/apache/archiva/redback/rbac/jpa/model/JpaUserAssignment.java
@@ -0,0 +1,97 @@
+package org.apache.archiva.redback.rbac.jpa.model;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.rbac.AbstractUserAssignment;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Martin Stockhammer <ma...@apache.org> on 26.09.16.
+ */
+@Entity
+@Table(name="SECURITY_USER_ASSIGNMENTS")
+public class JpaUserAssignment extends AbstractUserAssignment implements Serializable {
+
+
+ @Id
+ @Column(name="PRINCIPAL")
+ private String principal;
+ @ElementCollection
+ @Column(name="STRING_ELE")
+ @CollectionTable(
+ name="SECURITY_USERASSIGNMENT_MAP",
+ joinColumns = {
+ @JoinColumn(name = "PRINCIPAL_OID", referencedColumnName = "PRINCIPAL")
+ }
+ )
+ private List<String> roleNames = new ArrayList<String>();
+ @Column(name="PERMANENT")
+ private boolean permanent = false;
+
+ @Override
+ public String getPrincipal() {
+ return principal;
+ }
+
+ @Override
+ public void setPrincipal(String principal) {
+ this.principal = principal;
+ }
+
+ @Override
+ public List<String> getRoleNames() {
+ return roleNames;
+ }
+
+ @Override
+ public void setRoleNames(List<String> roleNames) {
+ this.roleNames = roleNames;
+ }
+
+ @Override
+ public boolean isPermanent() {
+ return permanent;
+ }
+
+ @Override
+ public void setPermanent(boolean permanent) {
+ this.permanent = permanent;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ JpaUserAssignment that = (JpaUserAssignment) o;
+
+ return principal.equals(that.principal);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return principal.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManagerTest.java
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManagerTest.java b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManagerTest.java
new file mode 100644
index 0000000..3c5bc9f
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/java/org/apache/archiva/redback/rbac/jpa/JpaRbacManagerTest.java
@@ -0,0 +1,132 @@
+package org.apache.archiva.redback.rbac.jpa;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.common.jdo.test.StoreManagerDebug;
+import org.apache.archiva.redback.rbac.RbacManagerException;
+import org.apache.archiva.redback.tests.AbstractRbacManagerTestCase;
+import org.junit.Before;
+import org.springframework.test.annotation.DirtiesContext;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * JdoRbacManagerTest:
+ *
+ * @author Jesse McConnell
+ * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
+ */
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+public class JpaRbacManagerTest
+ extends AbstractRbacManagerTestCase
+{
+
+ @Inject
+ @Named(value = "rbacManager#jpa")
+ JpaRbacManager rbacManager;
+
+ public static int EVENTCOUNT = 2;
+
+ @Override
+ public void assertEventCount()
+ {
+ assertEquals( EVENTCOUNT, eventTracker.initCount );
+ }
+
+ /**
+ * Creates a new RbacStore which contains no data.
+ */
+ @Before
+ public void setUp()
+ throws Exception
+ {
+
+ super.setUp();
+ Properties props = new Properties();
+ InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("test.properties");
+ assert is!=null;
+ props.load(is);
+ is.close();
+ EntityManagerFactory emf = Persistence.createEntityManagerFactory("redback-jpa",props);
+
+ log.info("test setup");
+ rbacManager.setEntityManager(emf.createEntityManager());
+ super.setRbacManager(rbacManager);
+ assertNotNull(rbacManager);
+ log.info("injected rbac manager "+rbacManager);
+
+ }
+
+
+ @Override
+ public void testGetAssignedRoles()
+ throws RbacManagerException
+ {
+ super.testGetAssignedRoles();
+ }
+
+ @Override
+ public void testGetAssignedPermissionsDeep()
+ throws RbacManagerException
+ {
+ super.testGetAssignedPermissionsDeep();
+ }
+
+ @Override
+ protected void afterSetup()
+ {
+ super.afterSetup();
+ }
+
+ @Override
+ public void testLargeApplicationInit()
+ throws RbacManagerException
+ {
+ this.clearCache();
+ super.testLargeApplicationInit();
+ }
+
+ @Override
+ public void testGetRolesDeep()
+ throws RbacManagerException
+ {
+ this.clearCache();
+ super.testGetRolesDeep();
+ }
+
+
+ @Override
+ public void testStoreInitialization()
+ throws Exception
+ {
+ this.clearCache();
+ rbacManager.eraseDatabase();
+ eventTracker.rbacInit( true );
+ super.testStoreInitialization();
+ assertEquals( EVENTCOUNT, eventTracker.initCount );
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/spring-context.xml
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/spring-context.xml b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/spring-context.xml
new file mode 100644
index 0000000..abee0b5
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/spring-context.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+
+<!--
+ ~ 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.
+ -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+ <context:component-scan base-package="org.apache.archiva.redback.rbac.jpa" />
+
+ <bean name="userConfiguration#default" class="org.apache.archiva.redback.configuration.DefaultUserConfiguration">
+ <property name="registry" ref="test-conf"/>
+ </bean>
+
+ <bean name="commons-configuration" class="org.apache.archiva.redback.components.registry.commons.CommonsConfigurationRegistry">
+ </bean>
+
+ <alias name="commons-configuration" alias="test-conf"/>
+
+</beans>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/test.properties
----------------------------------------------------------------------
diff --git a/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/test.properties b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/test.properties
new file mode 100644
index 0000000..df848c4
--- /dev/null
+++ b/redback-rbac/redback-rbac-providers/redback-rbac-jpa/src/test/resources/test.properties
@@ -0,0 +1,22 @@
+# 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.
+openjpa.ConnectionURL=jdbc:hsqldb:mem:reback-jpa
+openjpa.ConnectionDriverName=org.hsqldb.jdbcDriver
+openjpa.ConnectionUserName=sa
+openjpa.ConnectionPassword=
+openjp.Log=DefaultLevel=WARN,Tool=INFO
+openjpa.jdbc.SynchronizeMappings=buildSchema(ForeignKeys=true)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-users/redback-users-providers/pom.xml
----------------------------------------------------------------------
diff --git a/redback-users/redback-users-providers/pom.xml b/redback-users/redback-users-providers/pom.xml
index 9ddab02..4a90648 100644
--- a/redback-users/redback-users-providers/pom.xml
+++ b/redback-users/redback-users-providers/pom.xml
@@ -39,5 +39,6 @@
<module>redback-users-jdo</module>
<module>redback-users-ldap</module>
<module>redback-users-configurable</module>
+ <module>redback-users-jpa</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-users/redback-users-providers/redback-users-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/redback-users/redback-users-providers/redback-users-jpa/pom.xml b/redback-users/redback-users-providers/redback-users-jpa/pom.xml
new file mode 100644
index 0000000..2606b71
--- /dev/null
+++ b/redback-users/redback-users-providers/redback-users-jpa/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>redback-users-providers</artifactId>
+ <groupId>org.apache.archiva.redback</groupId>
+ <version>2.5-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>redback-users-jpa</artifactId>
+ <packaging>jar</packaging>
+ <name>Redback :: Users Provider :: JPA</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>jsr250-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-policy</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-common-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa</artifactId>
+ <version>${openjpa.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva.redback</groupId>
+ <artifactId>redback-users-tests</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserManager.java
----------------------------------------------------------------------
diff --git a/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserManager.java b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserManager.java
new file mode 100644
index 0000000..c4c83f6
--- /dev/null
+++ b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserManager.java
@@ -0,0 +1,307 @@
+package org.apache.archiva.redback.users.jpa;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.policy.UserSecurityPolicy;
+import org.apache.archiva.redback.users.*;
+import org.apache.archiva.redback.users.jpa.model.JpaUser;
+import org.apache.commons.lang.StringUtils;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.persistence.*;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Created by martin on 20.09.16.
+ */
+@org.springframework.stereotype.Service("userManager#jpa")
+public class JpaUserManager extends AbstractUserManager {
+
+
+ @PersistenceContext(unitName = "redback-jpa")
+ EntityManager em;
+
+ @Inject
+ private UserSecurityPolicy userSecurityPolicy;
+
+ // JpaUserManager is a singleton and initialization should be thread safe
+ private AtomicBoolean initialized = new AtomicBoolean(false);
+
+
+ public void setEntityManager(EntityManager em) {
+ this.em = em;
+ }
+
+ @Override
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ @Override
+ public String getId() {
+ return "jpa";
+ }
+
+ private EntityManager getEm() {
+ if (initialized.compareAndSet(false,true)) {
+ Query q = em.createQuery("SELECT COUNT(u.username) FROM JpaUser u");
+ boolean dbInit = q.getFirstResult()==0;
+ fireUserManagerInit(dbInit);
+ }
+ return em;
+ }
+
+
+ @Override
+ public User createUser(String username, String fullName, String emailAddress) throws UserManagerException {
+
+ JpaUser user = new JpaUser();
+ user.setUsername(username);
+ user.setFullName(fullName);
+ user.setEmail(emailAddress);
+ return user;
+ }
+
+ @Override
+ public UserQuery createUserQuery() {
+ return new JpaUserQuery();
+ }
+
+ @Override
+ public List<User> getUsers() throws UserManagerException {
+ final EntityManager em = getEm();
+ Query q= em.createQuery("SELECT x from JpaUser x");
+ return q.getResultList();
+ }
+
+ @Override
+ public List<User> getUsers(boolean orderAscending) throws UserManagerException {
+ final EntityManager em = getEm();
+ final String orderFlag = orderAscending ? "ASC" : "DESC";
+ Query q = em.createQuery("SELECT u FROM JpaUser u ORDER BY u.username "+orderFlag);
+ return q.getResultList();
+ }
+
+ @Override
+ public User addUser(User user) throws UserManagerException {
+ EntityManager em = getEm();
+ if ( !( user instanceof JpaUser ) )
+ {
+ throw new UserManagerException( "Unable to Add User. User object " + user.getClass().getName() +
+ " is not an instance of " + JpaUser.class.getName() );
+ }
+
+ if ( StringUtils.isEmpty( user.getUsername() ) )
+ {
+ throw new IllegalStateException(
+ Messages.getString( "user.manager.cannot.add.user.without.username" ) ); //$NON-NLS-1$
+ }
+
+ userSecurityPolicy.extensionChangePassword( user );
+
+ fireUserManagerUserAdded( user );
+
+ // TODO: find a better solution
+ // workaround for avoiding the admin from providing another password on the next login after the
+ // admin account has been created
+ // extensionChangePassword by default sets the password change status to false
+ if ( "admin".equals( user.getUsername() ) )
+ {
+ user.setPasswordChangeRequired( false );
+ }
+ else
+ {
+ user.setPasswordChangeRequired( true );
+ }
+ em.getTransaction().begin();
+ em.persist((JpaUser)user);
+ em.getTransaction().commit();
+ return user;
+ }
+
+ @Override
+ public User updateUser(User user) throws UserNotFoundException, UserManagerException {
+ return updateUser(user, false);
+ }
+
+ @Override
+ public User findUser(String username) throws UserNotFoundException, UserManagerException {
+ if (username==null) {
+ throw new UserNotFoundException("Username was <null>");
+ }
+ final EntityManager em = getEm();
+ TypedQuery<JpaUser> q = em.createQuery("SELECT u FROM JpaUser u WHERE LOWER(u.username)=:uname", JpaUser.class);
+ q.setParameter("uname",username.toLowerCase());
+ User result;
+ try {
+ result = q.getSingleResult();
+ } catch (NoResultException ex ) {
+ throw new UserNotFoundException(ex);
+ }
+ return result;
+ }
+
+ @Override
+ public User findUser(String username, boolean useCache) throws UserNotFoundException, UserManagerException {
+ return findUser(username);
+ }
+
+ @Override
+ public List<User> findUsersByUsernameKey(String usernameKey, boolean orderAscending) throws UserManagerException {
+ return findUsers("username",usernameKey,"username",orderAscending);
+ }
+
+ @Override
+ public List<User> findUsersByFullNameKey(String fullNameKey, boolean orderAscending) throws UserManagerException {
+ return findUsers("fullName",fullNameKey,"username",orderAscending);
+ }
+
+ @Override
+ public List<User> findUsersByEmailKey(String emailKey, boolean orderAscending) throws UserManagerException {
+ return findUsers("email",emailKey,"username", orderAscending);
+ }
+
+ @Override
+ public List<User> findUsersByQuery(final UserQuery queryParam) throws UserManagerException {
+ final EntityManager em = getEm();
+ final JpaUserQuery query = (JpaUserQuery)queryParam;
+ String orderByAttribute = "";
+ if (UserQuery.ORDER_BY_EMAIL.equals(query.getOrderBy())) {
+ orderByAttribute="email";
+ } else if (UserQuery.ORDER_BY_FULLNAME.equals(query.getOrderBy())) {
+ orderByAttribute="fullName";
+ } else if (UserQuery.ORDER_BY_USERNAME.equals(query.getOrderBy())) {
+ orderByAttribute="username";
+ } else {
+ throw new IllegalArgumentException("Unknown order attribute "+query.getOrderBy());
+ }
+ StringBuilder sb = new StringBuilder("SELECT u FROM JpaUser u ");
+ if (query.hasUsername()||query.hasFullName()||query.hasEmail()) {
+ sb.append("WHERE ");
+ }
+ boolean checkBefore = false;
+ if (query.hasUsername()) {
+ sb.append("LOWER(u.username) LIKE :username ");
+ checkBefore=true;
+ }
+ if (query.hasEmail()) {
+ if (checkBefore) {
+ sb.append("AND ");
+ }
+ checkBefore=true;
+ sb.append("LOWER(u.email) LIKE :email ");
+ }
+ if (query.hasFullName()) {
+ if (checkBefore) {
+ sb.append("AND ");
+ }
+ sb.append("LOWER(u.fullName) LIKE :fullname ");
+ }
+ if (query.getOrderBy()!=null && !"".equals(query.getOrderBy())) {
+ sb.append("ORDER BY u.").append(orderByAttribute).append(query.isAscending() ? " ASC" : " DESC");
+ }
+ TypedQuery<User> q = em.createQuery(sb.toString(), User.class);
+ if (query.hasUsername()) {
+ q.setParameter("username", "%"+query.getUsername().toLowerCase()+"%");
+ }
+ if (query.hasEmail()) {
+ q.setParameter("email", "%"+query.getEmail().toLowerCase()+"%");
+ }
+ if (query.hasFullName()) {
+ q.setParameter("fullname", "%"+query.getFullName().toLowerCase()+"%");
+ }
+ q.setFirstResult((int)query.getFirstResult()).setMaxResults((int)query.getMaxResults());
+ return q.getResultList();
+ }
+
+ private List<User> findUsers(final String attribute, final String pattern,
+ final String orderAttribute, final boolean orderAscending) {
+ final EntityManager em = getEm();
+ StringBuilder sb = new StringBuilder("SELECT u FROM JpaUser u WHERE LOWER(u.");
+ sb.append(attribute).append(") LIKE :patternvalue ORDER BY u.").append(orderAttribute);
+ sb.append(orderAscending ? " ASC" : " DESC");
+ TypedQuery<User> q = em.createQuery(sb.toString(),User.class);
+ q.setParameter("patternvalue","%"+pattern.toLowerCase()+"%");
+ return q.getResultList();
+ }
+
+ @Override
+ public boolean userExists(String principal) throws UserManagerException {
+ EntityManager em = getEm();
+ JpaUser user = em.find(JpaUser.class, principal);
+ return user != null;
+ }
+
+
+
+ @Override
+ public void deleteUser(String username) throws UserNotFoundException, UserManagerException {
+ final EntityManager em = getEm();
+ User u = findUser(username);
+ if (u.isPermanent()) {
+ throw new PermanentUserException("User "+username+" cannot be deleted");
+ }
+ em.getTransaction().begin();
+ em.remove(u);
+ em.getTransaction().commit();
+ fireUserManagerUserRemoved(u);
+ }
+
+ @Override
+ public void addUserUnchecked(User user) throws UserManagerException {
+
+ }
+
+ @Override
+ public void eraseDatabase() {
+ EntityManager em = getEm();
+ em.getTransaction().begin();
+ Query q = em.createQuery("DELETE FROM JpaUser u");
+ q.executeUpdate();
+ em.getTransaction().commit();
+ }
+
+ @Override
+ public User updateUser(User user, boolean passwordChangeRequired) throws UserNotFoundException, UserManagerException {
+ if ( StringUtils.isNotEmpty( user.getPassword() ) )
+ {
+ userSecurityPolicy.extensionChangePassword( user, passwordChangeRequired );
+ }
+ final EntityManager em = getEm();
+ em.getTransaction().begin();
+ em.persist((JpaUser)user);
+ em.getTransaction().commit();
+ fireUserManagerUserUpdated(user);
+ return user;
+ }
+
+ @Override
+ public String getDescriptionKey() {
+ return null;
+ }
+
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserQuery.java
----------------------------------------------------------------------
diff --git a/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserQuery.java b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserQuery.java
new file mode 100644
index 0000000..d48a59c
--- /dev/null
+++ b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/JpaUserQuery.java
@@ -0,0 +1,123 @@
+package org.apache.archiva.redback.users.jpa;
+
+/*
+ * 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.
+ */
+
+import org.apache.archiva.redback.users.UserQuery;
+
+import java.util.Arrays;
+
+/**
+ * Created by martin on 23.09.16.
+ */
+public class JpaUserQuery implements UserQuery {
+
+ private String username;
+ private String email;
+ private String fullName;
+ private long firstResult=0;
+ private long maxResults=Integer.MAX_VALUE;
+ private boolean ascending=true;
+
+ private String orderBy="username";
+
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ @Override
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public boolean hasUsername() {
+ return username != null && !"".equals(username);
+ }
+
+ @Override
+ public String getEmail() {
+ return email;
+ }
+
+ @Override
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public boolean hasEmail() {
+ return email!=null && !"".equals(email);
+ }
+
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ @Override
+ public void setFullName(String fullName) {
+ this.fullName = fullName;
+ }
+
+ public boolean hasFullName() {
+ return fullName!=null && !"".equals(fullName);
+ }
+
+ @Override
+ public long getFirstResult() {
+ return firstResult;
+ }
+
+ public void setFirstResult(int firstResult) {
+ this.firstResult = firstResult;
+ }
+
+ @Override
+ public long getMaxResults() {
+ return maxResults;
+ }
+
+ public void setMaxResults(int maxResults) {
+ this.maxResults = maxResults;
+ }
+
+ @Override
+ public boolean isAscending() {
+ return ascending;
+ }
+
+ @Override
+ public void setAscending(boolean ascending) {
+ this.ascending = ascending;
+ }
+
+
+ @Override
+ public String getOrderBy() {
+ return orderBy;
+ }
+
+ @Override
+ public void setOrderBy(String orderBy) {
+ if (!UserQuery.ALLOWED_ORDER_FIELDS.contains(orderBy)) {
+ throw new IllegalArgumentException("Order attribute not allowed: "+orderBy);
+ }
+ this.orderBy = orderBy;
+ }
+}
http://git-wip-us.apache.org/repos/asf/archiva-redback-core/blob/62efc70b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/model/JpaUser.java
----------------------------------------------------------------------
diff --git a/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/model/JpaUser.java b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/model/JpaUser.java
new file mode 100644
index 0000000..04f441e
--- /dev/null
+++ b/redback-users/redback-users-providers/redback-users-jpa/src/main/java/org/apache/archiva/redback/users/jpa/model/JpaUser.java
@@ -0,0 +1,206 @@
+package org.apache.archiva.redback.users.jpa.model;
+
+/*
+ * 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.
+ */
+
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Created by martin on 20.09.16.
+ */
+@Entity
+@Table(name="JDOUSER")
+public class JpaUser implements org.apache.archiva.redback.users.User {
+
+ @Id
+ private String username;
+
+ private String fullName;
+ private String email;
+ private String encodedPassword;
+ private Date lastPasswordChange;
+ @ElementCollection
+ private List<String> previousEncodedPasswords = new ArrayList<String>();
+ private boolean permanent;
+ private boolean locked;
+ private boolean passwordChangeRequired;
+ private boolean validated;
+ private int countFailedLoginAttempts;
+ private Date accountCreationDate;
+ private Date lastLoginDate;
+ private String rawPassword;
+
+
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ @Override
+ public void setUsername(String name) {
+ this.username = name;
+ }
+
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ @Override
+ public void setFullName(String name) {
+ this.fullName = name;
+ }
+
+ @Override
+ public String getEmail() {
+ return email;
+ }
+
+ @Override
+ public void setEmail(String address) {
+ this.email = address;
+ }
+
+ @Override
+ public String getPassword() {
+ return rawPassword;
+ }
+
+ @Override
+ public void setPassword(String rawPassword) {
+ this.rawPassword = rawPassword;
+ }
+
+ @Override
+ public String getEncodedPassword() {
+ return encodedPassword;
+ }
+
+ @Override
+ public void setEncodedPassword(String encodedPassword) {
+ this.encodedPassword = encodedPassword;
+ }
+
+ @Override
+ public Date getLastPasswordChange() {
+ return lastPasswordChange;
+ }
+
+ @Override
+ public void setLastPasswordChange(Date passwordChangeDate) {
+ this.lastPasswordChange = lastPasswordChange;
+ }
+
+ @Override
+ public List<String> getPreviousEncodedPasswords() {
+ return previousEncodedPasswords;
+ }
+
+ @Override
+ public void setPreviousEncodedPasswords(List<String> encodedPasswordList) {
+ this.previousEncodedPasswords.clear();
+ this.previousEncodedPasswords.addAll(encodedPasswordList);
+ }
+
+ @Override
+ public void addPreviousEncodedPassword(String encodedPassword) {
+ this.previousEncodedPasswords.add(encodedPassword);
+ }
+
+ @Override
+ public boolean isPermanent() {
+ return permanent;
+ }
+
+ @Override
+ public void setPermanent(boolean permanent) {
+ this.permanent = permanent;
+ }
+
+ @Override
+ public boolean isLocked() {
+ return locked;
+ }
+
+ @Override
+ public void setLocked(boolean locked) {
+ this.locked = locked;
+ }
+
+ @Override
+ public boolean isPasswordChangeRequired() {
+ return passwordChangeRequired;
+ }
+
+ @Override
+ public void setPasswordChangeRequired(boolean changeRequired) {
+ this.passwordChangeRequired = changeRequired;
+ }
+
+ @Override
+ public boolean isValidated() {
+ return validated;
+ }
+
+ @Override
+ public void setValidated(boolean valid) {
+ this.validated = valid;
+ }
+
+ @Override
+ public int getCountFailedLoginAttempts() {
+ return countFailedLoginAttempts;
+ }
+
+ @Override
+ public void setCountFailedLoginAttempts(int count) {
+ this.countFailedLoginAttempts = count;
+ }
+
+ @Override
+ public Date getAccountCreationDate() {
+ return accountCreationDate;
+ }
+
+ @Override
+ public void setAccountCreationDate(Date date) {
+ this.accountCreationDate = date;
+ }
+
+ @Override
+ public Date getLastLoginDate() {
+ return lastLoginDate;
+ }
+
+ @Override
+ public void setLastLoginDate(Date date) {
+ this.lastLoginDate = date;
+ }
+
+ @Override
+ public String getUserManagerId() {
+ return null;
+ }
+}