summaryrefslogtreecommitdiffstats
path: root/archiva-modules/archiva-web
diff options
context:
space:
mode:
authorMaria Odea B. Ching <oching@apache.org>2009-10-13 10:36:24 +0000
committerMaria Odea B. Ching <oching@apache.org>2009-10-13 10:36:24 +0000
commitc893eefe9fd685bdcfaf14805d8448665c777125 (patch)
treeed8b202a595030793893bc402ef362622ff1232a /archiva-modules/archiva-web
parent88f79fe1e7688750f3236feb71a5288e6891abe1 (diff)
downloadarchiva-c893eefe9fd685bdcfaf14805d8448665c777125.tar.gz
archiva-c893eefe9fd685bdcfaf14805d8448665c777125.zip
[MRM-747] Archiva should prevent re-deployment of released or non-snapshot versioned artifacts
submitted by Marc Lustig o added checks in webdav to block re-deployment if artifact version already exists in the repo and throw a 409 in such cases o added tests for deploying and re-deploying an artifact additional modifications to the patch: o update checking for artifact types that will be blocked o add tests for deploying metadata and support file git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@824677 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'archiva-modules/archiva-web')
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java135
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ReleaseArtifactAlreadyExistsException.java38
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java7
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletDeployTest.java48
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/test/resources/artifact.jar.sha10
5 files changed, 181 insertions, 47 deletions
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
index 7ca4de562..319104634 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ArchivaDavResourceFactory.java
@@ -40,6 +40,7 @@ import org.apache.jackrabbit.webdav.DavSession;
import org.apache.jackrabbit.webdav.lock.LockManager;
import org.apache.jackrabbit.webdav.lock.SimpleLockManager;
import org.apache.maven.archiva.common.utils.PathUtil;
+import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.RepositoryGroupConfiguration;
import org.apache.maven.archiva.model.ArchivaRepositoryMetadata;
@@ -162,12 +163,12 @@ public class ArchivaDavResourceFactory
* @plexus.requirement role-hint="md5";
*/
private Digester digestMd5;
-
+
/**
* @plexus.requirement
*/
private ArchivaTaskScheduler scheduler;
-
+
public DavResource createResource( final DavResourceLocator locator, final DavServletRequest request,
final DavServletResponse response )
throws DavException
@@ -190,7 +191,7 @@ public class ArchivaDavResourceFactory
throw new DavException( HttpServletResponse.SC_METHOD_NOT_ALLOWED,
"Write method not allowed for repository groups." );
}
-
+
log.debug( "Repository group '" + repoGroupConfig.getId() + "' accessed by '" + activePrincipal + "'" );
// handle browse requests for virtual repos
@@ -200,9 +201,16 @@ public class ArchivaDavResourceFactory
}
else
{
- resource =
- processRepositoryGroup( request, archivaLocator, repoGroupConfig.getRepositories(),
- activePrincipal, resourcesInAbsolutePath );
+ try
+ {
+ resource =
+ processRepositoryGroup( request, archivaLocator, repoGroupConfig.getRepositories(),
+ activePrincipal, resourcesInAbsolutePath );
+ }
+ catch ( ReleaseArtifactAlreadyExistsException e )
+ {
+ throw new DavException( HttpServletResponse.SC_CONFLICT );
+ }
}
}
else
@@ -215,8 +223,8 @@ public class ArchivaDavResourceFactory
}
catch ( RepositoryNotFoundException e )
{
- throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid repository: "
- + archivaLocator.getRepositoryId() );
+ throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid repository: " +
+ archivaLocator.getRepositoryId() );
}
catch ( RepositoryException e )
{
@@ -225,7 +233,14 @@ public class ArchivaDavResourceFactory
log.debug( "Managed repository '" + managedRepository.getId() + "' accessed by '" + activePrincipal + "'" );
- resource = processRepository( request, archivaLocator, activePrincipal, managedRepository );
+ try
+ {
+ resource = processRepository( request, archivaLocator, activePrincipal, managedRepository );
+ }
+ catch ( ReleaseArtifactAlreadyExistsException e )
+ {
+ throw new DavException( HttpServletResponse.SC_CONFLICT, e );
+ }
String logicalResource = RepositoryPathUtil.getLogicalResource( locator.getResourcePath() );
resourcesInAbsolutePath.add( new File( managedRepository.getRepoRoot(), logicalResource ).getAbsolutePath() );
@@ -235,8 +250,8 @@ public class ArchivaDavResourceFactory
// MRM-872 : merge all available metadata
// merge metadata only when requested via the repo group
- if ( ( repositoryRequest.isMetadata( requestedResource ) || ( requestedResource.endsWith( "metadata.xml.sha1" ) || requestedResource.endsWith( "metadata.xml.md5" ) ) )
- && repoGroupConfig != null )
+ if ( ( repositoryRequest.isMetadata( requestedResource ) || ( requestedResource.endsWith( "metadata.xml.sha1" ) || requestedResource.endsWith( "metadata.xml.md5" ) ) ) &&
+ repoGroupConfig != null )
{
// this should only be at the project level not version level!
if ( isProjectReference( requestedResource ) )
@@ -334,9 +349,9 @@ public class ArchivaDavResourceFactory
private DavResource processRepositoryGroup( final DavServletRequest request,
ArchivaDavResourceLocator archivaLocator, List<String> repositories,
String activePrincipal, List<String> resourcesInAbsolutePath )
- throws DavException
+ throws DavException, ReleaseArtifactAlreadyExistsException
{
- DavResource resource = null;
+ DavResource resource = null;
List<DavException> storedExceptions = new ArrayList<DavException>();
for ( String repositoryId : repositories )
@@ -372,24 +387,24 @@ public class ArchivaDavResourceFactory
resourcesInAbsolutePath.add( new File( managedRepository.getRepoRoot(), logicalResource ).getAbsolutePath() );
}
catch ( DavException e )
- {
+ {
storedExceptions.add( e );
}
}
if ( resource == null )
- {
+ {
if ( !storedExceptions.isEmpty() )
- {
+ {
// MRM-1232
- for( DavException e : storedExceptions )
+ for ( DavException e : storedExceptions )
{
- if( 401 == e.getErrorCode() )
+ if ( 401 == e.getErrorCode() )
{
throw e;
}
}
-
+
throw new DavException( HttpServletResponse.SC_NOT_FOUND );
}
else
@@ -402,7 +417,7 @@ public class ArchivaDavResourceFactory
private DavResource processRepository( final DavServletRequest request, ArchivaDavResourceLocator archivaLocator,
String activePrincipal, ManagedRepositoryContent managedRepository )
- throws DavException
+ throws DavException, ReleaseArtifactAlreadyExistsException
{
DavResource resource = null;
if ( isAuthorized( request, managedRepository.getId() ) )
@@ -412,13 +427,12 @@ public class ArchivaDavResourceFactory
{
path = path.substring( 1 );
}
- LogicalResource logicalResource = new LogicalResource( path );
+ LogicalResource logicalResource = new LogicalResource( path );
File resourceFile = new File( managedRepository.getRepoRoot(), path );
resource =
- new ArchivaDavResource( resourceFile.getAbsolutePath(), path,
- managedRepository.getRepository(), request.getRemoteAddr(), activePrincipal,
- request.getDavSession(), archivaLocator, this, mimeTypes, auditListeners,
- scheduler );
+ new ArchivaDavResource( resourceFile.getAbsolutePath(), path, managedRepository.getRepository(),
+ request.getRemoteAddr(), activePrincipal, request.getDavSession(),
+ archivaLocator, this, mimeTypes, auditListeners, scheduler );
if ( WebdavMethodUtil.isReadMethod( request.getMethod() ) )
{
@@ -432,7 +446,7 @@ public class ArchivaDavResourceFactory
if ( !resource.isCollection() )
{
boolean previouslyExisted = resourceFile.exists();
-
+
// Attempt to fetch the resource from any defined proxy.
boolean fromProxy = fetchContentFromProxies( managedRepository, request, logicalResource );
@@ -462,11 +476,11 @@ public class ArchivaDavResourceFactory
if ( fromProxy )
{
String event =
- ( previouslyExisted ? AuditEvent.MODIFY_FILE : AuditEvent.CREATE_FILE )
- + PROXIED_SUFFIX;
-
+ ( previouslyExisted ? AuditEvent.MODIFY_FILE : AuditEvent.CREATE_FILE ) +
+ PROXIED_SUFFIX;
+
log.debug( "Proxied artifact '" + resourceFile.getName() + "' in repository '" +
- managedRepository.getId() + "' (current user '" + activePrincipal + "')" );
+ managedRepository.getId() + "' (current user '" + activePrincipal + "')" );
triggerAuditEvent( request.getRemoteAddr(), archivaLocator.getRepositoryId(),
logicalResource.getPath(), event, activePrincipal );
@@ -482,6 +496,35 @@ public class ArchivaDavResourceFactory
if ( request.getMethod().equals( HTTP_PUT_METHOD ) )
{
+ String resourcePath = logicalResource.getPath();
+
+ // check if target repo is enabled for releases
+ // we suppose that release-artifacts can deployed only to repos enabled for releases
+ if ( managedRepository.getRepository().isReleases() && !repositoryRequest.isMetadata( resourcePath ) &&
+ !repositoryRequest.isSupportFile( resourcePath ) )
+ {
+ ArtifactReference artifact = null;
+ try
+ {
+ artifact = managedRepository.toArtifactReference( resourcePath );
+ }
+ catch ( LayoutException e )
+ {
+ throw new DavException( HttpServletResponse.SC_BAD_REQUEST, e );
+ }
+
+ if ( !VersionUtil.isSnapshot( artifact.getVersion() ) )
+ {
+ // check if artifact already exists
+ if ( managedRepository.hasContent( artifact ) )
+ {
+ log.warn( "Overwriting released artifacts is not allowed." );
+ throw new ReleaseArtifactAlreadyExistsException( managedRepository.getId(),
+ "Overwriting released artifacts is not allowed." );
+ }
+ }
+ }
+
/*
* Create parent directories that don't exist when writing a file This actually makes this
* implementation not compliant to the WebDAV RFC - but we have enough knowledge about how the
@@ -496,9 +539,10 @@ public class ArchivaDavResourceFactory
{
destDir.mkdirs();
String relPath = PathUtil.getRelative( rootDirectory.getAbsolutePath(), destDir );
-
- log.debug( "Creating destination directory '" + destDir.getName() + "' (current user '" + activePrincipal + "')" );
-
+
+ log.debug( "Creating destination directory '" + destDir.getName() + "' (current user '" +
+ activePrincipal + "')" );
+
triggerAuditEvent( request.getRemoteAddr(), logicalResource.getPath(), relPath,
AuditEvent.CREATE_DIR, activePrincipal );
}
@@ -519,8 +563,8 @@ public class ArchivaDavResourceFactory
}
catch ( RepositoryNotFoundException e )
{
- throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid repository: "
- + archivaLocator.getRepositoryId() );
+ throw new DavException( HttpServletResponse.SC_NOT_FOUND, "Invalid repository: " +
+ archivaLocator.getRepositoryId() );
}
catch ( RepositoryException e )
{
@@ -572,8 +616,9 @@ public class ArchivaDavResourceFactory
File proxiedFile = connectors.fetchFromProxies( managedRepository, artifact );
resource.setPath( managedRepository.toPath( artifact ) );
-
- log.debug( "Proxied artifact '" + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion() + "'" );
+
+ log.debug( "Proxied artifact '" + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" +
+ artifact.getVersion() + "'" );
return ( proxiedFile != null );
}
@@ -774,9 +819,9 @@ public class ArchivaDavResourceFactory
AuthenticationResult result = httpAuth.getAuthenticationResult( request, null );
SecuritySession securitySession = httpAuth.getSecuritySession( request.getSession( true ) );
- return servletAuth.isAuthenticated( request, result )
- && servletAuth.isAuthorized( request, securitySession, repositoryId,
- WebdavMethodUtil.getMethodPermission( request.getMethod() ) );
+ return servletAuth.isAuthenticated( request, result ) &&
+ servletAuth.isAuthorized( request, securitySession, repositoryId,
+ WebdavMethodUtil.getMethodPermission( request.getMethod() ) );
}
catch ( AuthenticationException e )
{
@@ -878,8 +923,8 @@ public class ArchivaDavResourceFactory
catch ( DavException e )
{
// TODO: review exception handling
- log.debug( "Skipping repository '" + managedRepository + "' for user '" + activePrincipal
- + "': " + e.getMessage() );
+ log.debug( "Skipping repository '" + managedRepository + "' for user '" + activePrincipal +
+ "': " + e.getMessage() );
}
}
else
@@ -897,8 +942,8 @@ public class ArchivaDavResourceFactory
catch ( UnauthorizedException e )
{
// TODO: review exception handling
- log.debug( "Skipping repository '" + managedRepository + "' for user '" + activePrincipal
- + "': " + e.getMessage() );
+ log.debug( "Skipping repository '" + managedRepository + "' for user '" + activePrincipal +
+ "': " + e.getMessage() );
}
}
}
@@ -1057,7 +1102,7 @@ public class ArchivaDavResourceFactory
{
this.repositoryRequest = repositoryRequest;
}
-
+
public void setConnectors( RepositoryProxyConnectors connectors )
{
this.connectors = connectors;
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ReleaseArtifactAlreadyExistsException.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ReleaseArtifactAlreadyExistsException.java
new file mode 100644
index 000000000..0d46b215e
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/maven/archiva/webdav/ReleaseArtifactAlreadyExistsException.java
@@ -0,0 +1,38 @@
+package org.apache.maven.archiva.webdav;
+
+/*
+ * 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.
+ */
+
+/**
+ */
+public class ReleaseArtifactAlreadyExistsException
+ extends Exception
+{
+ final private String repositoryName;
+
+ public ReleaseArtifactAlreadyExistsException( String repositoryName, String message )
+ {
+ this.repositoryName = repositoryName;
+ }
+
+ public String getRepositoryName()
+ {
+ return repositoryName;
+ }
+}
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java
index 892eeeedb..a0ec2c811 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/AbstractRepositoryServletTestCase.java
@@ -111,6 +111,13 @@ public abstract class AbstractRepositoryServletTestCase
Assert.assertEquals( "Should have been an 500/Internal Server Error response code.", HttpServletResponse.SC_INTERNAL_SERVER_ERROR, response
.getResponseCode() );
}
+
+ protected void assertResponseConflictError( WebResponse response )
+ {
+ assertNotNull( "Should have received a response", response );
+ Assert.assertEquals( "Should have been a 409/Conflict response code.", HttpServletResponse.SC_CONFLICT,
+ response.getResponseCode() );
+ }
protected ManagedRepositoryConfiguration createManagedRepository( String id, String name, File location )
{
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletDeployTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletDeployTest.java
index e15c374e7..886fac309 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletDeployTest.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/maven/archiva/webdav/RepositoryServletDeployTest.java
@@ -38,20 +38,64 @@ import org.apache.maven.archiva.webdav.httpunit.MkColMethodWebRequest;
public class RepositoryServletDeployTest
extends AbstractRepositoryServletTestCase
{
+ private static final String ARTIFACT_DEFAULT_LAYOUT = "/path/to/artifact/1.0.0/artifact-1.0.0.jar";
+
public void testPutWithMissingParentCollection()
throws Exception
{
setupCleanRepo( repoRootInternal );
- String putUrl = "http://machine.com/repository/internal/path/to/artifact.jar";
+ String putUrl = "http://machine.com/repository/internal" + ARTIFACT_DEFAULT_LAYOUT;
InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
+ // verify that the file exists in resources-dir
assertNotNull( "artifact.jar inputstream", is );
WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
WebResponse response = sc.getResponse( request );
assertResponseCreated( response );
- assertFileContents( "artifact.jar\n", repoRootInternal, "path/to/artifact.jar" );
+ assertFileContents( "artifact.jar\n", repoRootInternal, ARTIFACT_DEFAULT_LAYOUT );
+ }
+
+ /**
+ * MRM-747
+ * test whether trying to overwrite existing relase-artifact is blocked by returning HTTP-code 409
+ *
+ * @throws Exception
+ */
+ public void testPreventOverwritingReleaseArtifacts()
+ throws Exception
+ {
+ setupCleanRepo( repoRootInternal );
+
+ String putUrl = "http://machine.com/repository/internal" + ARTIFACT_DEFAULT_LAYOUT;
+ String metadataUrl = "http://machine.com/repository/internal/path/to/artifact/maven-metadata.xml";
+ String checksumUrl = "http://machine.com/repository/internal" + ARTIFACT_DEFAULT_LAYOUT + ".sha1";
+
+ InputStream is = getClass().getResourceAsStream( "/artifact.jar" );
+ // verify that the file exists in resources-dir
+ assertNotNull( "artifact.jar inputstream", is );
+
+ // send request #1 and verify it's successful
+ WebRequest request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
+ WebResponse response = sc.getResponse( request );
+ assertResponseCreated( response );
+
+ is = getClass().getResourceAsStream( "/artifact.jar.sha1" );
+ request = new PutMethodWebRequest( checksumUrl, is, "application/octet-stream" );
+ response = sc.getResponse( request );
+ assertResponseCreated( response );
+
+ is = getClass().getResourceAsStream( "/maven-metadata.xml" );
+ request = new PutMethodWebRequest( metadataUrl, is, "application/octet-stream" );
+ response = sc.getResponse( request );
+ assertResponseCreated( response );
+
+ // send request #2 and verify it's blocked
+ is = getClass().getResourceAsStream( "/artifact.jar" );
+ request = new PutMethodWebRequest( putUrl, is, "application/octet-stream" );
+ response = sc.getResponse( request );
+ assertResponseConflictError( response );
}
public void testMkColWithMissingParentCollectionFails()
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/resources/artifact.jar.sha1 b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/artifact.jar.sha1
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-webdav/src/test/resources/artifact.jar.sha1