Adding JPA implementation of users and rbac provider

Uses OpenJPA
This commit is contained in:
Martin Stockhammer 2016-09-27 23:13:03 +02:00
parent d17c6ffb9d
commit 62efc70bd2
25 changed files with 2304 additions and 1 deletions

14
pom.xml
View File

@ -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>
@ -299,6 +301,16 @@
<artifactId>redback-integrations-security</artifactId>
<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>
@ -930,7 +942,7 @@
<descriptorRefs>
<descriptorRef>${sourceReleaseAssemblyDescriptor}</descriptorRef>
</descriptorRefs>
<tarLongFileFormat>gnu</tarLongFileFormat>
<tarLongFileMode>gnu</tarLongFileMode>
</configuration>
</execution>
</executions>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,86 @@
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.User;
import org.apache.archiva.redback.users.UserManager;
import org.apache.archiva.redback.users.provider.test.AbstractUserManagerTestCase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Created by martin on 21.09.16.
*/
public class JpaUserManagerTest extends AbstractUserManagerTestCase {
Log log = LogFactory.getLog(JpaUserManagerTest.class);
@Inject
@Named("userManager#jpa")
JpaUserManager jpaUserManager;
@Inject
private UserSecurityPolicy securityPolicy;
@Before
@Override
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");
jpaUserManager.setEntityManager(emf.createEntityManager());
super.setUserManager(jpaUserManager);
assertNotNull(jpaUserManager);
log.info("injected usermanager "+jpaUserManager);
// create the factory defined by the "openjpa" entity-manager entry
}
@Test
public void testInit() {
jpaUserManager.initialize();
}
}

View File

@ -0,0 +1,50 @@
<?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.users.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">
<property name="properties">
<value>
<![CDATA[
<configuration>
<properties fileName="test.properties" config-name="properties"/>
</configuration>
]]>
</value>
</property>
</bean>
<alias name="commons-configuration" alias="test-conf"/>
</beans>

View File

@ -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)

View File

@ -97,10 +97,12 @@ public class AbstractUserManagerTestCase
throws UserManagerException
{
assertNotNull(userManager);
getUserManager().eraseDatabase();
getEventTracker().userManagerInit( true );
assertNotNull( getUserManager() );
assertNotNull(userManager.getUsers());
assertEquals( "New UserManager should contain no users. " + userManager.getUsers(), 0,
userManager.getUsers().size() );
}