From 4d8ac381fd918dd4241ec8425f520f36dfff54b4 Mon Sep 17 00:00:00 2001 From: Thomasr Date: Fri, 11 Oct 2024 04:10:06 -0400 Subject: [PATCH] add new endpoint to retrieve archived snapshot list --- ...tionHistoryArchivedSnapshotRepository.java | 26 ++++++ .../ApplicationHistorySnapshotService.java | 4 + ...ApplicationHistorySnapshotServiceImpl.java | 17 ++++ .../ApplicationHistorySnapshotController.java | 80 ++++++++++++++++--- .../ApplicationHistorySnapshotEndpoints.java | 23 ++++++ .../src/main/resources/application-debug.yaml | 2 +- .../src/main/resources/application.yaml | 2 +- 7 files changed, 141 insertions(+), 13 deletions(-) create mode 100644 server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationHistoryArchivedSnapshotRepository.java diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationHistoryArchivedSnapshotRepository.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationHistoryArchivedSnapshotRepository.java new file mode 100644 index 000000000..dded29c35 --- /dev/null +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationHistoryArchivedSnapshotRepository.java @@ -0,0 +1,26 @@ +package org.lowcoder.domain.application.repository; + +import org.lowcoder.domain.application.model.ApplicationHistorySnapshot; +import org.springframework.data.domain.Pageable; +import org.springframework.data.mongodb.repository.Query; +import org.springframework.data.mongodb.repository.ReactiveMongoRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.Instant; + +@Repository +public interface ApplicationHistoryArchivedSnapshotRepository extends ReactiveMongoRepository { + + @Query(value = "{ 'applicationId': ?0, $and: [" + + "{$or: [ { 'context.operations': { $elemMatch: { 'compName': ?1 } } }, { $expr: { $eq: [?1, null] } } ]}, " + + "{$or: [ { 'dsl.settings.themeId': ?2 }, { $expr: { $eq: [?2, null] } } ] }, " + + "{$or: [ { 'createdAt': { $gte: ?3} }, { $expr: { $eq: [?3, null] } } ] }, " + + "{$or: [ { 'createdAt': { $lte: ?4} }, { $expr: { $eq: [?4, null] } } ] } " + + "]}", + fields = "{applicationId : 1, context: 1, createdBy : 1, createdAt : 1}") + Flux findAllByApplicationId(String applicationId, String compName, String theme, Instant createdAtFrom, Instant createdAtTo, Pageable pageable); + + Mono countByApplicationId(String applicationId); +} diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationHistorySnapshotService.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationHistorySnapshotService.java index 93ccbabf7..fd4a79f82 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationHistorySnapshotService.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationHistorySnapshotService.java @@ -1,5 +1,6 @@ package org.lowcoder.domain.application.service; +import org.lowcoder.domain.application.model.ApplicationHistorySnapshot; import org.lowcoder.domain.application.model.ApplicationHistorySnapshotTS; import org.springframework.data.domain.PageRequest; import reactor.core.publisher.Mono; @@ -13,8 +14,11 @@ public interface ApplicationHistorySnapshotService { Mono createHistorySnapshot(String applicationId, Map dsl, Map context, String userId); Mono> listAllHistorySnapshotBriefInfo(String applicationId, String compName, String theme, Instant from, Instant to, PageRequest pageRequest); + Mono> listAllHistorySnapshotBriefInfoArchived(String applicationId, String compName, String theme, Instant from, Instant to, PageRequest pageRequest); Mono countByApplicationId(String applicationId); Mono getHistorySnapshotDetail(String historySnapshotId); + + Mono getHistorySnapshotDetailArchived(String historySnapshotId); } diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/impl/ApplicationHistorySnapshotServiceImpl.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/impl/ApplicationHistorySnapshotServiceImpl.java index c29905662..c47b39955 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/impl/ApplicationHistorySnapshotServiceImpl.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/impl/ApplicationHistorySnapshotServiceImpl.java @@ -1,7 +1,9 @@ package org.lowcoder.domain.application.service.impl; import lombok.RequiredArgsConstructor; +import org.lowcoder.domain.application.model.ApplicationHistorySnapshot; import org.lowcoder.domain.application.model.ApplicationHistorySnapshotTS; +import org.lowcoder.domain.application.repository.ApplicationHistoryArchivedSnapshotRepository; import org.lowcoder.domain.application.repository.ApplicationHistorySnapshotRepository; import org.lowcoder.domain.application.service.ApplicationHistorySnapshotService; import org.lowcoder.sdk.exception.BizError; @@ -23,6 +25,7 @@ public class ApplicationHistorySnapshotServiceImpl implements ApplicationHistorySnapshotService { private final ApplicationHistorySnapshotRepository repository; + private final ApplicationHistoryArchivedSnapshotRepository repositoryArchived; @Override public Mono createHistorySnapshot(String applicationId, Map dsl, Map context, String userId) { @@ -42,6 +45,13 @@ public Mono> listAllHistorySnapshotBriefInfo( .onErrorMap(Exception.class, e -> ofException(BizError.FETCH_HISTORY_SNAPSHOT_FAILURE, "FETCH_HISTORY_SNAPSHOT_FAILURE")); } + @Override + public Mono> listAllHistorySnapshotBriefInfoArchived(String applicationId, String compName, String theme, Instant from, Instant to, PageRequest pageRequest) { + return repositoryArchived.findAllByApplicationId(applicationId, compName, theme, from, to, pageRequest.withSort(Direction.DESC, "id")) + .collectList() + .onErrorMap(Exception.class, e -> ofException(BizError.FETCH_HISTORY_SNAPSHOT_FAILURE, "FETCH_HISTORY_SNAPSHOT_FAILURE")); + } + @Override public Mono countByApplicationId(String applicationId) { return repository.countByApplicationId(applicationId) @@ -55,4 +65,11 @@ public Mono getHistorySnapshotDetail(String histor return repository.findById(historySnapshotId) .switchIfEmpty(deferredError(INVALID_HISTORY_SNAPSHOT, "INVALID_HISTORY_SNAPSHOT", historySnapshotId)); } + + + @Override + public Mono getHistorySnapshotDetailArchived(String historySnapshotId) { + return repositoryArchived.findById(historySnapshotId) + .switchIfEmpty(deferredError(INVALID_HISTORY_SNAPSHOT, "INVALID_HISTORY_SNAPSHOT", historySnapshotId)); + } } diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotController.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotController.java index 0fff671ed..6b6d94a51 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotController.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotController.java @@ -1,17 +1,13 @@ package org.lowcoder.api.application; -import static org.lowcoder.api.util.ViewBuilder.multiBuild; - -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - +import com.google.common.collect.ImmutableMap; +import lombok.RequiredArgsConstructor; import org.lowcoder.api.application.view.HistorySnapshotDslView; import org.lowcoder.api.framework.view.ResponseView; import org.lowcoder.api.home.SessionUserService; import org.lowcoder.api.util.Pagination; import org.lowcoder.domain.application.model.Application; +import org.lowcoder.domain.application.model.ApplicationHistorySnapshot; import org.lowcoder.domain.application.model.ApplicationHistorySnapshotTS; import org.lowcoder.domain.application.service.ApplicationHistorySnapshotService; import org.lowcoder.domain.application.service.ApplicationService; @@ -22,11 +18,14 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; -import com.google.common.collect.ImmutableMap; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; -import reactor.core.publisher.Mono; +import static org.lowcoder.api.util.ViewBuilder.multiBuild; @RequiredArgsConstructor @RestController @@ -90,6 +89,43 @@ public Mono>> listAllHistorySnapshotBriefInfo(@ .map(ResponseView::success); } + @Override + public Mono>> listAllHistorySnapshotBriefInfoArchived(@PathVariable String applicationId, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam String compName, + @RequestParam String theme, + @RequestParam Instant from, + @RequestParam Instant to) { + + Pagination pagination = Pagination.of(page, size).check(); + + return sessionUserService.getVisitorId() + .delayUntil(visitor -> resourcePermissionService.checkResourcePermissionWithError(visitor, applicationId, + ResourceAction.EDIT_APPLICATIONS)) + .flatMap(__ -> applicationHistorySnapshotService.listAllHistorySnapshotBriefInfoArchived(applicationId, compName, theme, from, to, pagination.toPageRequest())) + .flatMap(snapshotList -> { + Mono> snapshotBriefInfoList = multiBuild(snapshotList, + ApplicationHistorySnapshot::getCreatedBy, + userService::getByIds, + (applicationHistorySnapshot, user) -> new ApplicationHistorySnapshotBriefInfo( + applicationHistorySnapshot.getId(), + applicationHistorySnapshot.getContext(), + applicationHistorySnapshot.getCreatedBy(), + user.getName(), + user.getAvatarUrl(), + applicationHistorySnapshot.getCreatedAt().toEpochMilli() + ) + ); + + Mono applicationHistorySnapshotCount = applicationHistorySnapshotService.countByApplicationId(applicationId); + + return Mono.zip(snapshotBriefInfoList, applicationHistorySnapshotCount) + .map(tuple -> ImmutableMap.of("list", tuple.getT1(), "count", tuple.getT2())); + }) + .map(ResponseView::success); + } + @Override public Mono> getHistorySnapshotDsl(@PathVariable String applicationId, @PathVariable String snapshotId) { @@ -98,7 +134,29 @@ public Mono> getHistorySnapshotDsl(@PathVar ResourceAction.EDIT_APPLICATIONS)) .flatMap(__ -> applicationHistorySnapshotService.getHistorySnapshotDetail(snapshotId)) .map(ApplicationHistorySnapshotTS::getDsl) - .zipWhen(dsl -> applicationService.getAllDependentModulesFromDsl(dsl)) + .zipWhen(applicationService::getAllDependentModulesFromDsl) + .map(tuple -> { + Map applicationDsl = tuple.getT1(); + List dependentModules = tuple.getT2(); + Map> dependentModuleDsl = dependentModules.stream() + .collect(Collectors.toMap(Application::getId, Application::getLiveApplicationDsl, (a, b) -> b)); + return HistorySnapshotDslView.builder() + .applicationsDsl(applicationDsl) + .moduleDSL(dependentModuleDsl) + .build(); + }) + .map(ResponseView::success); + } + + @Override + public Mono> getHistorySnapshotDslArchived(@PathVariable String applicationId, + @PathVariable String snapshotId) { + return sessionUserService.getVisitorId() + .delayUntil(visitor -> resourcePermissionService.checkResourcePermissionWithError(visitor, applicationId, + ResourceAction.EDIT_APPLICATIONS)) + .flatMap(__ -> applicationHistorySnapshotService.getHistorySnapshotDetailArchived(snapshotId)) + .map(ApplicationHistorySnapshot::getDsl) + .zipWhen(applicationService::getAllDependentModulesFromDsl) .map(tuple -> { Map applicationDsl = tuple.getT1(); List dependentModules = tuple.getT2(); diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotEndpoints.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotEndpoints.java index 7233b8627..32276f3a8 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotEndpoints.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationHistorySnapshotEndpoints.java @@ -46,6 +46,19 @@ public Mono>> listAllHistorySnapshotBriefInfo(@ @RequestParam(required = false ) @Nullable Instant from, @RequestParam(required = false ) @Nullable Instant to); + @Operation( + tags = TAG_APPLICATION_HISTORY_MANAGEMENT, + operationId = "listApplicationSnapshotsArchived", + summary = "List Archived Application Snapshots", + description = "Retrieve a list of Archived Snapshots associated with a specific Application within Lowcoder." + ) + @GetMapping("/archive/{applicationId}") + public Mono>> listAllHistorySnapshotBriefInfoArchived(@PathVariable String applicationId, + @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size, + @RequestParam(required = false ) @Nullable String compName, @RequestParam(required = false ) @Nullable String theme, + @RequestParam(required = false ) @Nullable Instant from, + @RequestParam(required = false ) @Nullable Instant to); + @Operation( tags = TAG_APPLICATION_HISTORY_MANAGEMENT, operationId = "getApplicationSnapshot", @@ -56,6 +69,16 @@ public Mono>> listAllHistorySnapshotBriefInfo(@ public Mono> getHistorySnapshotDsl(@PathVariable String applicationId, @PathVariable String snapshotId); + @Operation( + tags = TAG_APPLICATION_HISTORY_MANAGEMENT, + operationId = "getApplicationSnapshotArchived", + summary = "Retrieve Archived Application Snapshot", + description = "Retrieve a specific Archived Application Snapshot within Lowcoder using the Application and Snapshot IDs." + ) + @GetMapping("/archive/{applicationId}/{snapshotId}") + public Mono> getHistorySnapshotDslArchived(@PathVariable String applicationId, + @PathVariable String snapshotId); + public record ApplicationHistorySnapshotBriefInfo(String snapshotId, Map context, String userId, String userName, String userAvatar, long createTime) { diff --git a/server/api-service/lowcoder-server/src/main/resources/application-debug.yaml b/server/api-service/lowcoder-server/src/main/resources/application-debug.yaml index 4ee437276..5f16fdace 100644 --- a/server/api-service/lowcoder-server/src/main/resources/application-debug.yaml +++ b/server/api-service/lowcoder-server/src/main/resources/application-debug.yaml @@ -48,7 +48,7 @@ common: cookie: max-age-in-hours: ${LOWCODER_COOKIE_MAX_AGE:24} query: - app-snapshot-keep-duration: ${LOWCODER_QUERY_SNAPSHOT_ACTIVE_DURATION:30} + app-snapshot-keep-duration: ${LOWCODER_APP_SNAPSHOT_RETENTIONTIME:30} debug: true diff --git a/server/api-service/lowcoder-server/src/main/resources/application.yaml b/server/api-service/lowcoder-server/src/main/resources/application.yaml index fbe60e81e..1ca536930 100644 --- a/server/api-service/lowcoder-server/src/main/resources/application.yaml +++ b/server/api-service/lowcoder-server/src/main/resources/application.yaml @@ -89,7 +89,7 @@ common: cookie: max-age-in-hours: ${LOWCODER_COOKIE_MAX_AGE:24} query: - app-snapshot-keep-duration: ${LOWCODER_QUERY_SNAPSHOT_ACTIVE_DURATION:30} + app-snapshot-keep-duration: ${LOWCODER_APP_SNAPSHOT_RETENTIONTIME:30} material: mongodb-grid-fs: