mirror of https://github.com/apache/archiva.git
[MRM-913]
submitted by Jevica Arianne Zurbano o patch does the following: - deletes artifacts - cleans up database - executes scan to reflect changes when browsing repository - updates metadata - updates audit.log - 'Delete Artifact' added in navigation and is displayed for users with repository manager role - only allows manager of the repository to delete artifacts from it o additional tweaks to the submitted patch: - removed catch for NPE in DeleteArtifactAction - migrated jsps & action class to struts 2 - moved invocation of cleanup consumers in DeleteArtifactAction to DatabaseConsumers (added new method for this in DatabaseConsumers) - applied formatting git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@746183 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
48e96d554f
commit
0cecbab8be
|
@ -25,11 +25,15 @@ import org.apache.commons.collections.functors.OrPredicate;
|
||||||
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
||||||
import org.apache.maven.archiva.configuration.DatabaseScanningConfiguration;
|
import org.apache.maven.archiva.configuration.DatabaseScanningConfiguration;
|
||||||
import org.apache.maven.archiva.consumers.functors.PermanentConsumerPredicate;
|
import org.apache.maven.archiva.consumers.functors.PermanentConsumerPredicate;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaArtifact;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +44,8 @@ import java.util.List;
|
||||||
public class DatabaseConsumers
|
public class DatabaseConsumers
|
||||||
implements ApplicationContextAware
|
implements ApplicationContextAware
|
||||||
{
|
{
|
||||||
|
private Logger log = LoggerFactory.getLogger( DatabaseConsumers.class );
|
||||||
|
|
||||||
private ArchivaConfiguration archivaConfiguration;
|
private ArchivaConfiguration archivaConfiguration;
|
||||||
|
|
||||||
private Predicate selectedCleanupConsumers;
|
private Predicate selectedCleanupConsumers;
|
||||||
|
@ -149,4 +155,37 @@ public class DatabaseConsumers
|
||||||
{
|
{
|
||||||
return new ArrayList( applicationContext.getBeansOfType( DatabaseCleanupConsumer.class ).values() );
|
return new ArrayList( applicationContext.getBeansOfType( DatabaseCleanupConsumer.class ).values() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the cleanup consumers to cleanup the specified artifact from the database and index.
|
||||||
|
*
|
||||||
|
* @param artifact
|
||||||
|
*/
|
||||||
|
public void executeCleanupConsumer( ArchivaArtifact artifact )
|
||||||
|
{
|
||||||
|
List consumers = getSelectedCleanupConsumers();
|
||||||
|
Iterator it = consumers.iterator();
|
||||||
|
while ( it.hasNext() )
|
||||||
|
{
|
||||||
|
ArchivaArtifactConsumer consumer = (ArchivaArtifactConsumer) it.next();
|
||||||
|
consumer.beginScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CollectionUtils.isEmpty( consumers ) )
|
||||||
|
{
|
||||||
|
log.warn( "There are no selected consumers for artifact cleanup." );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessArchivaArtifactClosure processArtifactClosure = new ProcessArchivaArtifactClosure();
|
||||||
|
processArtifactClosure.setArtifact( artifact );
|
||||||
|
|
||||||
|
CollectionUtils.forAllDo( consumers, processArtifactClosure );
|
||||||
|
|
||||||
|
while ( it.hasNext() )
|
||||||
|
{
|
||||||
|
ArchivaArtifactConsumer consumer = (ArchivaArtifactConsumer) it.next();
|
||||||
|
consumer.completeScan();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,19 @@ package org.apache.maven.archiva.security;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
||||||
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
|
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
|
||||||
|
import org.apache.maven.archiva.security.ArchivaRoleConstants;
|
||||||
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
|
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
|
||||||
import org.codehaus.plexus.redback.authorization.AuthorizationException;
|
import org.codehaus.plexus.redback.authorization.AuthorizationException;
|
||||||
import org.codehaus.plexus.redback.rbac.RBACManager;
|
import org.codehaus.plexus.redback.rbac.RBACManager;
|
||||||
|
import org.codehaus.plexus.redback.rbac.RbacObjectNotFoundException;
|
||||||
|
import org.codehaus.plexus.redback.rbac.RbacManagerException;
|
||||||
|
import org.codehaus.plexus.redback.rbac.Role;
|
||||||
import org.codehaus.plexus.redback.role.RoleManager;
|
import org.codehaus.plexus.redback.role.RoleManager;
|
||||||
import org.codehaus.plexus.redback.role.RoleManagerException;
|
import org.codehaus.plexus.redback.role.RoleManagerException;
|
||||||
import org.codehaus.plexus.redback.system.DefaultSecuritySession;
|
import org.codehaus.plexus.redback.system.DefaultSecuritySession;
|
||||||
|
@ -161,4 +167,47 @@ public class DefaultUserRepositories
|
||||||
throw new ArchivaSecurityException( e.getMessage() );
|
throw new ArchivaSecurityException( e.getMessage() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAuthorizedToDeleteArtifacts( String principal, String repoId )
|
||||||
|
throws RbacManagerException, RbacObjectNotFoundException
|
||||||
|
{
|
||||||
|
boolean isAuthorized = false;
|
||||||
|
String delimiter = " - ";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Collection roleList = rbacManager.getEffectivelyAssignedRoles( principal );
|
||||||
|
|
||||||
|
Iterator it = roleList.iterator();
|
||||||
|
|
||||||
|
while ( it.hasNext() )
|
||||||
|
{
|
||||||
|
Role role = (Role) it.next();
|
||||||
|
|
||||||
|
String roleName = role.getName();
|
||||||
|
|
||||||
|
if ( roleName.startsWith( ArchivaRoleConstants.REPOSITORY_MANAGER_ROLE_PREFIX ) )
|
||||||
|
{
|
||||||
|
int delimiterIndex = roleName.indexOf( delimiter );
|
||||||
|
String resourceName = roleName.substring( delimiterIndex + delimiter.length() );
|
||||||
|
|
||||||
|
if ( resourceName.equals( repoId ) )
|
||||||
|
{
|
||||||
|
isAuthorized = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( RbacObjectNotFoundException e )
|
||||||
|
{
|
||||||
|
throw new RbacObjectNotFoundException( "Unable to find user " + principal + "" );
|
||||||
|
}
|
||||||
|
catch ( RbacManagerException e )
|
||||||
|
{
|
||||||
|
throw new RbacManagerException( "Unable to get roles for user " + principal + "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return isAuthorized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ package org.apache.maven.archiva.security;
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.codehaus.plexus.redback.rbac.RbacObjectNotFoundException;
|
||||||
|
import org.codehaus.plexus.redback.rbac.RbacManagerException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,4 +64,16 @@ public interface UserRepositories
|
||||||
public boolean isAuthorizedToUploadArtifacts( String principal, String repoId)
|
public boolean isAuthorizedToUploadArtifacts( String principal, String repoId)
|
||||||
throws PrincipalNotFoundException, ArchivaSecurityException;
|
throws PrincipalNotFoundException, ArchivaSecurityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user is authorized to delete artifacts in the repository.
|
||||||
|
*
|
||||||
|
* @param principal
|
||||||
|
* @param repoId
|
||||||
|
* @return
|
||||||
|
* @throws RbacManagerException
|
||||||
|
* @throws RbacObjectNotFoundException
|
||||||
|
*/
|
||||||
|
public boolean isAuthorizedToDeleteArtifacts( String principal, String repoId )
|
||||||
|
throws RbacManagerException, RbacObjectNotFoundException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
<id>archiva-run-indexer</id>
|
<id>archiva-run-indexer</id>
|
||||||
<name>archiva-run-indexer</name>
|
<name>archiva-run-indexer</name>
|
||||||
<description>Run Archiva Indexer</description>
|
<description>Run Archiva Indexer</description>
|
||||||
|
</operation>
|
||||||
|
<operation>
|
||||||
|
<id>archiva-delete-artifact</id>
|
||||||
|
<name>archiva-delete-artifact</name>
|
||||||
|
<description>Delete Artifact</description>
|
||||||
</operation>
|
</operation>
|
||||||
<operation>
|
<operation>
|
||||||
<id>archiva-access-reports</id>
|
<id>archiva-access-reports</id>
|
||||||
|
@ -180,6 +185,13 @@
|
||||||
<namePrefix>Repository Manager</namePrefix>
|
<namePrefix>Repository Manager</namePrefix>
|
||||||
<assignable>true</assignable>
|
<assignable>true</assignable>
|
||||||
<permissions>
|
<permissions>
|
||||||
|
<permission>
|
||||||
|
<id>archiva-delete-artifact</id>
|
||||||
|
<name>Delete Artifact</name>
|
||||||
|
<operation>archiva-delete-artifact</operation>
|
||||||
|
<resource>global</resource>
|
||||||
|
<permanent>true</permanent>
|
||||||
|
</permission>
|
||||||
<permission>
|
<permission>
|
||||||
<id>archiva-edit-repository</id>
|
<id>archiva-edit-repository</id>
|
||||||
<name>Archiva Edit Repository</name>
|
<name>Archiva Edit Repository</name>
|
||||||
|
|
|
@ -0,0 +1,426 @@
|
||||||
|
package org.apache.maven.archiva.web.action;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 java.io.File;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.apache.archiva.checksum.ChecksumAlgorithm;
|
||||||
|
import org.apache.archiva.checksum.ChecksummedFile;
|
||||||
|
import org.apache.maven.archiva.common.utils.VersionComparator;
|
||||||
|
import org.apache.maven.archiva.common.utils.VersionUtil;
|
||||||
|
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
|
||||||
|
import org.apache.maven.archiva.configuration.ManagedRepositoryConfiguration;
|
||||||
|
import org.apache.maven.archiva.database.updater.DatabaseConsumers;
|
||||||
|
import org.apache.maven.archiva.database.ArchivaDatabaseException;
|
||||||
|
import org.apache.maven.archiva.database.ArtifactDAO;
|
||||||
|
import org.apache.maven.archiva.database.constraints.ArtifactVersionsConstraint;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaArtifact;
|
||||||
|
import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
|
||||||
|
import org.apache.maven.archiva.model.VersionedReference;
|
||||||
|
import org.apache.maven.archiva.repository.audit.Auditable;
|
||||||
|
import org.apache.maven.archiva.repository.audit.AuditEvent;
|
||||||
|
import org.apache.maven.archiva.repository.audit.AuditListener;
|
||||||
|
import org.apache.maven.archiva.repository.metadata.MetadataTools;
|
||||||
|
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataException;
|
||||||
|
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataReader;
|
||||||
|
import org.apache.maven.archiva.repository.metadata.RepositoryMetadataWriter;
|
||||||
|
import org.apache.maven.archiva.repository.ContentNotFoundException;
|
||||||
|
import org.apache.maven.archiva.repository.RepositoryException;
|
||||||
|
import org.apache.maven.archiva.repository.RepositoryNotFoundException;
|
||||||
|
import org.apache.maven.archiva.repository.ManagedRepositoryContent;
|
||||||
|
import org.apache.maven.archiva.repository.RepositoryContentFactory;
|
||||||
|
import org.apache.maven.archiva.security.ArchivaXworkUser;
|
||||||
|
import org.apache.maven.archiva.security.UserRepositories;
|
||||||
|
import org.codehaus.plexus.redback.rbac.RbacManagerException;
|
||||||
|
|
||||||
|
import org.apache.struts2.ServletActionContext;
|
||||||
|
import com.opensymphony.xwork2.ActionContext;
|
||||||
|
import com.opensymphony.xwork2.Preparable;
|
||||||
|
import com.opensymphony.xwork2.Validateable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an artifact. Metadata will be updated if one exists, otherwise it would be created.
|
||||||
|
*
|
||||||
|
* @plexus.component role="com.opensymphony.xwork2.Action" role-hint="deleteArtifactAction"
|
||||||
|
*/
|
||||||
|
public class DeleteArtifactAction
|
||||||
|
extends PlexusActionSupport
|
||||||
|
implements Validateable, Preparable, Auditable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @plexus.requirement
|
||||||
|
*/
|
||||||
|
private ArchivaXworkUser archivaXworkUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The groupId of the artifact to be deleted.
|
||||||
|
*/
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The artifactId of the artifact to be deleted.
|
||||||
|
*/
|
||||||
|
private String artifactId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version of the artifact to be deleted.
|
||||||
|
*/
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The repository where the artifact is to be deleted.
|
||||||
|
*/
|
||||||
|
private String repositoryId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of managed repositories to delete from.
|
||||||
|
*/
|
||||||
|
private List<String> managedRepos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement
|
||||||
|
*/
|
||||||
|
private UserRepositories userRepositories;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="default"
|
||||||
|
*/
|
||||||
|
private ArchivaConfiguration configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement
|
||||||
|
*/
|
||||||
|
private RepositoryContentFactory repositoryFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role-hint="jdo"
|
||||||
|
*/
|
||||||
|
private ArtifactDAO artifactDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement
|
||||||
|
*/
|
||||||
|
private DatabaseConsumers databaseConsumers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @plexus.requirement role="org.apache.maven.archiva.repository.audit.AuditListener"
|
||||||
|
*/
|
||||||
|
private List<AuditListener> auditListeners = new ArrayList<AuditListener>();
|
||||||
|
|
||||||
|
private ChecksumAlgorithm[] algorithms = new ChecksumAlgorithm[] { ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 };
|
||||||
|
|
||||||
|
public String getGroupId()
|
||||||
|
{
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupId( String groupId )
|
||||||
|
{
|
||||||
|
this.groupId = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getArtifactId()
|
||||||
|
{
|
||||||
|
return artifactId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArtifactId( String artifactId )
|
||||||
|
{
|
||||||
|
this.artifactId = artifactId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion()
|
||||||
|
{
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion( String version )
|
||||||
|
{
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRepositoryId()
|
||||||
|
{
|
||||||
|
return repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepositoryId( String repositoryId )
|
||||||
|
{
|
||||||
|
this.repositoryId = repositoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getManagedRepos()
|
||||||
|
{
|
||||||
|
return managedRepos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setManagedRepos( List<String> managedRepos )
|
||||||
|
{
|
||||||
|
this.managedRepos = managedRepos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prepare()
|
||||||
|
{
|
||||||
|
managedRepos = new ArrayList<String>( configuration.getConfiguration().getManagedRepositoriesAsMap().keySet() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String input()
|
||||||
|
{
|
||||||
|
return INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reset()
|
||||||
|
{
|
||||||
|
// reset the fields so the form is clear when
|
||||||
|
// the action returns to the jsp page
|
||||||
|
groupId = "";
|
||||||
|
artifactId = "";
|
||||||
|
version = "";
|
||||||
|
repositoryId = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String doDelete()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Date lastUpdatedTimestamp = Calendar.getInstance().getTime();
|
||||||
|
|
||||||
|
TimeZone timezone = TimeZone.getTimeZone( "UTC" );
|
||||||
|
DateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
|
||||||
|
fmt.setTimeZone( timezone );
|
||||||
|
String timestamp = fmt.format( lastUpdatedTimestamp );
|
||||||
|
|
||||||
|
ManagedRepositoryConfiguration repoConfig =
|
||||||
|
configuration.getConfiguration().findManagedRepositoryById( repositoryId );
|
||||||
|
|
||||||
|
VersionedReference ref = new VersionedReference();
|
||||||
|
ref.setArtifactId( artifactId );
|
||||||
|
ref.setGroupId( groupId );
|
||||||
|
ref.setVersion( version );
|
||||||
|
|
||||||
|
ManagedRepositoryContent repository = repositoryFactory.getManagedRepositoryContent( repositoryId );
|
||||||
|
|
||||||
|
String path = repository.toMetadataPath( ref );
|
||||||
|
int index = path.lastIndexOf( '/' );
|
||||||
|
File targetPath = new File( repoConfig.getLocation(), path.substring( 0, index ) );
|
||||||
|
|
||||||
|
if ( !targetPath.exists() )
|
||||||
|
{
|
||||||
|
throw new ContentNotFoundException( groupId + ":" + artifactId + ":" + version );
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete from file system
|
||||||
|
repository.deleteVersion( ref );
|
||||||
|
|
||||||
|
File metadataFile = getMetadata( targetPath.getAbsolutePath() );
|
||||||
|
ArchivaRepositoryMetadata metadata = getMetadata( metadataFile );
|
||||||
|
|
||||||
|
updateMetadata( metadata, metadataFile, lastUpdatedTimestamp );
|
||||||
|
|
||||||
|
ArtifactVersionsConstraint constraint =
|
||||||
|
new ArtifactVersionsConstraint( repositoryId, groupId, artifactId, false );
|
||||||
|
List<ArchivaArtifact> artifacts = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
artifacts = artifactDAO.queryArtifacts( constraint );
|
||||||
|
|
||||||
|
if ( artifacts != null )
|
||||||
|
{
|
||||||
|
for ( ArchivaArtifact artifact : artifacts )
|
||||||
|
{
|
||||||
|
if ( artifact.getVersion().equals( version ) )
|
||||||
|
{
|
||||||
|
databaseConsumers.executeCleanupConsumer( artifact );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( ArchivaDatabaseException e )
|
||||||
|
{
|
||||||
|
addActionError( "Error occurred while cleaning up database: " + e.getMessage() );
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
String msg =
|
||||||
|
"Artifact \'" + groupId + ":" + artifactId + ":" + version +
|
||||||
|
"\' was successfully deleted from repository \'" + repositoryId + "\'";
|
||||||
|
|
||||||
|
triggerAuditEvent( getPrincipal(), repositoryId, groupId + ":" + artifactId + ":" + version,
|
||||||
|
AuditEvent.REMOVE_FILE );
|
||||||
|
|
||||||
|
addActionMessage( msg );
|
||||||
|
|
||||||
|
reset();
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
catch ( ContentNotFoundException e )
|
||||||
|
{
|
||||||
|
addActionError( "Artifact does not exist: " + e.getMessage() );
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
catch ( RepositoryNotFoundException e )
|
||||||
|
{
|
||||||
|
addActionError( "Target repository cannot be found: " + e.getMessage() );
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
catch ( RepositoryException e )
|
||||||
|
{
|
||||||
|
addActionError( "Repository exception: " + e.getMessage() );
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPrincipal()
|
||||||
|
{
|
||||||
|
return archivaXworkUser.getActivePrincipal( ActionContext.getContext().getSession() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getMetadata( String targetPath )
|
||||||
|
{
|
||||||
|
String artifactPath = targetPath.substring( 0, targetPath.lastIndexOf( File.separatorChar ) );
|
||||||
|
|
||||||
|
return new File( artifactPath, MetadataTools.MAVEN_METADATA );
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArchivaRepositoryMetadata getMetadata( File metadataFile )
|
||||||
|
throws RepositoryMetadataException
|
||||||
|
{
|
||||||
|
ArchivaRepositoryMetadata metadata = new ArchivaRepositoryMetadata();
|
||||||
|
if ( metadataFile.exists() )
|
||||||
|
{
|
||||||
|
metadata = RepositoryMetadataReader.read( metadataFile );
|
||||||
|
}
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update artifact level metadata. Creates one if metadata does not exist after artifact deletion.
|
||||||
|
*
|
||||||
|
* @param metadata
|
||||||
|
*/
|
||||||
|
private void updateMetadata( ArchivaRepositoryMetadata metadata, File metadataFile, Date lastUpdatedTimestamp )
|
||||||
|
throws RepositoryMetadataException
|
||||||
|
{
|
||||||
|
List<String> availableVersions = new ArrayList<String>();
|
||||||
|
String latestVersion = "";
|
||||||
|
|
||||||
|
if ( metadataFile.exists() )
|
||||||
|
{
|
||||||
|
if ( metadata.getAvailableVersions() != null )
|
||||||
|
{
|
||||||
|
availableVersions = metadata.getAvailableVersions();
|
||||||
|
|
||||||
|
if ( availableVersions.size() > 0 )
|
||||||
|
{
|
||||||
|
Collections.sort( availableVersions, VersionComparator.getInstance() );
|
||||||
|
|
||||||
|
if ( availableVersions.contains( version ) )
|
||||||
|
{
|
||||||
|
availableVersions.remove( availableVersions.indexOf( version ) );
|
||||||
|
}
|
||||||
|
if ( availableVersions.size() > 0 )
|
||||||
|
{
|
||||||
|
latestVersion = availableVersions.get( availableVersions.size() - 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( metadata.getGroupId() == null )
|
||||||
|
{
|
||||||
|
metadata.setGroupId( groupId );
|
||||||
|
}
|
||||||
|
if ( metadata.getArtifactId() == null )
|
||||||
|
{
|
||||||
|
metadata.setArtifactId( artifactId );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !VersionUtil.isSnapshot( version ) )
|
||||||
|
{
|
||||||
|
if ( metadata.getReleasedVersion().equals( version ) )
|
||||||
|
{
|
||||||
|
metadata.setReleasedVersion( latestVersion );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.setLatestVersion( latestVersion );
|
||||||
|
metadata.setLastUpdatedTimestamp( lastUpdatedTimestamp );
|
||||||
|
metadata.setAvailableVersions( availableVersions );
|
||||||
|
|
||||||
|
RepositoryMetadataWriter.write( metadata, metadataFile );
|
||||||
|
ChecksummedFile checksum = new ChecksummedFile( metadataFile );
|
||||||
|
checksum.fixChecksums( algorithms );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ( !userRepositories.isAuthorizedToDeleteArtifacts( getPrincipal(), repositoryId ) )
|
||||||
|
{
|
||||||
|
addActionError( "User is not authorized to delete artifacts in repository '" + repositoryId + "'." );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( version.length() > 0 ) && ( !VersionUtil.isVersion( version ) ) )
|
||||||
|
{
|
||||||
|
addActionError( "Invalid version." );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( RbacManagerException e )
|
||||||
|
{
|
||||||
|
addActionError( e.getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAuditListener( AuditListener listener )
|
||||||
|
{
|
||||||
|
this.auditListeners.add( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearAuditListeners()
|
||||||
|
{
|
||||||
|
this.auditListeners.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAuditListener( AuditListener listener )
|
||||||
|
{
|
||||||
|
this.auditListeners.remove( listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerAuditEvent( String user, String repositoryId, String resource, String action )
|
||||||
|
{
|
||||||
|
AuditEvent event = new AuditEvent( repositoryId, user, resource, action );
|
||||||
|
event.setRemoteIP( ServletActionContext.getRequest().getRemoteAddr() );
|
||||||
|
|
||||||
|
for ( AuditListener listener : auditListeners )
|
||||||
|
{
|
||||||
|
listener.auditEvent( event );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
|
||||||
|
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
|
||||||
|
|
||||||
|
<validators>
|
||||||
|
<field name="groupId">
|
||||||
|
<field-validator type="requiredstring">
|
||||||
|
<message>You must enter a groupId.</message>
|
||||||
|
</field-validator>
|
||||||
|
</field>
|
||||||
|
<field name="artifactId">
|
||||||
|
<field-validator type="requiredstring">
|
||||||
|
<message>You must enter an artifactId.</message>
|
||||||
|
</field-validator>
|
||||||
|
</field>
|
||||||
|
<field name="version">
|
||||||
|
<field-validator type="requiredstring">
|
||||||
|
<message>You must enter a version.</message>
|
||||||
|
</field-validator>
|
||||||
|
</field>
|
||||||
|
</validators>
|
|
@ -170,6 +170,12 @@
|
||||||
<interceptor-ref name="fileUpload"/>
|
<interceptor-ref name="fileUpload"/>
|
||||||
</action>
|
</action>
|
||||||
|
|
||||||
|
<action name="deleteArtifact" class="deleteArtifactAction" method="input">
|
||||||
|
<result name="input">/WEB-INF/jsp/deleteArtifact.jsp</result>
|
||||||
|
<result name="error">/WEB-INF/jsp/deleteArtifact.jsp</result>
|
||||||
|
<result name="success">/WEB-INF/jsp/deleteArtifact.jsp</result>
|
||||||
|
</action>
|
||||||
|
|
||||||
<action name="checksumSearch" class="searchAction" method="findArtifact">
|
<action name="checksumSearch" class="searchAction" method="findArtifact">
|
||||||
<result name="input">/WEB-INF/jsp/findArtifact.jsp</result>
|
<result name="input">/WEB-INF/jsp/findArtifact.jsp</result>
|
||||||
<result name="results">/WEB-INF/jsp/results.jsp</result>
|
<result name="results">/WEB-INF/jsp/results.jsp</result>
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<redback:ifAnyAuthorized permissions="archiva-manage-users,archiva-access-reports,archiva-manage-configuration">
|
<redback:ifAnyAuthorized permissions="archiva-delete-artifact,archiva-manage-users,archiva-access-reports,archiva-manage-configuration">
|
||||||
<h5>Manage</h5>
|
<h5>Manage</h5>
|
||||||
<ul>
|
<ul>
|
||||||
<redback:ifAuthorized permission="archiva-access-reports">
|
<redback:ifAuthorized permission="archiva-access-reports">
|
||||||
|
@ -110,6 +110,11 @@
|
||||||
<li class="none">
|
<li class="none">
|
||||||
<my:currentWWUrl action="upload" namespace="/">Upload Artifact</my:currentWWUrl>
|
<my:currentWWUrl action="upload" namespace="/">Upload Artifact</my:currentWWUrl>
|
||||||
</li>
|
</li>
|
||||||
|
</redback:ifAuthorized>
|
||||||
|
<redback:ifAuthorized permission="archiva-delete-artifact">
|
||||||
|
<li class="none">
|
||||||
|
<my:currentWWUrl action="deleteArtifact" namespace="/">Delete Artifact</my:currentWWUrl>
|
||||||
|
</li>
|
||||||
</redback:ifAuthorized>
|
</redback:ifAuthorized>
|
||||||
<%-- TODO: future options here.
|
<%-- TODO: future options here.
|
||||||
* Repository Statistics.
|
* Repository Statistics.
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<%--
|
||||||
|
~ 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.
|
||||||
|
--%>
|
||||||
|
|
||||||
|
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Delete Artifact</title>
|
||||||
|
<s:head/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Delete Artifact</h1>
|
||||||
|
|
||||||
|
<s:actionerror/>
|
||||||
|
<s:actionmessage/>
|
||||||
|
|
||||||
|
<div id="contentArea">
|
||||||
|
<s:form action="deleteArtifact!doDelete" namespace="/" method="post" validate="true">
|
||||||
|
<%@ include file="/WEB-INF/jsp/include/deleteArtifactForm.jspf" %>
|
||||||
|
<s:submit/>
|
||||||
|
</s:form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<%--
|
||||||
|
~ 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.
|
||||||
|
--%>
|
||||||
|
|
||||||
|
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||||
|
|
||||||
|
<s:textfield name="groupId" label="Group Id" size="50" required="true"/>
|
||||||
|
<s:textfield name="artifactId" label="Artifact Id" size="50" required="true"/>
|
||||||
|
<s:textfield name="version" label="Version" size="50" required="true"/>
|
||||||
|
<s:select name="repositoryId" list="managedRepos" label="Repository Id"/>
|
||||||
|
|
|
@ -26,6 +26,8 @@ import org.apache.maven.archiva.security.AccessDeniedException;
|
||||||
import org.apache.maven.archiva.security.ArchivaSecurityException;
|
import org.apache.maven.archiva.security.ArchivaSecurityException;
|
||||||
import org.apache.maven.archiva.security.PrincipalNotFoundException;
|
import org.apache.maven.archiva.security.PrincipalNotFoundException;
|
||||||
import org.apache.maven.archiva.security.UserRepositories;
|
import org.apache.maven.archiva.security.UserRepositories;
|
||||||
|
import org.codehaus.plexus.redback.rbac.RbacObjectNotFoundException;
|
||||||
|
import org.codehaus.plexus.redback.rbac.RbacManagerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UserRepositories stub used for testing.
|
* UserRepositories stub used for testing.
|
||||||
|
@ -59,4 +61,10 @@ public class UserRepositoriesStub
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAuthorizedToDeleteArtifacts( String principal, String repoId )
|
||||||
|
throws RbacManagerException, RbacObjectNotFoundException
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue