aboutsummaryrefslogtreecommitdiffstats
path: root/archiva-modules/archiva-web
diff options
context:
space:
mode:
Diffstat (limited to 'archiva-modules/archiva-web')
-rw-r--r--archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java16
-rw-r--r--archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java149
-rw-r--r--archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java47
-rw-r--r--archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java42
-rw-r--r--archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java39
-rw-r--r--archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java276
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/DavResourceTest.java5
7 files changed, 529 insertions, 45 deletions
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java
index e1f423d2b..d5612c6f3 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/FileInfo.java
@@ -35,9 +35,11 @@ package org.apache.archiva.rest.api.model.v2;/*
*/
import io.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.repository.storage.StorageAsset;
import java.io.Serializable;
import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
/**
* @author Martin Stockhammer <martin_s@apache.org>
@@ -50,7 +52,19 @@ public class FileInfo implements Serializable
private String fileName;
private String path;
- @Schema(description = "Time when the file was last modified")
+ public FileInfo( )
+ {
+ }
+
+ public static FileInfo of( StorageAsset asset ) {
+ FileInfo fileInfo = new FileInfo( );
+ fileInfo.setFileName( asset.getName() );
+ fileInfo.setPath( asset.getPath() );
+ fileInfo.setModified( asset.getModificationTime( ).atOffset( ZoneOffset.UTC ) );
+ return fileInfo;
+ }
+
+ @Schema(description = "Time when the file was last modified")
public OffsetDateTime getModified( )
{
return modified;
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java
index 6a045b438..99455f148 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepository.java
@@ -35,9 +35,17 @@ package org.apache.archiva.rest.api.model.v2;/*
*/
import io.swagger.v3.oas.annotations.media.Schema;
+import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.features.ArtifactCleanupFeature;
+import org.apache.archiva.repository.features.IndexCreationFeature;
+import org.apache.archiva.repository.features.StagingRepositoryFeature;
+import java.time.Period;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
/**
* @author Martin Stockhammer <martin_s@apache.org>
@@ -49,6 +57,52 @@ public class MavenManagedRepository extends Repository
boolean blocksRedeployments;
List<String> releaseSchemes = new ArrayList<>( );
+ boolean deleteSnapshotsOfRelease = false;
+ private Period retentionPeriod;
+ private int retentionCount;
+ private String indexPath;
+ private String packedIndexPath;
+ private boolean skipPackedIndexCreation;
+ private boolean hasStagingRepository;
+ private String stagingRepository;
+
+
+ public MavenManagedRepository( )
+ {
+ super.setCharacteristic( Repository.CHARACTERISTIC_MANAGED );
+ super.setType( RepositoryType.MAVEN.name( ) );
+ }
+
+ protected static void update(MavenManagedRepository repo, ManagedRepository beanRepo) {
+ repo.setDescription( beanRepo.getDescription() );
+ repo.setId( beanRepo.getId() );
+ repo.setIndex( true );
+ repo.setLayout( beanRepo.getLayout() );
+ repo.setBlocksRedeployments( beanRepo.blocksRedeployments() );
+ repo.setReleaseSchemes( beanRepo.getActiveReleaseSchemes().stream().map( Objects::toString).collect( Collectors.toList()) );
+ repo.setLocation( beanRepo.getLocation().toString() );
+ repo.setName( beanRepo.getName());
+ repo.setScanned( beanRepo.isScanned() );
+ repo.setSchedulingDefinition( beanRepo.getSchedulingDefinition() );
+ ArtifactCleanupFeature artifactCleanupFeature = beanRepo.getFeature( ArtifactCleanupFeature.class ).get( );
+ repo.setDeleteSnapshotsOfRelease( artifactCleanupFeature.isDeleteReleasedSnapshots());
+ repo.setRetentionCount( artifactCleanupFeature.getRetentionCount());
+ repo.setRetentionPeriod( artifactCleanupFeature.getRetentionPeriod() );
+ IndexCreationFeature icf = beanRepo.getFeature( IndexCreationFeature.class ).get( );
+ repo.setIndex( icf.hasIndex( ) );
+ repo.setIndexPath( icf.getIndexPath( ).getPath( ) );
+ repo.setPackedIndexPath( icf.getPackedIndexPath( ).getPath( ) );
+ repo.setSkipPackedIndexCreation( icf.isSkipPackedIndexCreation() );
+ StagingRepositoryFeature srf = beanRepo.getFeature( StagingRepositoryFeature.class ).get( );
+ repo.setHasStagingRepository( srf.isStageRepoNeeded( ) );
+ repo.setStagingRepository( srf.getStagingRepository()!=null?srf.getStagingRepository().getId():"" );
+ }
+
+ public static MavenManagedRepository of( ManagedRepository beanRepo ) {
+ MavenManagedRepository repo = new MavenManagedRepository( );
+ update( repo, beanRepo );
+ return repo;
+ }
@Schema(name="blocks_redeployments",description = "True, if redeployments to this repository are not allowed")
public boolean isBlocksRedeployments( )
@@ -72,6 +126,101 @@ public class MavenManagedRepository extends Repository
this.releaseSchemes = new ArrayList<>( releaseSchemes );
}
+ public void addReleaseScheme(String scheme) {
+ if (!this.releaseSchemes.contains( scheme ))
+ {
+ this.releaseSchemes.add( scheme );
+ }
+ }
+
+ @Schema(name="delete_snaphots_of_release", description = "True, if snapshots are deleted, after a version is released")
+ public boolean isDeleteSnapshotsOfRelease( )
+ {
+ return deleteSnapshotsOfRelease;
+ }
+
+ public void setDeleteSnapshotsOfRelease( boolean deleteSnapshotsOfRelease )
+ {
+ this.deleteSnapshotsOfRelease = deleteSnapshotsOfRelease;
+ }
+
+ @Schema(name="retention_period", description = "The period after which snapshots are deleted.")
+ public Period getRetentionPeriod( )
+ {
+ return retentionPeriod;
+ }
+
+ public void setRetentionPeriod( Period retentionPeriod )
+ {
+ this.retentionPeriod = retentionPeriod;
+ }
+
+ @Schema(name="retention_count", description = "Number of snapshot artifacts to keep.")
+ public int getRetentionCount( )
+ {
+ return retentionCount;
+ }
+
+ public void setRetentionCount( int retentionCount )
+ {
+ this.retentionCount = retentionCount;
+ }
+
+ @Schema( name = "index_path", description = "Path to the directory that contains the index, relative to the repository base directory" )
+ public String getIndexPath( )
+ {
+ return indexPath;
+ }
+
+ public void setIndexPath( String indexPath )
+ {
+ this.indexPath = indexPath;
+ }
+
+ @Schema( name = "packed_index_path", description = "Path to the directory that contains the packed index, relative to the repository base directory" )
+ public String getPackedIndexPath( )
+ {
+ return packedIndexPath;
+ }
+
+ public void setPackedIndexPath( String packedIndexPath )
+ {
+ this.packedIndexPath = packedIndexPath;
+ }
+
+ @Schema(name="skip_packed_index_creation", description = "True, if packed index is not created during index update")
+ public boolean isSkipPackedIndexCreation( )
+ {
+ return skipPackedIndexCreation;
+ }
+
+ public void setSkipPackedIndexCreation( boolean skipPackedIndexCreation )
+ {
+ this.skipPackedIndexCreation = skipPackedIndexCreation;
+ }
+
+ @Schema(name="has_staging_repository", description = "True, if this repository has a staging repository assigned")
+ public boolean isHasStagingRepository( )
+ {
+ return hasStagingRepository;
+ }
+
+ public void setHasStagingRepository( boolean hasStagingRepository )
+ {
+ this.hasStagingRepository = hasStagingRepository;
+ }
+
+ @Schema(name="staging_repository", description = "The id of the assigned staging repository")
+ public String getStagingRepository( )
+ {
+ return stagingRepository;
+ }
+
+ public void setStagingRepository( String stagingRepository )
+ {
+ this.stagingRepository = stagingRepository;
+ }
+
@Override
public boolean equals( Object o )
{
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java
new file mode 100644
index 000000000..32809f63c
--- /dev/null
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/model/v2/MavenManagedRepositoryUpdate.java
@@ -0,0 +1,47 @@
+package org.apache.archiva.rest.api.model.v2;
+/*
+ * 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.repository.ManagedRepository;
+
+import java.io.Serializable;
+
+/**
+ * @author Martin Stockhammer <martin_s@apache.org>
+ */
+public class MavenManagedRepositoryUpdate extends MavenManagedRepository implements Serializable
+{
+ private static final long serialVersionUID = -9181643343284109862L;
+ private boolean resetStats = false;
+
+ public static MavenManagedRepositoryUpdate of( ManagedRepository repository ) {
+ MavenManagedRepositoryUpdate repo = new MavenManagedRepositoryUpdate( );
+ update( repo, repository );
+ return repo;
+ }
+
+ public boolean isResetStats( )
+ {
+ return resetStats;
+ }
+
+ public void setResetStats( boolean resetStats )
+ {
+ this.resetStats = resetStats;
+ }
+}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java
index 793f2d7d1..ab74ceaec 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java
@@ -78,8 +78,48 @@ public interface ErrorKeys
String TASK_QUEUE_FAILED = PREFIX + "task.queue_failed";
String REPOSITORY_SCAN_FAILED = REPOSITORY_PREFIX + "scan.failed";
String ARTIFACT_EXISTS_AT_DEST = REPOSITORY_PREFIX + "artifact.dest.exists";
-
String REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED = REPOSITORY_PREFIX + "remote.index.download_failed";
+ String REPOSITORY_WRONG_TYPE = REPOSITORY_PREFIX + "wrong_type";
+ String REPOSITORY_DELETE_FAILED = REPOSITORY_PREFIX + "delete.failed";
+ String REPOSITORY_INVALID_ID = REPOSITORY_PREFIX + "invalid.id";
+ String REPOSITORY_ID_EXISTS = REPOSITORY_PREFIX + "id.exists";
+ String REPOSITORY_UPDATE_FAILED = REPOSITORY_PREFIX + "update.failed";
+ String ARTIFACT_NOT_FOUND = REPOSITORY_PREFIX + "artifact.notfound";
+ String REPOSITORY_LAYOUT_ERROR = REPOSITORY_PREFIX + "layout.error";
+
+ String ARTIFACT_COPY_ERROR = REPOSITORY_PREFIX + "artifact.copy.error";
+
+ /**
+ * The given user was not found
+ * Parameters:
+ * - User Id
+ */
+ String USER_NOT_FOUND = PREFIX+"user.not_found";
+
+ /**
+ * Error from UserManager
+ * Parameters:
+ * - Error Message
+ */
+ String USER_MANAGER_ERROR = PREFIX+"user_manager.error";
+
+ /**
+ * Permission to the repository denied.
+ * Parameters:
+ * - Repository Id
+ * - Permission ID
+ */
+ String PERMISSION_REPOSITORY_DENIED = PREFIX + "permission.repository.denied";
+ /**
+ * A generic authorization error thrown during the authorization check.
+ * Parameters:
+ * - Error message
+ */
+ String AUTHORIZATION_ERROR = PREFIX + "authorization.error";
+ /**
+ * When the operation needs authentication, but not authenticated user was found in the request context.
+ */
+ String NOT_AUTHENTICATED = PREFIX + "user.not_authenticated";
}
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java
index dd931217c..5aff95ef6 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java
@@ -23,13 +23,14 @@ import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.security.OAuthScope;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.archiva.components.rest.model.PagedResult;
import org.apache.archiva.redback.authorization.RedbackAuthorization;
-import org.apache.archiva.rest.api.model.v2.Artifact;
import org.apache.archiva.rest.api.model.v2.FileInfo;
import org.apache.archiva.rest.api.model.v2.MavenManagedRepository;
+import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate;
import org.apache.archiva.security.common.ArchivaRoleConstants;
import javax.ws.rs.Consumes;
@@ -199,14 +200,14 @@ public interface MavenManagedRepositoryService
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
}
)
- MavenManagedRepository updateManagedRepository( MavenManagedRepository managedRepository )
+ MavenManagedRepository updateManagedRepository( @PathParam( "id" ) String repositoryId, MavenManagedRepositoryUpdate managedRepository )
throws ArchivaRestServiceException;
- @Path( "{id}/a/{filePath: .+}" )
+ @Path( "{id}/path/{filePath: .+}" )
@GET
@Produces( {MediaType.APPLICATION_JSON} )
- @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
+ @RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, resource = "{id}")
@Operation( summary = "Returns the status of a given file in the repository",
security = {
@SecurityRequirement(
@@ -229,18 +230,28 @@ public interface MavenManagedRepositoryService
/**
- * permissions are checked in impl
+ * Permissions are checked in impl
* will copy an artifact from the source repository to the target repository
*/
- @Path ("{srcId}/a/{path: .+}/copyto/{dstId}")
+ @Path ("{srcId}/path/{path: .+}/copyto/{dstId}")
@POST
@Produces({APPLICATION_JSON})
@RedbackAuthorization (noPermission = true)
@Operation( summary = "Copies a artifact from the source repository to the destination repository",
security = {
@SecurityRequirement(
- name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
+ name = ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS,
+ scopes = {
+ "{srcId}"
+ }
+ ),
+ @SecurityRequirement(
+ name= ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
+ scopes = {
+ "{dstId}"
+ }
)
+
},
responses = {
@ApiResponse( responseCode = "200",
@@ -257,7 +268,7 @@ public interface MavenManagedRepositoryService
throws ArchivaRestServiceException;
- @Path ("{id}/a/{path: .+}")
+ @Path ("{id}/path/{path: .+}")
@DELETE
@Consumes ({ APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@@ -280,7 +291,7 @@ public interface MavenManagedRepositoryService
Response deleteArtifact( @PathParam( "id" ) String repositoryId, @PathParam( "path" ) String path )
throws ArchivaRestServiceException;
- @Path ("{id}/c/{namespace}/{projectId}/{version}")
+ @Path ( "{id}/co/{group}/{project}/{version}" )
@DELETE
@Produces ({ MediaType.APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@@ -301,12 +312,12 @@ public interface MavenManagedRepositoryService
}
)
Response removeProjectVersion( @PathParam ( "id" ) String repositoryId,
- @PathParam ( "namespace" ) String namespace, @PathParam ( "projectId" ) String projectId,
- @PathParam ( "version" ) String version )
+ @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId,
+ @PathParam ( "version" ) String version )
throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
- @Path ( "{id}/c/{namespace}/{projectId}" )
+ @Path ( "{id}/co/{group}/{project}" )
@DELETE
@Produces ({ MediaType.APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@@ -326,10 +337,10 @@ public interface MavenManagedRepositoryService
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
}
)
- Response deleteProject( @PathParam ("id") String repositoryId, @PathParam ( "namespace" ) String namespace, @PathParam ("projectId") String projectId )
+ Response deleteProject( @PathParam ("id") String repositoryId, @PathParam ( "group" ) String namespace, @PathParam ( "project" ) String projectId )
throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;
- @Path ( "{id}/c/{namespace}" )
+ @Path ( "{id}/co/{namespace}" )
@DELETE
@Produces ({ MediaType.APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
diff --git a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
index 7fbfe16ce..6fd85d5cf 100644
--- a/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
+++ b/archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java
@@ -17,27 +17,62 @@ package org.apache.archiva.rest.services.v2;
* under the License.
*/
+import org.apache.archiva.admin.model.AuditInformation;
import org.apache.archiva.admin.model.RepositoryAdminException;
import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
import org.apache.archiva.components.rest.model.PagedResult;
import org.apache.archiva.components.rest.util.QueryHelper;
+import org.apache.archiva.redback.authentication.AuthenticationResult;
+import org.apache.archiva.redback.authorization.AuthorizationException;
+import org.apache.archiva.redback.rest.services.RedbackAuthenticationThreadLocal;
+import org.apache.archiva.redback.rest.services.RedbackRequestInformation;
+import org.apache.archiva.redback.system.DefaultSecuritySession;
+import org.apache.archiva.redback.system.SecuritySession;
+import org.apache.archiva.redback.system.SecuritySystem;
+import org.apache.archiva.redback.users.User;
+import org.apache.archiva.redback.users.UserManagerException;
+import org.apache.archiva.redback.users.UserNotFoundException;
import org.apache.archiva.repository.ManagedRepository;
+import org.apache.archiva.repository.ReleaseScheme;
+import org.apache.archiva.repository.Repository;
+import org.apache.archiva.repository.RepositoryException;
import org.apache.archiva.repository.RepositoryRegistry;
+import org.apache.archiva.repository.RepositoryType;
+import org.apache.archiva.repository.content.ContentItem;
+import org.apache.archiva.repository.content.LayoutException;
+import org.apache.archiva.repository.storage.fs.FilesystemStorage;
+import org.apache.archiva.repository.storage.fs.FsStorageUtil;
+import org.apache.archiva.repository.storage.util.StorageUtil;
import org.apache.archiva.rest.api.model.v2.Artifact;
import org.apache.archiva.rest.api.model.v2.FileInfo;
import org.apache.archiva.rest.api.model.v2.MavenManagedRepository;
+import org.apache.archiva.rest.api.model.v2.MavenManagedRepositoryUpdate;
import org.apache.archiva.rest.api.services.v2.ArchivaRestServiceException;
import org.apache.archiva.rest.api.services.v2.ErrorKeys;
import org.apache.archiva.rest.api.services.v2.ErrorMessage;
import org.apache.archiva.rest.api.services.v2.MavenManagedRepositoryService;
+import org.apache.archiva.security.common.ArchivaRoleConstants;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
+import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Comparator;
import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS;
+import static org.apache.archiva.security.common.ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD;
/**
* @author Martin Stockhammer <martin_s@apache.org>
@@ -45,81 +80,196 @@ import java.util.List;
@Service("v2.managedMavenRepositoryService#rest")
public class DefaultMavenManagedRepositoryService implements MavenManagedRepositoryService
{
+ @Context
+ HttpServletResponse httpServletResponse;
+
+ @Context
+ UriInfo uriInfo;
+
private static final Logger log = LoggerFactory.getLogger( DefaultMavenManagedRepositoryService.class );
- private static final QueryHelper<org.apache.archiva.admin.model.beans.ManagedRepository> QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} );
+ private static final QueryHelper<ManagedRepository> QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} );
static
{
- QUERY_HELPER.addStringFilter( "id", org.apache.archiva.admin.model.beans.ManagedRepository::getId );
- QUERY_HELPER.addStringFilter( "name", org.apache.archiva.admin.model.beans.ManagedRepository::getName );
- QUERY_HELPER.addStringFilter( "location", org.apache.archiva.admin.model.beans.ManagedRepository::getName );
- QUERY_HELPER.addBooleanFilter( "snapshot", org.apache.archiva.admin.model.beans.ManagedRepository::isSnapshots );
- QUERY_HELPER.addBooleanFilter( "release", org.apache.archiva.admin.model.beans.ManagedRepository::isReleases );
- QUERY_HELPER.addNullsafeFieldComparator( "id", org.apache.archiva.admin.model.beans.ManagedRepository::getId );
- QUERY_HELPER.addNullsafeFieldComparator( "name", org.apache.archiva.admin.model.beans.ManagedRepository::getName );
+ QUERY_HELPER.addStringFilter( "id", ManagedRepository::getId );
+ QUERY_HELPER.addStringFilter( "name", ManagedRepository::getName );
+ QUERY_HELPER.addStringFilter( "location", (r) -> r.getLocation().toString() );
+ QUERY_HELPER.addBooleanFilter( "snapshot", (r) -> r.getActiveReleaseSchemes( ).contains( ReleaseScheme.SNAPSHOT ) );
+ QUERY_HELPER.addBooleanFilter( "release", (r) -> r.getActiveReleaseSchemes().contains( ReleaseScheme.RELEASE ));
+ QUERY_HELPER.addNullsafeFieldComparator( "id", ManagedRepository::getId );
+ QUERY_HELPER.addNullsafeFieldComparator( "name", ManagedRepository::getName );
}
private ManagedRepositoryAdmin managedRepositoryAdmin;
private RepositoryRegistry repositoryRegistry;
+ private SecuritySystem securitySystem;
- public DefaultMavenManagedRepositoryService( RepositoryRegistry repositoryRegistry, ManagedRepositoryAdmin managedRepositoryAdmin )
+ public DefaultMavenManagedRepositoryService( SecuritySystem securitySystem, RepositoryRegistry repositoryRegistry, ManagedRepositoryAdmin managedRepositoryAdmin )
{
+ this.securitySystem = securitySystem;
+ this.repositoryRegistry = repositoryRegistry;
this.managedRepositoryAdmin = managedRepositoryAdmin;
}
+ protected AuditInformation getAuditInformation( )
+ {
+ RedbackRequestInformation redbackRequestInformation = RedbackAuthenticationThreadLocal.get( );
+ User user = redbackRequestInformation == null ? null : redbackRequestInformation.getUser( );
+ String remoteAddr = redbackRequestInformation == null ? null : redbackRequestInformation.getRemoteAddr( );
+ return new AuditInformation( user, remoteAddr );
+ }
+
@Override
- public PagedResult<MavenManagedRepository> getManagedRepositories( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
+ public PagedResult<MavenManagedRepository> getManagedRepositories( final String searchTerm, final Integer offset,
+ final Integer limit, final List<String> orderBy,
+ final String order ) throws ArchivaRestServiceException
{
try
{
- List<org.apache.archiva.admin.model.beans.ManagedRepository> result = managedRepositoryAdmin.getManagedRepositories( );
- int totalCount = Math.toIntExact( result.stream( ).count( ) );
+ Collection<ManagedRepository> repos = repositoryRegistry.getManagedRepositories( );
+ final Predicate<ManagedRepository> queryFilter = QUERY_HELPER.getQueryFilter( searchTerm ).and( r -> r.getType() == RepositoryType.MAVEN );
+ final Comparator<ManagedRepository> comparator = QUERY_HELPER.getComparator( orderBy, order );
+ int totalCount = Math.toIntExact( repos.stream( ).filter( queryFilter ).count( ) );
+ return PagedResult.of( totalCount, offset, limit, repos.stream( ).filter( queryFilter ).sorted( comparator )
+ .map(mr -> MavenManagedRepository.of(mr)).skip( offset ).limit( limit ).collect( Collectors.toList( ) ) );
}
catch (ArithmeticException e) {
log.error( "Invalid number of repositories detected." );
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.INVALID_RESULT_SET_ERROR ) );
}
- catch ( RepositoryAdminException e )
- {
- e.printStackTrace( );
- }
- return null;
-
}
@Override
public MavenManagedRepository getManagedRepository( String repositoryId ) throws ArchivaRestServiceException
{
- return null;
+ ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
+ if (repo==null) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+ }
+ if (repo.getType()!=RepositoryType.MAVEN) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 );
+ }
+ return MavenManagedRepository.of( repo );
}
@Override
public Response deleteManagedRepository( String repositoryId, boolean deleteContent ) throws ArchivaRestServiceException
{
- return null;
+ ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
+ if (repo==null) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+ }
+ if (repo.getType()!=RepositoryType.MAVEN) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_WRONG_TYPE, repositoryId, repo.getType().name() ), 404 );
+ }
+ try
+ {
+ managedRepositoryAdmin.deleteManagedRepository( repositoryId, getAuditInformation( ), deleteContent );
+ return Response.ok( ).build( );
+ }
+ catch ( RepositoryAdminException e )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_DELETE_FAILED, e.getMessage( ) ) );
+ }
+ }
+
+ private org.apache.archiva.admin.model.beans.ManagedRepository convert(MavenManagedRepository repository) {
+ org.apache.archiva.admin.model.beans.ManagedRepository repoBean = new org.apache.archiva.admin.model.beans.ManagedRepository( );
+ repoBean.setId( repository.getId( ) );
+ repoBean.setName( repository.getName() );
+ repoBean.setDescription( repository.getDescription() );
+ repoBean.setBlockRedeployments( repository.isBlocksRedeployments() );
+ repoBean.setCronExpression( repository.getSchedulingDefinition() );
+ repoBean.setLocation( repository.getLocation() );
+ repoBean.setReleases( repository.getReleaseSchemes().contains( ReleaseScheme.RELEASE.name() ) );
+ repoBean.setSnapshots( repository.getReleaseSchemes().contains( ReleaseScheme.SNAPSHOT.name() ) );
+ repoBean.setScanned( repository.isScanned() );
+ repoBean.setDeleteReleasedSnapshots( repository.isDeleteSnapshotsOfRelease() );
+ repoBean.setSkipPackedIndexCreation( repository.isSkipPackedIndexCreation() );
+ repoBean.setRetentionCount( repository.getRetentionCount() );
+ repoBean.setRetentionPeriod( repository.getRetentionPeriod().getDays() );
+ repoBean.setIndexDirectory( repository.getIndexPath() );
+ repoBean.setPackedIndexDirectory( repository.getPackedIndexPath() );
+ repoBean.setLayout( repository.getLayout() );
+ repoBean.setType( RepositoryType.MAVEN.name( ) );
+ return repoBean;
}
@Override
public MavenManagedRepository addManagedRepository( MavenManagedRepository managedRepository ) throws ArchivaRestServiceException
{
- return null;
+ final String repoId = managedRepository.getId( );
+ if ( StringUtils.isEmpty( repoId ) ) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_INVALID_ID, repoId ), 422 );
+ }
+ Repository repo = repositoryRegistry.getRepository( repoId );
+ if (repo!=null) {
+ httpServletResponse.setHeader( "Location", uriInfo.getAbsolutePathBuilder( ).path( repoId ).build( ).toString( ) );
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ID_EXISTS, repoId ), 303 );
+ }
+ try
+ {
+ managedRepositoryAdmin.addManagedRepository( convert( managedRepository ), managedRepository.isHasStagingRepository(), getAuditInformation() );
+ httpServletResponse.setStatus( 201 );
+ return MavenManagedRepository.of( repositoryRegistry.getManagedRepository( repoId ) );
+ }
+ catch ( RepositoryAdminException e )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+ }
}
@Override
- public MavenManagedRepository updateManagedRepository( MavenManagedRepository managedRepository ) throws ArchivaRestServiceException
+ public MavenManagedRepository updateManagedRepository( final String repositoryId, final MavenManagedRepositoryUpdate managedRepository ) throws ArchivaRestServiceException
{
- return null;
+ org.apache.archiva.admin.model.beans.ManagedRepository repo = convert( managedRepository );
+ try
+ {
+ managedRepositoryAdmin.updateManagedRepository( repo, managedRepository.isHasStagingRepository( ), getAuditInformation( ), managedRepository.isResetStats( ) );
+ ManagedRepository newRepo = repositoryRegistry.getManagedRepository( managedRepository.getId( ) );
+ if (newRepo==null) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_UPDATE_FAILED, repositoryId ) );
+ }
+ return MavenManagedRepository.of( newRepo );
+ }
+ catch ( RepositoryAdminException e )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_ADMIN_ERROR, e.getMessage( ) ) );
+ }
}
@Override
public FileInfo getFileStatus( String repositoryId, String fileLocation ) throws ArchivaRestServiceException
{
- return null;
+ ManagedRepository repo = repositoryRegistry.getManagedRepository( repositoryId );
+ if (repo==null) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, repositoryId ), 404 );
+ }
+ try
+ {
+ ContentItem contentItem = repo.getContent( ).toItem( fileLocation );
+ if (contentItem.getAsset( ).exists( )) {
+ return FileInfo.of( contentItem.getAsset( ) );
+ } else {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, repositoryId, fileLocation ), 404 );
+ }
+ }
+ catch ( LayoutException e )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage( ) ) );
+ }
}
@Override
public Response copyArtifact( String srcRepositoryId, String dstRepositoryId,
String path ) throws ArchivaRestServiceException
{
+ final AuditInformation auditInformation = getAuditInformation( );
+ final String userName = auditInformation.getUser( ).getUsername( );
+ if ( StringUtils.isEmpty( userName ) )
+ {
+ httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" );
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.NOT_AUTHENTICATED ), 401 );
+ }
ManagedRepository srcRepo = repositoryRegistry.getManagedRepository( srcRepositoryId );
if (srcRepo==null) {
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, srcRepositoryId ), 404 );
@@ -128,17 +278,89 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit
if (dstRepo==null) {
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, dstRepositoryId ), 404 );
}
- if (dstRepo.getAsset( path ).exists()) {
- throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_EXISTS_AT_DEST, path ) );
+ checkAuthority( auditInformation.getUser().getUsername(), srcRepositoryId, dstRepositoryId );
+ try
+ {
+ ContentItem srcItem = srcRepo.getContent( ).toItem( path );
+ ContentItem dstItem = dstRepo.getContent( ).toItem( path );
+ if (!srcItem.getAsset().exists()){
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_NOT_FOUND, srcRepositoryId, path ), 404 );
+ }
+ if (dstItem.getAsset().exists()) {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_EXISTS_AT_DEST, srcRepositoryId, path ), 400 );
+ }
+ FsStorageUtil.copyAsset( srcItem.getAsset( ), dstItem.getAsset( ), true );
+ }
+ catch ( LayoutException e )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_LAYOUT_ERROR, e.getMessage() ) );
+ }
+ catch ( IOException e )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.ARTIFACT_COPY_ERROR, e.getMessage() ) );
+ }
+ return Response.ok( ).build();
+ }
+
+ private void checkAuthority(final String userName, final String srcRepositoryId, final String dstRepositoryId ) throws ArchivaRestServiceException {
+ User user = null;
+ try
+ {
+ user = securitySystem.getUserManager().findUser( userName );
+ }
+ catch ( UserNotFoundException e )
+ {
+ httpServletResponse.setHeader( "WWW-Authenticate", "Bearer realm=\"archiva\"" );
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_NOT_FOUND, userName ), 401 );
+ }
+ catch ( UserManagerException e )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.USER_MANAGER_ERROR, e.getMessage( ) ) );
+ }
+
+ // check karma on source : read
+ AuthenticationResult authn = new AuthenticationResult( true, userName, null );
+ SecuritySession securitySession = new DefaultSecuritySession( authn, user );
+ try
+ {
+ boolean authz =
+ securitySystem.isAuthorized( securitySession, OPERATION_REPOSITORY_ACCESS,
+ srcRepositoryId );
+ if ( !authz )
+ {
+ throw new ArchivaRestServiceException(ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, srcRepositoryId, OPERATION_REPOSITORY_ACCESS ), 403);
+ }
+ }
+ catch ( AuthorizationException e )
+ {
+ log.error( "Error reading permission: {}", e.getMessage(), e );
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403);
+ }
+
+ // check karma on target: write
+ try
+ {
+ boolean authz =
+ securitySystem.isAuthorized( securitySession, ArchivaRoleConstants.OPERATION_REPOSITORY_UPLOAD,
+ dstRepositoryId );
+ if ( !authz )
+ {
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.PERMISSION_REPOSITORY_DENIED, dstRepositoryId, OPERATION_REPOSITORY_UPLOAD ) );
+ }
+ }
+ catch ( AuthorizationException e )
+ {
+ log.error( "Error reading permission: {}", e.getMessage(), e );
+ throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.AUTHORIZATION_ERROR, e.getMessage() ), 403);
}
- return null;
}
@Override
public Response deleteArtifact( String repositoryId, String path ) throws ArchivaRestServiceException
{
+
return null;
}
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/DavResourceTest.java b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/DavResourceTest.java
index f09ba013c..6df8624f1 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/DavResourceTest.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/test/java/org/apache/archiva/webdav/DavResourceTest.java
@@ -27,6 +27,7 @@ import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.storage.fs.FilesystemAsset;
import org.apache.archiva.metadata.audit.AuditListener;
import org.apache.archiva.repository.maven.MavenManagedRepository;
+import org.apache.archiva.repository.storage.fs.FilesystemStorage;
import org.apache.archiva.test.utils.ArchivaSpringJUnit4ClassRunner;
import org.apache.archiva.webdav.util.MimeTypes;
import org.apache.commons.lang3.StringUtils;
@@ -127,7 +128,7 @@ public class DavResourceTest
private DavResource getDavResource( String logicalPath, Path file ) throws LayoutException
{
- return new ArchivaDavResource( new FilesystemAsset( repository, logicalPath, file.toAbsolutePath()) , logicalPath, repository, session, resourceLocator,
+ return new ArchivaDavResource( new FilesystemAsset( (FilesystemStorage) repository.getRoot().getStorage(), logicalPath, file.toAbsolutePath()) , logicalPath, repository, session, resourceLocator,
resourceFactory, mimeTypes, Collections.<AuditListener> emptyList(), null);
}
@@ -349,7 +350,7 @@ public class DavResourceTest
{
try
{
- return new ArchivaDavResource( new FilesystemAsset(repository, "/" , baseDir.toAbsolutePath()), "/", repository, session, resourceLocator,
+ return new ArchivaDavResource( new FilesystemAsset( (FilesystemStorage) repository.getRoot().getStorage(), "/" , baseDir.toAbsolutePath()), "/", repository, session, resourceLocator,
resourceFactory, mimeTypes, Collections.<AuditListener> emptyList(),
null );
}