From c4a7c1fb0156a6e707ec87e698eed640593a39c1 Mon Sep 17 00:00:00 2001 From: Nayan <83352306+nayan-rafiq@users.noreply.github.com> Date: Mon, 6 Sep 2021 16:17:02 +0600 Subject: [PATCH] feat: add last edit information to application (#6948) Adds the last edit time and editor username to the application when there is a change in the application. --- .../appsmith/server/domains/Application.java | 12 +++++++++++ .../BaseAppsmithRepositoryImpl.java | 3 +++ .../CustomApplicationRepositoryImpl.java | 1 - .../services/ApplicationPageServiceImpl.java | 6 +++++- .../server/services/ApplicationService.java | 2 ++ .../services/ApplicationServiceImpl.java | 15 ++++++++++++++ .../services/LayoutActionServiceImpl.java | 20 +++++-------------- .../server/services/NewPageServiceImpl.java | 4 ++-- .../ImportExportApplicationService.java | 1 + .../services/ApplicationServiceTest.java | 18 +++++++++++++++++ 10 files changed, 63 insertions(+), 19 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java index 3c21dc78c9..ff1139fe4c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Application.java @@ -70,6 +70,18 @@ public class Application extends BaseDomain { @JsonProperty(access = JsonProperty.Access.READ_ONLY) Instant lastDeployedAt; // when this application was last deployed + /** + * This method has been added because the updatedAt property in base domain has @JsonIgnore annotation + * @return updated time as a string + */ + @JsonProperty(value = "modifiedAt", access = JsonProperty.Access.READ_ONLY) + public String getLastUpdateTime() { + if(updatedAt != null) { + return ISO_FORMATTER.format(updatedAt); + } + return null; + } + public String getLastDeployedAt() { if(lastDeployedAt != null) { return ISO_FORMATTER.format(lastDeployedAt); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/BaseAppsmithRepositoryImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/BaseAppsmithRepositoryImpl.java index a8b3fbb93d..4c0c7c1908 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/BaseAppsmithRepositoryImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/BaseAppsmithRepositoryImpl.java @@ -25,6 +25,7 @@ import org.springframework.security.core.context.ReactiveSecurityContextHolder; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.time.Instant; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -122,6 +123,8 @@ public abstract class BaseAppsmithRepositoryImpl { // Set policies to null in the update object resource.setPolicies(null); + resource.setUpdatedAt(Instant.now()); + resource.setModifiedBy(user.getUsername()); DBObject update = getDbObject(resource); Update updateObj = new Update(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java index f3b25f2223..8a32814565 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomApplicationRepositoryImpl.java @@ -1,7 +1,6 @@ package com.appsmith.server.repositories; import com.appsmith.server.acl.AclPermission; -import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.ApplicationPage; import com.appsmith.server.domains.QApplication; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java index 227fde79db..0b7ba86904 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java @@ -108,6 +108,7 @@ public class ApplicationPageServiceImpl implements ApplicationPageService { final PageDTO savedPage = tuple.getT1(); final Application application = tuple.getT2(); return addPageToApplication(application, savedPage, false) + .then(applicationService.saveLastEditInformation(application.getId())) .thenReturn(savedPage); }); } @@ -309,7 +310,10 @@ public class ApplicationPageServiceImpl implements ApplicationPageService { return newPageService.findById(pageId, MANAGE_PAGES) .switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.ACTION_IS_NOT_AUTHORIZED, "Clone Page"))) - .flatMap(page -> clonePageGivenApplicationId(pageId, page.getApplicationId(), " Copy")); + .flatMap(page -> + applicationService.saveLastEditInformation(page.getApplicationId()) + .then(clonePageGivenApplicationId(pageId, page.getApplicationId(), " Copy")) + ); } private Mono clonePageGivenApplicationId(String pageId, String applicationId, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java index f182a2a7b1..0a24a8d5c5 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java @@ -31,4 +31,6 @@ public interface ApplicationService extends CrudService { Flux findAllApplicationsByOrganizationId(String organizationId); Mono getApplicationInViewMode(String applicationId); + + Mono saveLastEditInformation(String applicationId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java index 0850102d1d..8e31139538 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java @@ -35,6 +35,7 @@ import java.util.Set; import static com.appsmith.server.acl.AclPermission.EXECUTE_DATASOURCES; import static com.appsmith.server.acl.AclPermission.MAKE_PUBLIC_APPLICATIONS; +import static com.appsmith.server.acl.AclPermission.MANAGE_APPLICATIONS; import static com.appsmith.server.acl.AclPermission.READ_APPLICATIONS; @@ -301,4 +302,18 @@ public class ApplicationServiceImpl extends BaseService saveLastEditInformation(String applicationId) { + Application application = new Application(); + /* + We're not setting updatedAt and modifiedBy fields to the application DTO because these fields will be set + by the updateById method of the BaseAppsmithRepositoryImpl + */ + return repository.updateById(applicationId, application, MANAGE_APPLICATIONS); // it'll do a set operation + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/LayoutActionServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/LayoutActionServiceImpl.java index d3275cf406..d101f9a26a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/LayoutActionServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/LayoutActionServiceImpl.java @@ -26,6 +26,7 @@ import com.appsmith.server.helpers.WidgetSpecificUtils; import com.appsmith.server.solutions.PageLoadActionsUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; @@ -56,6 +57,7 @@ import static java.util.stream.Collectors.toSet; @Service @Slf4j +@RequiredArgsConstructor public class LayoutActionServiceImpl implements LayoutActionService { private final ObjectMapper objectMapper; @@ -64,6 +66,7 @@ public class LayoutActionServiceImpl implements LayoutActionService { private final NewActionService newActionService; private final PageLoadActionsUtil pageLoadActionsUtil; private final SessionUserService sessionUserService; + private final ApplicationService applicationService; private JSONParser jsonParser = new JSONParser(JSONParser.MODE_PERMISSIVE); @@ -75,20 +78,6 @@ public class LayoutActionServiceImpl implements LayoutActionService { private final String preWord = "\\b("; private final String postWord = ")\\b"; - public LayoutActionServiceImpl(ObjectMapper objectMapper, - AnalyticsService analyticsService, - NewPageService newPageService, - NewActionService newActionService, - PageLoadActionsUtil pageLoadActionsUtil, - SessionUserService sessionUserService) { - this.objectMapper = objectMapper; - this.analyticsService = analyticsService; - this.newPageService = newPageService; - this.newActionService = newActionService; - this.pageLoadActionsUtil = pageLoadActionsUtil; - this.sessionUserService = sessionUserService; - } - @Override public Mono moveAction(ActionMoveDTO actionMoveDTO) { ActionDTO action = actionMoveDTO.getAction(); @@ -676,7 +665,8 @@ public class LayoutActionServiceImpl implements LayoutActionService { } } page.setLayouts(layoutList); - return newPageService.saveUnpublishedPage(page); + return applicationService.saveLastEditInformation(page.getApplicationId()) + .then(newPageService.saveUnpublishedPage(page)); }) .flatMap(page -> { List layoutList = page.getLayouts(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/NewPageServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/NewPageServiceImpl.java index fccdbd9806..8f14762dd4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/NewPageServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/NewPageServiceImpl.java @@ -4,7 +4,6 @@ import com.appsmith.server.acl.AclPermission; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.ApplicationPage; -import com.appsmith.server.domains.Collection; import com.appsmith.server.domains.Layout; import com.appsmith.server.domains.NewPage; import com.appsmith.server.dtos.ApplicationPagesDTO; @@ -381,7 +380,8 @@ public class NewPageServiceImpl extends BaseService getPageByViewMode(savedPage, false)); + .flatMap(savedPage -> applicationService.saveLastEditInformation(savedPage.getApplicationId()) + .then(getPageByViewMode(savedPage, false))); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ImportExportApplicationService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ImportExportApplicationService.java index 7c37900057..f84555f104 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ImportExportApplicationService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ImportExportApplicationService.java @@ -148,6 +148,7 @@ public class ImportExportApplicationService { final String organizationId = application.getOrganizationId(); application.setOrganizationId(null); application.setPages(null); + application.setModifiedBy(null); examplesOrganizationCloner.makePristine(application); applicationJson.setExportedApplication(application); return newPageRepository.findByApplicationId(applicationId, AclPermission.MANAGE_PAGES) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationServiceTest.java index 32422f8bf9..91c98c69a5 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationServiceTest.java @@ -1238,4 +1238,22 @@ public class ApplicationServiceTest { .verifyComplete(); } + + @WithUserDetails("api_user") + @Test + public void saveLastEditInformation_WhenUserHasPermission_Updated() { + Application testApplication = new Application(); + testApplication.setName("SaveLastEditInformation TestApp"); + testApplication.setModifiedBy("test-user"); + + Mono updatedApplication = applicationPageService.createApplication(testApplication, orgId) + .flatMap(application -> + applicationService.saveLastEditInformation(application.getId()) + ); + StepVerifier.create(updatedApplication).assertNext(application -> { + assertThat(application.getLastUpdateTime()).isNotNull(); + assertThat(application.getPolicies()).isNotNull().isNotEmpty(); + assertThat(application.getModifiedBy()).isEqualTo("api_user"); + }).verifyComplete(); + } }