From 074f119a0d54e26ec920b7be391fb9e62ff5eac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Mon, 22 Feb 2021 17:48:05 +0100 Subject: [PATCH] Add rest endpoint for import log --- .../v2/resources/RepositoryImportResource.java | 16 +++++++++++++++- .../scm/importexport/RepositoryImportLog.java | 16 ++++++++++++++++ .../RepositoryImportLoggerFactory.java | 15 ++++++++++++++- .../v2/resources/RepositoryRootResourceTest.java | 5 ++++- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryImportResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryImportResource.java index 2aa982b64e..7166cb5255 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryImportResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryImportResource.java @@ -47,6 +47,7 @@ import sonia.scm.importexport.FromBundleImporter; import sonia.scm.importexport.FromUrlImporter; import sonia.scm.importexport.FullScmRepositoryImporter; import sonia.scm.importexport.RepositoryImportExportEncryption; +import sonia.scm.importexport.RepositoryImportLoggerFactory; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryPermissions; import sonia.scm.repository.api.Command; @@ -59,14 +60,17 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.Pattern; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.io.InputStream; @@ -87,6 +91,7 @@ public class RepositoryImportResource { private final RepositoryImportDtoToRepositoryImportParametersMapper importParametersMapper; private final FromUrlImporter fromUrlImporter; private final FromBundleImporter fromBundleImporter; + private final RepositoryImportLoggerFactory importLoggerFactory; @Inject public RepositoryImportResource(RepositoryDtoToRepositoryMapper mapper, @@ -94,7 +99,8 @@ public class RepositoryImportResource { FullScmRepositoryImporter fullScmRepositoryImporter, RepositoryImportDtoToRepositoryImportParametersMapper importParametersMapper, RepositoryImportExportEncryption repositoryImportExportEncryption, FromUrlImporter fromUrlImporter, - FromBundleImporter fromBundleImporter) { + FromBundleImporter fromBundleImporter, + RepositoryImportLoggerFactory importLoggerFactory) { this.mapper = mapper; this.resourceLinks = resourceLinks; this.fullScmRepositoryImporter = fullScmRepositoryImporter; @@ -102,6 +108,7 @@ public class RepositoryImportResource { this.importParametersMapper = importParametersMapper; this.fromUrlImporter = fromUrlImporter; this.fromBundleImporter = fromBundleImporter; + this.importLoggerFactory = importLoggerFactory; } /** @@ -254,6 +261,13 @@ public class RepositoryImportResource { return Response.created(URI.create(resourceLinks.repository().self(createdRepository.getNamespace(), createdRepository.getName()))).build(); } + @GET + @Path("log/{logId}") + @Produces(MediaType.TEXT_PLAIN) + public StreamingOutput getImportLog(@PathParam("logId") String logId) { + return out -> importLoggerFactory.getLog(logId, out); + } + private Repository importFullRepositoryFromInput(MultipartFormDataInput input) { Map> formParts = input.getFormDataMap(); InputStream inputStream = extractInputStream(formParts); diff --git a/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLog.java b/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLog.java index 7faea2349b..af42c44f2d 100644 --- a/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLog.java +++ b/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLog.java @@ -35,6 +35,8 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import static java.lang.String.format; +import static java.util.Arrays.asList; import static java.util.Collections.unmodifiableList; @XmlRootElement(name = "import") @@ -65,6 +67,16 @@ class RepositoryImportLog { return unmodifiableList(entries); } + public List toLogHeader() { + return asList( + format("Import of repository %s/%s", namespace, name), + format("Repository type: %s", repositoryId), + format("Imported from: %s", type), + format("Imported by %s (%s)", userId, userName), + success ? "Finished successful" : "Import failed" + ); + } + enum ImportType { FULL, URL, DUMP } @@ -82,5 +94,9 @@ class RepositoryImportLog { Entry(String message) { this.message = message; } + + public String toLogMessage() { + return time + " - " + message; + } } } diff --git a/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLoggerFactory.java b/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLoggerFactory.java index 9530844daa..4cf01198ac 100644 --- a/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLoggerFactory.java +++ b/scm-webapp/src/main/java/sonia/scm/importexport/RepositoryImportLoggerFactory.java @@ -24,11 +24,14 @@ package sonia.scm.importexport; +import sonia.scm.NotFoundException; import sonia.scm.store.DataStoreFactory; import javax.inject.Inject; +import java.io.OutputStream; +import java.io.PrintStream; -class RepositoryImportLoggerFactory { +public class RepositoryImportLoggerFactory { private final DataStoreFactory dataStoreFactory; @@ -40,4 +43,14 @@ class RepositoryImportLoggerFactory { RepositoryImportLogger createLogger() { return new RepositoryImportLogger(dataStoreFactory.withType(RepositoryImportLog.class).withName("imports").build()); } + + public void getLog(String logId, OutputStream out) { + RepositoryImportLog log = dataStoreFactory.withType(RepositoryImportLog.class).withName("imports").build().getOptional(logId).orElseThrow(() -> new NotFoundException("Log", logId)); + PrintStream printStream = new PrintStream(out); + log.toLogHeader().forEach(printStream::println); + log.getEntries() + .stream() + .map(RepositoryImportLog.Entry::toLogMessage) + .forEach(printStream::println); + } } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java index 413f108a66..bf39e35aae 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java @@ -53,6 +53,7 @@ import sonia.scm.importexport.FromUrlImporter; import sonia.scm.importexport.FullScmRepositoryExporter; import sonia.scm.importexport.FullScmRepositoryImporter; import sonia.scm.importexport.RepositoryImportExportEncryption; +import sonia.scm.importexport.RepositoryImportLoggerFactory; import sonia.scm.repository.CustomNamespaceStrategy; import sonia.scm.repository.NamespaceAndName; import sonia.scm.repository.NamespaceStrategy; @@ -166,6 +167,8 @@ public class RepositoryRootResourceTest extends RepositoryTestBase { @Mock private ExportFileExtensionResolver fileExtensionResolver; @Mock + private RepositoryImportLoggerFactory importLoggerFactory; + @Mock private ExportService exportService; @Captor @@ -187,7 +190,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase { super.manager = repositoryManager; RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks); super.repositoryCollectionResource = new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks, repositoryInitializer); - super.repositoryImportResource = new RepositoryImportResource(dtoToRepositoryMapper, resourceLinks, fullScmRepositoryImporter, new RepositoryImportDtoToRepositoryImportParametersMapperImpl(), repositoryImportExportEncryption, fromUrlImporter, fromBundleImporter); + super.repositoryImportResource = new RepositoryImportResource(dtoToRepositoryMapper, resourceLinks, fullScmRepositoryImporter, new RepositoryImportDtoToRepositoryImportParametersMapperImpl(), repositoryImportExportEncryption, fromUrlImporter, fromBundleImporter, importLoggerFactory); super.repositoryExportResource = new RepositoryExportResource(repositoryManager, serviceFactory, fullScmRepositoryExporter, repositoryImportExportEncryption, exportService, exportInformationToDtoMapper, fileExtensionResolver, resourceLinks); dispatcher.addSingletonResource(getRepositoryRootResource()); when(serviceFactory.create(any(Repository.class))).thenReturn(service);