blob: ac565a3c1653dcc57b98f2747a5b568b008cc415 [file] [log] [blame]
package org.apache.archiva.redback.rbac.jdo;
/*
* 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.AbstractRBACManager;
import org.apache.archiva.redback.rbac.Operation;
import org.apache.archiva.redback.rbac.RBACManagerListener;
import org.apache.archiva.redback.rbac.RbacManagerException;
import org.apache.archiva.redback.rbac.RbacObjectInvalidException;
import org.apache.archiva.redback.rbac.RbacObjectNotFoundException;
import org.apache.archiva.redback.rbac.RbacPermanentException;
import org.apache.archiva.redback.rbac.Resource;
import org.apache.archiva.redback.rbac.Role;
import org.apache.archiva.redback.rbac.UserAssignment;
import org.apache.archiva.redback.rbac.Permission;
import org.apache.archiva.redback.rbac.RBACObjectAssertions;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import java.util.Collection;
import java.util.List;
/**
* JdoRbacManager:
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @author Jesse McConnell
*
*/
@Service( "rbacManager#jdo" )
public class JdoRbacManager
extends AbstractRBACManager
implements RBACManagerListener
{
@Inject
private JdoTool jdo;
private boolean enableCache = true;
// private static final String ROLE_DETAIL = "role-child-detail";
private static final String ROLE_DETAIL = null;
// ----------------------------------------------------------------------
// Role methods
// ----------------------------------------------------------------------
/**
* Creates an implementation specific {@link Role}.
*
* Note: this method does not add the {@link Role} to the underlying store.
* a call to {@link #saveRole(Role)} is required to track the role created with this
* method call.
*
* @param name the name.
* @return the new {@link Role} object with an empty (non-null) {@link Role#getChildRoleNames()} object.
*/
public Role createRole( String name )
{
Role role;
try
{
role = getRole( name );
}
catch ( RbacManagerException e )
{
role = new JdoRole();
role.setName( name );
}
return role;
}
/**
* Method addRole
*
* @param role
*/
public Role saveRole( Role role )
throws RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( role );
return jdo.saveObject( role, new String[]{ ROLE_DETAIL } );
}
public boolean roleExists( Role role )
{
return jdo.objectExists( role );
}
public boolean roleExists( String name )
{
try
{
return jdo.objectExistsById( JdoRole.class, name );
}
catch ( RbacManagerException e )
{
return false;
}
}
/**
* @param roleName
* @return
* @throws RbacObjectNotFoundException
* @throws RbacManagerException
*/
public Role getRole( String roleName )
throws RbacObjectNotFoundException, RbacManagerException
{
return jdo.getObjectById( JdoRole.class, roleName, ROLE_DETAIL );
}
/**
* Method getRoles
*/
@SuppressWarnings( "unchecked" )
public List<Role> getAllRoles()
throws RbacManagerException
{
return (List<Role>) jdo.getAllObjects( JdoRole.class );
}
public void removeRole( Role role )
throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( role );
if ( role.isPermanent() )
{
throw new RbacPermanentException( "Unable to delete permanent role [" + role.getName() + "]" );
}
jdo.removeObject( role );
}
public void saveRoles( Collection<Role> roles )
throws RbacObjectInvalidException, RbacManagerException
{
if ( roles == null )
{
// Nothing to do.
return;
}
// This is done in JdoRbacManager as opposed to JdoTool as we need to assertValid() on each role and
// also wrap the entire collection into a single atomic save/makePersistent.
PersistenceManager pm = jdo.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try
{
tx.begin();
for ( Role role : roles )
{
if ( ( JDOHelper.getObjectId( role ) != null ) && !JDOHelper.isDetached( role ) )
{
// This is a fatal error that means we need to fix our code.
// Leave it as a JDOUserException, it's intentional.
throw new RbacManagerException( "Existing Role is not detached: " + role );
}
RBACObjectAssertions.assertValid( role );
pm.makePersistent( role );
}
tx.commit();
}
finally
{
jdo.rollbackIfActive( tx );
}
}
// ----------------------------------------------------------------------
// Permission methods
// ----------------------------------------------------------------------
/**
* Creates an implementation specific {@link Permission}.
*
* Note: this method does not add the {@link Permission} to the underlying store.
* a call to {@link #savePermission(Permission)} is required to track the permission created
* with this method call.
*
* @param name the name.
* @return the new Permission.
* @throws RbacManagerException
*/
public Permission createPermission( String name )
throws RbacManagerException
{
Permission permission;
try
{
permission = getPermission( name );
log.debug( "Create Permission [{}] Returning Existing.", name );
}
catch ( RbacObjectNotFoundException e )
{
permission = new JdoPermission();
permission.setName( name );
log.debug( "Create Permission [{}] New JdoPermission.", name );
}
return permission;
}
/**
* Creates an implementation specific {@link Permission} with specified {@link Operation},
* and {@link Resource} identifiers.
*
* Note: this method does not add the Permission, Operation, or Resource to the underlying store.
* a call to {@link #savePermission(Permission)} is required to track the permission, operation,
* or resource created with this method call.
*
* @param name the name.
* @param operationName the {@link Operation#setName(String)} value
* @param resourceIdentifier the {@link Resource#setIdentifier(String)} value
* @return the new Permission.
* @throws RbacManagerException
*/
public Permission createPermission( String name, String operationName, String resourceIdentifier )
throws RbacManagerException
{
Permission permission = new JdoPermission();
permission.setName( name );
Operation operation;
try
{
operation = getOperation( operationName );
}
catch ( RbacObjectNotFoundException e )
{
operation = new JdoOperation();
operation.setName( operationName );
}
permission.setOperation( operation );
Resource resource;
try
{
resource = getResource( resourceIdentifier );
}
catch ( RbacObjectNotFoundException e )
{
resource = new JdoResource();
resource.setIdentifier( resourceIdentifier );
}
permission.setResource( resource );
return permission;
}
public Permission savePermission( Permission permission )
throws RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( permission );
return jdo.saveObject( permission, null );
}
public boolean permissionExists( Permission permission )
{
return jdo.objectExists( permission );
}
public boolean permissionExists( String name )
{
try
{
return jdo.objectExistsById( JdoPermission.class, name );
}
catch ( RbacManagerException e )
{
return false;
}
}
public Permission getPermission( String permissionName )
throws RbacObjectNotFoundException, RbacManagerException
{
return jdo.getObjectById( JdoPermission.class, permissionName, null );
}
@SuppressWarnings( "unchecked" )
public List<Permission> getAllPermissions()
throws RbacManagerException
{
return (List<Permission>) jdo.getAllObjects( JdoPermission.class );
}
public void removePermission( Permission permission )
throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( permission );
if ( permission.isPermanent() )
{
throw new RbacPermanentException( "Unable to delete permanent permission [" + permission.getName() + "]" );
}
jdo.removeObject( permission );
}
// ----------------------------------------------------------------------
// Operation methods
// ----------------------------------------------------------------------
/**
* Creates an implementation specific {@link Operation}.
*
* Note: this method does not add the {@link Operation} to the underlying store.
* a call to {@link #saveOperation(Operation)} is required to track the operation created
* with this method call.
*
* @param name the name.
* @return the new Operation.
* @throws RbacManagerException
*/
public Operation createOperation( String name )
throws RbacManagerException
{
Operation operation;
try
{
operation = getOperation( name );
}
catch ( RbacObjectNotFoundException e )
{
operation = new JdoOperation();
operation.setName( name );
}
return operation;
}
public Operation saveOperation( Operation operation )
throws RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( operation );
return jdo.saveObject( operation, null );
}
public boolean operationExists( Operation operation )
{
return jdo.objectExists( operation );
}
public boolean operationExists( String name )
{
try
{
return jdo.objectExistsById( JdoOperation.class, name );
}
catch ( RbacManagerException e )
{
return false;
}
}
public Operation getOperation( String operationName )
throws RbacObjectNotFoundException, RbacManagerException
{
return jdo.getObjectById( JdoOperation.class, operationName, null );
}
@SuppressWarnings( "unchecked" )
public List<Operation> getAllOperations()
throws RbacManagerException
{
return (List<Operation>) jdo.getAllObjects( JdoOperation.class );
}
public void removeOperation( Operation operation )
throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( operation );
if ( operation.isPermanent() )
{
throw new RbacPermanentException( "Unable to delete permanent operation [" + operation.getName() + "]" );
}
jdo.removeObject( operation );
}
// ----------------------------------------------------------------------
// Resource methods
// ----------------------------------------------------------------------
/**
* Creates an implementation specific {@link Resource}.
*
* Note: this method does not add the {@link Resource} to the underlying store.
* a call to {@link #saveResource(Resource)} is required to track the resource created
* with this method call.
*
* @param identifier the identifier.
* @return the new Resource.
* @throws RbacManagerException
*/
public Resource createResource( String identifier )
throws RbacManagerException
{
Resource resource;
try
{
resource = getResource( identifier );
log.debug( "Create Resource [ {} ] Returning Existing.", identifier );
}
catch ( RbacObjectNotFoundException e )
{
resource = new JdoResource();
resource.setIdentifier( identifier );
log.debug( "Create Resource [ {} ] New JdoResource.", identifier );
}
return resource;
}
public Resource saveResource( Resource resource )
throws RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( resource );
return jdo.saveObject( resource, null );
}
public boolean resourceExists( Resource resource )
{
return jdo.objectExists( resource );
}
public boolean resourceExists( String identifier )
{
try
{
return jdo.objectExistsById( JdoResource.class, identifier );
}
catch ( RbacManagerException e )
{
return false;
}
}
public Resource getResource( String resourceIdentifier )
throws RbacObjectNotFoundException, RbacManagerException
{
return jdo.getObjectById( JdoResource.class, resourceIdentifier, null );
}
@SuppressWarnings( "unchecked" )
public List<Resource> getAllResources()
throws RbacManagerException
{
return (List<Resource>) jdo.getAllObjects( JdoResource.class );
}
public void removeResource( Resource resource )
throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( resource );
if ( resource.isPermanent() )
{
throw new RbacPermanentException(
"Unable to delete permanent resource [" + resource.getIdentifier() + "]" );
}
jdo.removeObject( resource );
}
// ----------------------------------------------------------------------
// User Assignment methods
// ----------------------------------------------------------------------
/**
* Creates an implementation specific {@link UserAssignment}.
*
* Note: this method does not add the {@link UserAssignment} to the underlying store.
* a call to {@link #saveUserAssignment(UserAssignment)} is required to track the user
* assignment created with this method call.
*
* @param principal the principal reference to the user.
* @return the new UserAssignment with an empty (non-null) {@link UserAssignment#getRoleNames()} object.
*/
public UserAssignment createUserAssignment( String principal )
{
UserAssignment ua;
try
{
ua = getUserAssignment( principal );
}
catch ( RbacManagerException e )
{
ua = new JdoUserAssignment();
ua.setPrincipal( principal );
}
return ua;
}
/**
* Method addUserAssignment
*
* @param userAssignment
*/
public UserAssignment saveUserAssignment( UserAssignment userAssignment )
throws RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( "Save User Assignment", userAssignment );
fireRbacUserAssignmentSaved( userAssignment );
return jdo.saveObject( userAssignment, new String[]{ ROLE_DETAIL } );
}
public boolean userAssignmentExists( String principal )
{
try
{
return jdo.objectExistsById( JdoUserAssignment.class, principal );
}
catch ( RbacManagerException e )
{
return false;
}
}
public boolean userAssignmentExists( UserAssignment assignment )
{
return jdo.objectExists( assignment );
}
public UserAssignment getUserAssignment( String principal )
throws RbacObjectNotFoundException, RbacManagerException
{
return jdo.getObjectById( JdoUserAssignment.class, principal, ROLE_DETAIL );
}
/**
* Method getAssignments
*/
@SuppressWarnings( "unchecked" )
public List<UserAssignment> getAllUserAssignments()
throws RbacManagerException
{
return (List<UserAssignment>) jdo.getAllObjects( JdoUserAssignment.class );
}
/**
* Method getUserAssignmentsForRoles
*/
@SuppressWarnings( "unchecked" )
public List<UserAssignment> getUserAssignmentsForRoles( Collection<String> roleNames )
throws RbacManagerException
{
return (List<UserAssignment>) jdo.getUserAssignmentsForRoles( JdoUserAssignment.class, null, roleNames );
}
/**
* Method removeAssignment
*
* @param userAssignment
*/
public void removeUserAssignment( UserAssignment userAssignment )
throws RbacObjectNotFoundException, RbacObjectInvalidException, RbacManagerException
{
RBACObjectAssertions.assertValid( userAssignment );
if ( userAssignment.isPermanent() )
{
throw new RbacPermanentException(
"Unable to delete permanent user assignment [" + userAssignment.getPrincipal() + "]" );
}
fireRbacUserAssignmentRemoved( userAssignment );
jdo.removeObject( userAssignment );
}
public void eraseDatabase()
{
// Must delete in order so that FK constraints don't get violated
jdo.removeAll( JdoRole.class );
jdo.removeAll( JdoPermission.class );
jdo.removeAll( JdoOperation.class );
jdo.removeAll( JdoResource.class );
jdo.removeAll( JdoUserAssignment.class );
jdo.removeAll( RbacJdoModelModelloMetadata.class );
}
@PostConstruct
public void initialize()
{
super.initialize();
jdo.setListener( this );
if ( enableCache )
{
jdo.enableCache( JdoRole.class );
jdo.enableCache( JdoOperation.class );
jdo.enableCache( JdoResource.class );
jdo.enableCache( JdoUserAssignment.class );
jdo.enableCache( JdoPermission.class );
}
}
public void rbacInit( boolean freshdb )
{
fireRbacInit( freshdb );
}
public void rbacPermissionRemoved( Permission permission )
{
fireRbacPermissionRemoved( permission );
}
public void rbacPermissionSaved( Permission permission )
{
fireRbacPermissionSaved( permission );
}
public void rbacRoleRemoved( Role role )
{
fireRbacRoleRemoved( role );
}
public void rbacRoleSaved( Role role )
{
fireRbacRoleSaved( role );
}
public void rbacUserAssignmentSaved( UserAssignment userAssignment )
{
fireRbacUserAssignmentSaved( userAssignment );
}
public void rbacUserAssignmentRemoved( UserAssignment userAssignment )
{
fireRbacUserAssignmentRemoved( userAssignment );
}
public JdoTool getJdo()
{
return jdo;
}
public void setJdo( JdoTool jdo )
{
this.jdo = jdo;
}
public boolean isEnableCache()
{
return enableCache;
}
public void setEnableCache( boolean enableCache )
{
this.enableCache = enableCache;
}
@Override
public boolean isFinalImplementation()
{
return true;
}
public String getDescriptionKey()
{
return "archiva.redback.rbacmanager.jdo";
}
public boolean isReadOnly()
{
return false;
}
}