Browse Source

Adding REST v2 methods for repository

pull/62/head
Martin Stockhammer 3 years ago
parent
commit
27640503d6

+ 7
- 1
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/ErrorKeys.java View File

@@ -70,10 +70,16 @@ public interface ErrorKeys

String REPOSITORY_GROUP_DELETE_FAILED = REPOSITORY_GROUP_PREFIX + "delete.failed";
String REPOSITORY_NOT_FOUND = REPOSITORY_PREFIX + "notfound";
String REPOSITORY_MANAGED_NOT_FOUND = REPOSITORY_PREFIX + ".managed.notfound";
String REPOSITORY_MANAGED_NOT_FOUND = REPOSITORY_PREFIX + "managed.notfound";
String REPOSITORY_REMOTE_NOT_FOUND = REPOSITORY_PREFIX + "remote.notfound";

String REPOSITORY_METADATA_ERROR = REPOSITORY_PREFIX + "metadata_error";

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";


}

+ 57
- 4
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/MavenManagedRepositoryService.java View File

@@ -27,6 +27,7 @@ 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.security.common.ArchivaRoleConstants;
@@ -202,7 +203,7 @@ public interface MavenManagedRepositoryService
throws ArchivaRestServiceException;


@Path( "{id}/files/{filePath: .+}" )
@Path( "{id}/a/{filePath: .+}" )
@GET
@Produces( {MediaType.APPLICATION_JSON} )
@RedbackAuthorization( permissions = ArchivaRoleConstants.OPERATION_MANAGE_CONFIGURATION )
@@ -227,7 +228,59 @@ public interface MavenManagedRepositoryService
throws ArchivaRestServiceException;


@Path ("{id}/content/{namespace}/{projectId}/{version}")
/**
* permissions are checked in impl
* will copy an artifact from the source repository to the target repository
*/
@Path ("{srcId}/a/{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
)
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the artifact was copied"
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
@ApiResponse( responseCode = "404", description = "The repository does not exist, or if the artifact was not found",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
}
)
Response copyArtifact( @PathParam( "srcId" ) String srcRepositoryId, @PathParam( "dstId" ) String dstRepositoryId,
@PathParam( "path" ) String path )
throws ArchivaRestServiceException;


@Path ("{id}/a/{path: .+}")
@DELETE
@Consumes ({ APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@Operation( summary = "Deletes a artifact in the repository.",
security = {
@SecurityRequirement(
name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
)
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the artifact was deleted"
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
@ApiResponse( responseCode = "404", description = "The repository or the artifact does not exist",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
}
)
Response deleteArtifact( @PathParam( "id" ) String repositoryId, @PathParam( "path" ) String path )
throws ArchivaRestServiceException;

@Path ("{id}/c/{namespace}/{projectId}/{version}")
@DELETE
@Produces ({ MediaType.APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@@ -253,7 +306,7 @@ public interface MavenManagedRepositoryService
throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;


@Path ( "{id}/content/{namespace}/{projectId}" )
@Path ( "{id}/c/{namespace}/{projectId}" )
@DELETE
@Produces ({ MediaType.APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@@ -276,7 +329,7 @@ public interface MavenManagedRepositoryService
Response deleteProject( @PathParam ("id") String repositoryId, @PathParam ( "namespace" ) String namespace, @PathParam ("projectId") String projectId )
throws org.apache.archiva.rest.api.services.ArchivaRestServiceException;

@Path ( "{id}/content/{namespace}" )
@Path ( "{id}/c/{namespace}" )
@DELETE
@Produces ({ MediaType.APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)

+ 12
- 66
archiva-modules/archiva-web/archiva-rest/archiva-rest-api/src/main/java/org/apache/archiva/rest/api/services/v2/RepositoryService.java View File

@@ -26,8 +26,6 @@ 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.ArtifactTransferRequest;
import org.apache.archiva.rest.api.model.v2.Repository;
import org.apache.archiva.rest.api.model.v2.RepositoryStatistics;
import org.apache.archiva.rest.api.model.v2.ScanStatus;
@@ -42,8 +40,9 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.List;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@@ -170,13 +169,6 @@ public interface RepositoryService
throws ArchivaRestServiceException;


/**
* Returns the scan status of the given repository
* @param repositoryId the repository identifier
* @return the status
* @throws ArchivaRestServiceException
* @since 3.0
*/
@Path ("managed/{id}/scan/status")
@GET
@Produces ({ APPLICATION_JSON })
@@ -205,7 +197,7 @@ public interface RepositoryService
@DELETE
@Produces ({ APPLICATION_JSON })
@RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
@Operation( summary = "Removes a scan task from the queue.",
@Operation( summary = "Cancels and removes all tasks for the given repository.",
security = {
@SecurityRequirement(
name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
@@ -224,40 +216,17 @@ public interface RepositoryService
Response removeScanningTaskFromQueue( @PathParam ("id") String repositoryId )
throws ArchivaRestServiceException;

/**
* permissions are checked in impl
* will copy an artifact from the source repository to the target repository
*/
@Path ("managed/{id}/artifact/copy")
@POST
@Produces({APPLICATION_JSON})
@Consumes({ APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@Operation( summary = "Copies a artifact between repositories.",
security = {
@SecurityRequirement(
name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
)
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the artifact was copied"
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
@ApiResponse( responseCode = "404", description = "The repository does not exist, or if the artifact was not found",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
}
)
Response copyArtifact( ArtifactTransferRequest artifactTransferRequest )
throws ArchivaRestServiceException;

@Path ("managed/{id}/index/download/start")

@Path ("remote/{id}/index/download/start")
@POST
@Produces ({ APPLICATION_JSON })
@Consumes({ APPLICATION_JSON })
@RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
@Operation( summary = "Schedules a task for remote index download.",
parameters = {
@Parameter( name = "full", description = "If true, download the full index, otherwise try a update download." )
},
security = {
@SecurityRequirement(
name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
@@ -274,38 +243,15 @@ public interface RepositoryService
}
)
Response scheduleDownloadRemoteIndex( @PathParam ("id") String repositoryId,
@QueryParam ("now") boolean now,
@QueryParam ("fullDownload") boolean fullDownload )
@QueryParam( "immediate" ) boolean immediately,
@QueryParam ("full") boolean full, @Context UriInfo uriInfo )
throws ArchivaRestServiceException;


@Path ("managed/{id}/artifact")
@DELETE
@Consumes ({ APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@Operation( summary = "Deletes a artifact in the repository.",
security = {
@SecurityRequirement(
name = ArchivaRoleConstants.OPERATION_RUN_INDEXER
)
},
responses = {
@ApiResponse( responseCode = "200",
description = "If the artifact was deleted"
),
@ApiResponse( responseCode = "403", description = "Authenticated user is not permitted to gather the information",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) ),
@ApiResponse( responseCode = "404", description = "The repository or the artifact does not exist",
content = @Content( mediaType = APPLICATION_JSON, schema = @Schema( implementation = ArchivaRestError.class ) ) )
}
)
Response deleteArtifact( Artifact artifact )
throws ArchivaRestServiceException;

@Path ("index_downloads")
@Path ("remote/index/downloads")
@GET
@Produces ({ APPLICATION_JSON })
@RedbackAuthorization (noPermission = true)
@RedbackAuthorization (permissions = ArchivaRoleConstants.OPERATION_RUN_INDEXER)
@Operation( summary = "Returns a list of running downloads from the remote repository.",
security = {
@SecurityRequirement(

+ 38
- 1
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultMavenManagedRepositoryService.java View File

@@ -21,6 +21,9 @@ 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.repository.ManagedRepository;
import org.apache.archiva.repository.RepositoryRegistry;
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.services.v2.ArchivaRestServiceException;
@@ -29,14 +32,17 @@ import org.apache.archiva.rest.api.services.v2.ErrorMessage;
import org.apache.archiva.rest.api.services.v2.MavenManagedRepositoryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.inject.Inject;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import java.util.List;

/**
* @author Martin Stockhammer <martin_s@apache.org>
*/
@Service("v2.managedMavenRepositoryService#rest")
public class DefaultMavenManagedRepositoryService implements MavenManagedRepositoryService
{
private static final Logger log = LoggerFactory.getLogger( DefaultMavenManagedRepositoryService.class );
@@ -52,9 +58,13 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit
QUERY_HELPER.addNullsafeFieldComparator( "name", org.apache.archiva.admin.model.beans.ManagedRepository::getName );
}

@Inject
private ManagedRepositoryAdmin managedRepositoryAdmin;
private RepositoryRegistry repositoryRegistry;

public DefaultMavenManagedRepositoryService( RepositoryRegistry repositoryRegistry, ManagedRepositoryAdmin managedRepositoryAdmin )
{
this.managedRepositoryAdmin = managedRepositoryAdmin;
}

@Override
public PagedResult<MavenManagedRepository> getManagedRepositories( String searchTerm, Integer offset, Integer limit, List<String> orderBy, String order ) throws ArchivaRestServiceException
@@ -106,6 +116,33 @@ public class DefaultMavenManagedRepositoryService implements MavenManagedReposit
return null;
}

@Override
public Response copyArtifact( String srcRepositoryId, String dstRepositoryId,
String path ) throws ArchivaRestServiceException
{
ManagedRepository srcRepo = repositoryRegistry.getManagedRepository( srcRepositoryId );
if (srcRepo==null) {
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_NOT_FOUND, srcRepositoryId ), 404 );
}
ManagedRepository dstRepo = repositoryRegistry.getManagedRepository( dstRepositoryId );
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 ) );
}


return null;
}

@Override
public Response deleteArtifact( String repositoryId, String path ) throws ArchivaRestServiceException
{
return null;
}


@Override
public Response removeProjectVersion( String repositoryId, String namespace, String projectId, String version ) throws org.apache.archiva.rest.api.services.ArchivaRestServiceException
{

+ 39
- 18
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/main/java/org/apache/archiva/rest/services/v2/DefaultRepositoryService.java View File

@@ -21,13 +21,13 @@ import org.apache.archiva.admin.model.RepositoryAdminException;
import org.apache.archiva.admin.model.admin.RepositoryTaskAdministration;
import org.apache.archiva.components.rest.model.PagedResult;
import org.apache.archiva.components.rest.util.QueryHelper;
import org.apache.archiva.components.rest.util.RestUtil;
import org.apache.archiva.metadata.repository.MetadataRepositoryException;
import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager;
import org.apache.archiva.repository.RemoteRepository;
import org.apache.archiva.repository.RepositoryRegistry;
import org.apache.archiva.repository.scanner.RepositoryScanner;
import org.apache.archiva.repository.scanner.RepositoryScannerException;
import org.apache.archiva.rest.api.model.v2.Artifact;
import org.apache.archiva.rest.api.model.v2.ArtifactTransferRequest;
import org.apache.archiva.rest.api.model.v2.Repository;
import org.apache.archiva.rest.api.model.v2.RepositoryStatistics;
import org.apache.archiva.rest.api.model.v2.ScanStatus;
@@ -35,6 +35,8 @@ 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.RepositoryService;
import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexException;
import org.apache.archiva.scheduler.indexing.DownloadRemoteIndexScheduler;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,6 +44,7 @@ import org.springframework.stereotype.Service;

import javax.inject.Named;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
@@ -66,6 +69,7 @@ public class DefaultRepositoryService implements RepositoryService

private final RepositoryScanner repoScanner;

private final DownloadRemoteIndexScheduler downloadRemoteIndexScheduler;

private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryService.class );
private static final QueryHelper<org.apache.archiva.repository.Repository> QUERY_HELPER = new QueryHelper<>( new String[]{"id", "name"} );
@@ -85,12 +89,13 @@ public class DefaultRepositoryService implements RepositoryService

public DefaultRepositoryService( RepositoryRegistry repositoryRegistry, RepositoryStatisticsManager repositoryStatisticsManager,
@Named( value = "repositoryTaskAdministration#default") RepositoryTaskAdministration repositoryTaskAdministration,
RepositoryScanner repoScanner )
RepositoryScanner repoScanner, DownloadRemoteIndexScheduler downloadRemoteIndexScheduler )
{
this.repositoryRegistry = repositoryRegistry;
this.repositoryStatisticsManager = repositoryStatisticsManager;
this.repoScanner = repoScanner;
this.repositoryTaskAdministration = repositoryTaskAdministration;
this.downloadRemoteIndexScheduler = downloadRemoteIndexScheduler;
}

private void handleAdminException( RepositoryAdminException e ) throws ArchivaRestServiceException
@@ -187,37 +192,53 @@ public class DefaultRepositoryService implements RepositoryService
catch ( RepositoryAdminException e )
{
handleAdminException( e );
return null;
return new ScanStatus();
}
}

@Override
public Response removeScanningTaskFromQueue( String repositoryId ) throws ArchivaRestServiceException
{
return null;
try
{
repositoryTaskAdministration.cancelTasks( repositoryId );
return Response.ok( ).build( );
}
catch ( RepositoryAdminException e )
{
handleAdminException( e );
return Response.serverError( ).build( );
}
}

@Override
public Response copyArtifact( ArtifactTransferRequest artifactTransferRequest ) throws ArchivaRestServiceException
{
return null;
}

@Override
public Response scheduleDownloadRemoteIndex( String repositoryId, boolean now, boolean fullDownload ) throws ArchivaRestServiceException
public Response scheduleDownloadRemoteIndex( String repositoryId, boolean immediately, boolean full,
UriInfo uriInfo ) throws ArchivaRestServiceException
{
return null;
boolean immediateSet = RestUtil.isFlagSet( uriInfo, "immediate" );
boolean fullSet = RestUtil.isFlagSet( uriInfo, "full" );
RemoteRepository repo = repositoryRegistry.getRemoteRepository( repositoryId );
if (repo==null) {
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_NOT_FOUND, repositoryId ), 404 );
}
try
{
downloadRemoteIndexScheduler.scheduleDownloadRemote( repositoryId, immediateSet, fullSet );
return Response.ok( ).build( );
}
catch ( DownloadRemoteIndexException e )
{
log.error( "Could not schedule index download for repository {}: {}", repositoryId, e.getMessage(), e );
throw new ArchivaRestServiceException( ErrorMessage.of( ErrorKeys.REPOSITORY_REMOTE_INDEX_DOWNLOAD_FAILED, e.getMessage( ) ) );
}
}

@Override
public Response deleteArtifact( Artifact artifact ) throws ArchivaRestServiceException
{
return null;
}


@Override
public List<String> getRunningRemoteDownloads( )
{
return null;
return downloadRemoteIndexScheduler.getRunningRemoteDownloadIds( );
}
}

+ 29
- 0
archiva-modules/archiva-web/archiva-rest/archiva-rest-services/src/test/java/org/apache/archiva/rest/services/v2/NativeRepositoryServiceTest.java View File

@@ -159,4 +159,33 @@ public class NativeRepositoryServiceTest extends AbstractNativeRestServices
assertNotNull( response );

}

@Test
void scheduleIndexDownload() {
String token = getAdminToken( );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.post( "remote/central/index/download/start" )
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
}

@Test
void getIndexDownloadList() {
String token = getAdminToken( );
given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.queryParam( "immediate", "true" )
.post( "remote/central/index/download/start" )
.then( ).statusCode( 200 ).extract( ).response( );
Response response = given( ).spec( getRequestSpec( token ) ).contentType( JSON )
.when( )
.get( "remote/index/downloads" )
.then( ).statusCode( 200 ).extract( ).response( );
assertNotNull( response );
List<String> downloads = response.getBody( ).jsonPath( ).getList( "", String.class );
assertEquals( 1, downloads.size() );
assertEquals( "central", downloads.get( 0 ) );
}

}

Loading…
Cancel
Save