chore: Converging git refactor changes (#33971)

Co-authored-by: sondermanish <sonder.manish@gmail.com>
This commit is contained in:
Nidhi 2024-06-04 22:31:39 +05:30 committed by GitHub
parent 05690f8339
commit 9dc9149c66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 1170 additions and 5119 deletions

View File

@ -301,10 +301,10 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
GitArtifactMetadata gitData = application.getGitApplicationMetadata();
if (gitData != null
&& !StringUtils.isEmpty(gitData.getBranchName())
&& !StringUtils.isEmpty(gitData.getDefaultApplicationId())) {
&& !StringUtils.isEmpty(gitData.getDefaultArtifactId())) {
applicationIdMono = this.findByBranchNameAndDefaultApplicationId(
gitData.getBranchName(),
gitData.getDefaultApplicationId(),
gitData.getDefaultArtifactId(),
applicationPermission.getEditPermission())
.map(Application::getId);
} else {
@ -690,8 +690,8 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
// Check if the current application is the root application
if (gitData != null
&& !StringUtils.isEmpty(gitData.getDefaultApplicationId())
&& applicationId.equals(gitData.getDefaultApplicationId())) {
&& !StringUtils.isEmpty(gitData.getDefaultArtifactId())
&& applicationId.equals(gitData.getDefaultArtifactId())) {
// This is the root application with update SSH key request
gitAuth.setRegeneratedKey(true);
gitData.setGitAuth(gitAuth);
@ -707,7 +707,7 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
// Children application with update SSH key request for root application
// Fetch root application and then make updates. We are storing the git metadata only in root
// application
if (StringUtils.isEmpty(gitData.getDefaultApplicationId())) {
if (StringUtils.isEmpty(gitData.getDefaultArtifactId())) {
throw new AppsmithException(
AppsmithError.INVALID_GIT_CONFIGURATION,
"Unable to find root application, please connect your application to remote repo to resolve this issue.");
@ -715,7 +715,7 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
gitAuth.setRegeneratedKey(true);
return repository
.findById(gitData.getDefaultApplicationId(), applicationPermission.getEditPermission())
.findById(gitData.getDefaultArtifactId(), applicationPermission.getEditPermission())
.flatMap(defaultApplication -> {
GitArtifactMetadata gitArtifactMetadata =
defaultApplication.getGitApplicationMetadata();
@ -770,7 +770,7 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
"Can't find valid SSH key. Please configure the application with git"));
}
// Check if the application is root application
if (applicationId.equals(gitData.getDefaultApplicationId())) {
if (applicationId.equals(gitData.getDefaultArtifactId())) {
gitData.getGitAuth().setDocUrl(Assets.GIT_DEPLOY_KEY_DOC_URL);
GitAuthDTO gitAuthDTO = new GitAuthDTO();
gitAuthDTO.setPublicKey(gitData.getGitAuth().getPublicKey());
@ -779,14 +779,14 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
gitAuthDTO.setGitSupportedSSHKeyType(gitDeployKeyDTOList);
return Mono.just(gitAuthDTO);
}
if (gitData.getDefaultApplicationId() == null) {
if (gitData.getDefaultArtifactId() == null) {
throw new AppsmithException(
AppsmithError.INVALID_GIT_CONFIGURATION,
"Can't find root application. Please configure the application with git");
}
return repository
.findById(gitData.getDefaultApplicationId(), applicationPermission.getEditPermission())
.findById(gitData.getDefaultArtifactId(), applicationPermission.getEditPermission())
.map(rootApplication -> {
GitAuthDTO gitAuthDTO = new GitAuthDTO();
GitAuth gitAuth = rootApplication

View File

@ -11,6 +11,8 @@ import com.appsmith.server.domains.Artifact;
import com.appsmith.server.domains.GitArtifactMetadata;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.ArtifactExchangeJson;
import com.appsmith.server.dtos.GitAuthDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
@ -47,7 +49,7 @@ import static com.appsmith.server.helpers.DefaultResourcesUtils.createDefaultIds
@RequiredArgsConstructor
public class GitApplicationHelperCEImpl implements GitArtifactHelperCE<Application> {
private final CommonGitFileUtils gitFileUtils;
private final CommonGitFileUtils commonGitFileUtils;
private final GitPrivateRepoHelper gitPrivateRepoHelper;
private final ApplicationService applicationService;
@ -178,9 +180,9 @@ public class GitApplicationHelperCEImpl implements GitArtifactHelperCE<Applicati
}
@Override
public Mono<Application> publishArtifact(Artifact artifact) {
public Mono<Application> publishArtifact(Artifact artifact, Boolean isPublishedManually) {
Application application = (Application) artifact;
return applicationPageService.publish(application.getId(), true).then(Mono.just(application));
return applicationPageService.publish(application.getId(), isPublishedManually);
}
// TODO: scope for improvement
@ -204,7 +206,7 @@ public class GitApplicationHelperCEImpl implements GitArtifactHelperCE<Applicati
String editModeUrl = Paths.get(viewModeUrl, "edit").toString();
// Initialize the repo with readme file
return gitFileUtils
return commonGitFileUtils
.initializeReadme(readMePath, originHeader + viewModeUrl, originHeader + editModeUrl)
.onErrorMap(throwable -> {
log.error("Error while initialising git repo, {0}", throwable);
@ -305,4 +307,23 @@ public class GitApplicationHelperCEImpl implements GitArtifactHelperCE<Applicati
public Application updateArtifactWithDefaultReponseUtils(Artifact artifact) {
return responseUtils.updateApplicationWithDefaultResources((Application) artifact);
}
@Override
public Mono<Application> createArtifactForImport(String workspaceId, String repoName) {
Application newApplication = new Application();
newApplication.setName(repoName);
newApplication.setWorkspaceId(workspaceId);
newApplication.setGitApplicationMetadata(new GitArtifactMetadata());
return applicationPageService.createOrUpdateSuffixedApplication(newApplication, newApplication.getName(), 0);
}
@Override
public Mono<Application> deleteArtifact(String artifactId) {
return applicationPageService.deleteApplication(artifactId);
}
@Override
public Boolean isContextInArtifactEmpty(ArtifactExchangeJson artifactExchangeJson) {
return CollectionUtils.isNullOrEmpty(((ApplicationJson) artifactExchangeJson).getPageList());
}
}

View File

@ -436,7 +436,7 @@ public class ApplicationImportServiceCEImpl
Mono<Application> parentApplicationMono;
if (application.getGitApplicationMetadata() != null) {
parentApplicationMono = applicationService.findById(
application.getGitApplicationMetadata().getDefaultApplicationId());
application.getGitApplicationMetadata().getDefaultArtifactId());
} else {
parentApplicationMono = Mono.just(application);
}

View File

@ -2,7 +2,7 @@ package com.appsmith.server.controllers;
import com.appsmith.server.constants.Url;
import com.appsmith.server.controllers.ce.GitControllerCE;
import com.appsmith.server.services.GitService;
import com.appsmith.server.git.common.CommonGitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping(Url.GIT_URL)
public class GitController extends GitControllerCE {
public GitController(GitService service) {
public GitController(CommonGitService service) {
super(service);
}
}

View File

@ -5,6 +5,7 @@ import com.appsmith.external.dtos.GitLogDTO;
import com.appsmith.external.dtos.GitStatusDTO;
import com.appsmith.external.dtos.MergeStatusDTO;
import com.appsmith.external.views.Views;
import com.appsmith.server.constants.ArtifactType;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.constants.Url;
import com.appsmith.server.domains.Application;
@ -21,14 +22,14 @@ import com.appsmith.server.dtos.GitDocsDTO;
import com.appsmith.server.dtos.GitMergeDTO;
import com.appsmith.server.dtos.GitPullDTO;
import com.appsmith.server.dtos.ResponseDTO;
import com.appsmith.server.git.common.CommonGitService;
import com.appsmith.server.helpers.GitDeployKeyGenerator;
import com.appsmith.server.services.GitService;
import com.fasterxml.jackson.annotation.JsonView;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.jgit.lib.BranchTrackingStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@ -48,14 +49,10 @@ import java.util.Map;
@Slf4j
@RequestMapping(Url.GIT_URL)
@RequiredArgsConstructor
public class GitControllerCE {
private final GitService service;
@Autowired
public GitControllerCE(GitService service) {
this.service = service;
}
private final CommonGitService service;
/**
* applicationId is the defaultApplicationId
@ -97,7 +94,7 @@ public class GitControllerCE {
@JsonView({Views.Metadata.class})
@GetMapping("/metadata/app/{defaultApplicationId}")
public Mono<ResponseDTO<GitArtifactMetadata>> getGitMetadata(@PathVariable String defaultApplicationId) {
return service.getGitApplicationMetadata(defaultApplicationId)
return service.getGitArtifactMetadata(defaultApplicationId, ArtifactType.APPLICATION)
.map(metadata -> new ResponseDTO<>(HttpStatus.OK.value(), metadata, null));
}
@ -107,7 +104,8 @@ public class GitControllerCE {
@PathVariable String defaultApplicationId,
@RequestBody GitConnectDTO gitConnectDTO,
@RequestHeader("Origin") String originHeader) {
return service.connectApplicationToGit(defaultApplicationId, gitConnectDTO, originHeader)
return service.connectArtifactToGit(defaultApplicationId, gitConnectDTO, originHeader, ArtifactType.APPLICATION)
.map(artefact -> (Application) artefact)
.map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null));
}
@ -120,7 +118,7 @@ public class GitControllerCE {
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName,
@RequestParam(required = false, defaultValue = "false") Boolean doAmend) {
log.debug("Going to commit application {}, branch : {}", defaultApplicationId, branchName);
return service.commitApplication(commitDTO, defaultApplicationId, branchName, doAmend)
return service.commitArtifact(commitDTO, defaultApplicationId, branchName, doAmend, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null));
}
@ -130,7 +128,7 @@ public class GitControllerCE {
@PathVariable String defaultApplicationId,
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug("Fetching commit-history for application {}, branch : {}", defaultApplicationId, branchName);
return service.getCommitHistory(defaultApplicationId, branchName)
return service.getCommitHistory(defaultApplicationId, branchName, ArtifactType.APPLICATION)
.map(logs -> new ResponseDTO<>(HttpStatus.OK.value(), logs, null));
}
@ -141,7 +139,7 @@ public class GitControllerCE {
@PathVariable String defaultApplicationId,
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug("Going to push application application {}, branch : {}", defaultApplicationId, branchName);
return service.pushApplication(defaultApplicationId, branchName)
return service.pushArtifact(defaultApplicationId, branchName, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null));
}
@ -153,7 +151,8 @@ public class GitControllerCE {
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String srcBranch,
@RequestBody GitBranchDTO branchDTO) {
log.debug("Going to create a branch from root application {}, srcBranch {}", defaultApplicationId, srcBranch);
return service.createBranch(defaultApplicationId, branchDTO, srcBranch)
return service.createBranch(defaultApplicationId, branchDTO, srcBranch, ArtifactType.APPLICATION)
.map(artefact -> (Application) artefact)
.map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null));
}
@ -163,7 +162,8 @@ public class GitControllerCE {
@PathVariable String defaultApplicationId,
@RequestParam(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug("Going to checkout to branch {} application {} ", branchName, defaultApplicationId);
return service.checkoutBranch(defaultApplicationId, branchName, true)
return service.checkoutBranch(defaultApplicationId, branchName, true, ArtifactType.APPLICATION)
.map(artefact -> (Application) artefact)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -171,7 +171,8 @@ public class GitControllerCE {
@PostMapping("/disconnect/app/{defaultApplicationId}")
public Mono<ResponseDTO<Application>> disconnectFromRemote(@PathVariable String defaultApplicationId) {
log.debug("Going to remove the remoteUrl for application {}", defaultApplicationId);
return service.detachRemote(defaultApplicationId)
return service.detachRemote(defaultApplicationId, ArtifactType.APPLICATION)
.map(artefact -> (Application) artefact)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -181,7 +182,7 @@ public class GitControllerCE {
@PathVariable String defaultApplicationId,
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug("Going to pull the latest for application {}, branch {}", defaultApplicationId, branchName);
return service.pullApplication(defaultApplicationId, branchName)
return service.pullArtifact(defaultApplicationId, branchName, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -192,7 +193,8 @@ public class GitControllerCE {
@RequestParam(required = false, defaultValue = "false") Boolean pruneBranches,
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug("Going to get branch list for application {}", defaultApplicationId);
return service.listBranchForApplication(defaultApplicationId, BooleanUtils.isTrue(pruneBranches), branchName)
return service.listBranchForArtifact(
defaultApplicationId, BooleanUtils.isTrue(pruneBranches), branchName, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -203,7 +205,7 @@ public class GitControllerCE {
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName,
@RequestParam(required = false, defaultValue = "true") Boolean compareRemote) {
log.debug("Going to get status for default application {}, branch {}", defaultApplicationId, branchName);
return service.getStatus(defaultApplicationId, compareRemote, branchName)
return service.getStatus(defaultApplicationId, compareRemote, branchName, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -214,7 +216,7 @@ public class GitControllerCE {
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug(
"Going to compare with remote for default application {}, branch {}", defaultApplicationId, branchName);
return service.fetchRemoteChanges(defaultApplicationId, branchName, true)
return service.fetchRemoteChanges(defaultApplicationId, branchName, true, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -227,7 +229,7 @@ public class GitControllerCE {
gitMergeDTO.getSourceBranch(),
gitMergeDTO.getDestinationBranch(),
defaultApplicationId);
return service.mergeBranch(defaultApplicationId, gitMergeDTO)
return service.mergeBranch(defaultApplicationId, gitMergeDTO, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -240,7 +242,7 @@ public class GitControllerCE {
gitMergeDTO.getSourceBranch(),
gitMergeDTO.getDestinationBranch(),
defaultApplicationId);
return service.isBranchMergeable(defaultApplicationId, gitMergeDTO)
return service.isBranchMergeable(defaultApplicationId, gitMergeDTO, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -249,7 +251,7 @@ public class GitControllerCE {
public Mono<ResponseDTO<String>> createConflictedBranch(
@PathVariable String defaultApplicationId, @RequestHeader(name = FieldName.BRANCH_NAME) String branchName) {
log.debug("Going to create conflicted state branch {} for application {}", branchName, defaultApplicationId);
return service.createConflictedBranch(defaultApplicationId, branchName)
return service.createConflictedBranch(defaultApplicationId, branchName, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>(HttpStatus.OK.value(), result, null));
}
@ -263,14 +265,15 @@ public class GitControllerCE {
@PostMapping("/import/{workspaceId}")
public Mono<ResponseDTO<ApplicationImportDTO>> importApplicationFromGit(
@PathVariable String workspaceId, @RequestBody GitConnectDTO gitConnectDTO) {
return service.importApplicationFromGit(workspaceId, gitConnectDTO)
return service.importArtifactFromGit(workspaceId, gitConnectDTO, ArtifactType.APPLICATION)
.map(artifactImportDTO -> (ApplicationImportDTO) artifactImportDTO)
.map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null));
}
@JsonView(Views.Public.class)
@GetMapping("/test-connection/app/{defaultApplicationId}")
public Mono<ResponseDTO<Boolean>> testGitConnection(@PathVariable String defaultApplicationId) {
return service.testConnection(defaultApplicationId)
return service.testConnection(defaultApplicationId, ArtifactType.APPLICATION)
.map(result -> new ResponseDTO<>((HttpStatus.OK.value()), result, null));
}
@ -279,7 +282,8 @@ public class GitControllerCE {
public Mono<ResponseDTO<Application>> deleteBranch(
@PathVariable String defaultApplicationId, @RequestParam String branchName) {
log.debug("Going to delete branch {} for defaultApplicationId {}", branchName, defaultApplicationId);
return service.deleteBranch(defaultApplicationId, branchName)
return service.deleteBranch(defaultApplicationId, branchName, ArtifactType.APPLICATION)
.map(artefact -> (Application) artefact)
.map(application -> new ResponseDTO<>(HttpStatus.OK.value(), application, null));
}
@ -291,7 +295,8 @@ public class GitControllerCE {
"Going to discard changes for branch {} with defaultApplicationId {}",
branchName,
defaultApplicationId);
return service.discardChanges(defaultApplicationId, branchName)
return service.discardChanges(defaultApplicationId, branchName, ArtifactType.APPLICATION)
.map(artefact -> (Application) artefact)
.map(result -> new ResponseDTO<>((HttpStatus.OK.value()), result, null));
}
@ -314,14 +319,15 @@ public class GitControllerCE {
public Mono<ResponseDTO<List<String>>> updateProtectedBranches(
@PathVariable String defaultApplicationId,
@RequestBody @Valid BranchProtectionRequestDTO branchProtectionRequestDTO) {
return service.updateProtectedBranches(defaultApplicationId, branchProtectionRequestDTO.getBranchNames())
return service.updateProtectedBranches(
defaultApplicationId, branchProtectionRequestDTO.getBranchNames(), ArtifactType.APPLICATION)
.map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null));
}
@JsonView(Views.Public.class)
@GetMapping("/branch/app/{defaultApplicationId}/protected")
public Mono<ResponseDTO<List<String>>> getProtectedBranches(@PathVariable String defaultApplicationId) {
return service.getProtectedBranches(defaultApplicationId)
return service.getProtectedBranches(defaultApplicationId, ArtifactType.APPLICATION)
.map(list -> new ResponseDTO<>(HttpStatus.OK.value(), list, null));
}
@ -329,21 +335,21 @@ public class GitControllerCE {
@PostMapping("/auto-commit/app/{defaultApplicationId}")
public Mono<ResponseDTO<Boolean>> autoCommit(
@PathVariable String defaultApplicationId, @RequestParam String branchName) {
return service.autoCommitApplication(defaultApplicationId, branchName)
return service.autoCommitApplication(defaultApplicationId, branchName, ArtifactType.APPLICATION)
.map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null));
}
@JsonView(Views.Public.class)
@GetMapping("/auto-commit/progress/app/{defaultApplicationId}")
public Mono<ResponseDTO<AutoCommitProgressDTO>> getAutoCommitProgress(@PathVariable String defaultApplicationId) {
return service.getAutoCommitProgress(defaultApplicationId)
return service.getAutoCommitProgress(defaultApplicationId, ArtifactType.APPLICATION)
.map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null));
}
@JsonView(Views.Public.class)
@PatchMapping("/auto-commit/toggle/app/{defaultApplicationId}")
public Mono<ResponseDTO<Boolean>> toggleAutoCommitEnabled(@PathVariable String defaultApplicationId) {
return service.toggleAutoCommitEnabled(defaultApplicationId)
return service.toggleAutoCommitEnabled(defaultApplicationId, ArtifactType.APPLICATION)
.map(data -> new ResponseDTO<>(HttpStatus.OK.value(), data, null));
}
}

View File

@ -489,6 +489,9 @@ public class Application extends BaseDomain implements Artifact {
dotted(gitApplicationMetadata, GitArtifactMetadata.Fields.gitAuth);
public static final String gitApplicationMetadata_defaultApplicationId =
dotted(gitApplicationMetadata, GitArtifactMetadata.Fields.defaultApplicationId);
public static final String gitApplicationMetadata_defaultArtifactId =
dotted(gitApplicationMetadata, GitArtifactMetadata.Fields.defaultArtifactId);
public static final String gitApplicationMetadata_isAutoDeploymentEnabled =
dotted(gitApplicationMetadata, GitArtifactMetadata.Fields.isAutoDeploymentEnabled);
public static final String gitApplicationMetadata_branchName =

View File

@ -3,4 +3,8 @@ package com.appsmith.server.domains;
public interface Context {
String getId();
String getArtifactId();
Layout getLayout();
}

View File

@ -107,8 +107,18 @@ public class GitArtifactMetadata implements AppsmithDomain {
@JsonView(Views.Public.class)
public String getDefaultArtifactId() {
if (StringUtils.hasText(defaultApplicationId)) {
return defaultApplicationId;
} else return defaultArtifactId;
if (StringUtils.hasText(defaultArtifactId)) {
return defaultArtifactId;
} else return defaultApplicationId;
}
// TODO : Set to private to prevent direct access unless migration is performed
private void setDefaultArtifactId(String defaultArtifactId) {
this.defaultArtifactId = defaultArtifactId;
}
public void setDefaultApplicationId(String defaultApplicationId) {
this.defaultApplicationId = defaultApplicationId;
this.defaultArtifactId = defaultApplicationId;
}
}

View File

@ -11,6 +11,8 @@ import lombok.Setter;
import lombok.experimental.FieldNameConstants;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@ -39,6 +41,19 @@ public class NewPage extends BranchAwareDomain implements Context {
super.sanitiseToExportDBObject();
}
@JsonView(Views.Internal.class)
@Override
public String getArtifactId() {
return this.applicationId;
}
@JsonView(Views.Internal.class)
@Override
public Layout getLayout() {
List<Layout> layouts = this.getUnpublishedPage().getLayouts();
return (layouts != null && !layouts.isEmpty()) ? layouts.get(0) : null;
}
public static class Fields extends BranchAwareDomain.Fields {
public static String unpublishedPage_layouts = unpublishedPage + "." + PageDTO.Fields.layouts;
public static String unpublishedPage_name = unpublishedPage + "." + PageDTO.Fields.name;

View File

@ -9,7 +9,7 @@ import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.dtos.ResponseDTO;
import com.appsmith.server.exceptions.util.DuplicateKeyExceptionUtils;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.SessionUserService;
@ -54,7 +54,7 @@ public class GlobalExceptionHandler {
private final AnalyticsService analyticsService;
private final GitFileUtils fileUtils;
private final CommonGitFileUtils commonGitFileUtils;
private final SessionUserService sessionUserService;
@ -351,7 +351,7 @@ public class GlobalExceptionHandler {
}
private Mono<Boolean> deleteLockFileAndSendAnalytics(File file, String urlPath) {
return fileUtils.deleteIndexLockFile(Path.of(file.getPath())).flatMap(fileTime -> {
return commonGitFileUtils.deleteIndexLockFile(Path.of(file.getPath())).flatMap(fileTime -> {
Map<String, Object> analyticsProps = new HashMap<>();
if (urlPath.contains("/git") && urlPath.contains("/app")) {
String appId = getAppIdFromUrlPath(urlPath);

View File

@ -16,7 +16,6 @@ import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.CollectionUtils;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.GitUtils;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.services.AnalyticsService;
@ -47,7 +46,6 @@ public class AutoCommitEventHandlerCEImpl implements AutoCommitEventHandlerCE {
private final GitRedisUtils gitRedisUtils;
private final RedisUtils redisUtils;
private final DSLMigrationUtils dslMigrationUtils;
private final GitFileUtils fileUtils;
private final CommonGitFileUtils commonGitFileUtils;
private final GitExecutor gitExecutor;
private final ProjectProperties projectProperties;
@ -106,7 +104,7 @@ public class AutoCommitEventHandlerCEImpl implements AutoCommitEventHandlerCE {
ApplicationJson applicationJson, AutoCommitEvent autoCommitEvent) {
// all the migrations are done, write to file system
try {
return fileUtils.saveApplicationToLocalRepo(
return commonGitFileUtils.saveArtifactToLocalRepo(
autoCommitEvent.getWorkspaceId(),
autoCommitEvent.getApplicationId(),
autoCommitEvent.getRepoName(),

View File

@ -4,7 +4,6 @@ import com.appsmith.external.git.GitExecutor;
import com.appsmith.server.configurations.ProjectProperties;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.services.AnalyticsService;
import org.springframework.context.ApplicationEventPublisher;
@ -18,7 +17,6 @@ public class AutoCommitEventHandlerImpl extends AutoCommitEventHandlerCEImpl imp
GitRedisUtils gitRedisUtils,
RedisUtils redisUtils,
DSLMigrationUtils dslMigrationUtils,
GitFileUtils fileUtils,
CommonGitFileUtils commonGitFileUtils,
GitExecutor gitExecutor,
ProjectProperties projectProperties,
@ -28,7 +26,6 @@ public class AutoCommitEventHandlerImpl extends AutoCommitEventHandlerCEImpl imp
gitRedisUtils,
redisUtils,
dslMigrationUtils,
fileUtils,
commonGitFileUtils,
gitExecutor,
projectProperties,

View File

@ -10,10 +10,10 @@ import com.appsmith.server.dtos.AutoCommitProgressDTO;
import com.appsmith.server.dtos.AutoCommitTriggerDTO;
import com.appsmith.server.events.AutoCommitEvent;
import com.appsmith.server.git.AutoCommitEventHandler;
import com.appsmith.server.git.common.CommonGitService;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.helpers.GitUtils;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.services.CommonGitService;
import com.appsmith.server.services.UserDataService;
import com.appsmith.server.solutions.ApplicationPermission;
import lombok.extern.slf4j.Slf4j;

View File

@ -0,0 +1,3 @@
package com.appsmith.server.git.common;
public interface CommonGitService extends CommonGitServiceCECompatible {}

View File

@ -1,4 +1,4 @@
package com.appsmith.server.services.ce;
package com.appsmith.server.git.common;
import com.appsmith.external.dtos.GitBranchDTO;
import com.appsmith.external.dtos.GitLogDTO;
@ -9,6 +9,7 @@ import com.appsmith.server.domains.Artifact;
import com.appsmith.server.domains.GitArtifactMetadata;
import com.appsmith.server.domains.GitAuth;
import com.appsmith.server.domains.GitProfile;
import com.appsmith.server.dtos.ArtifactImportDTO;
import com.appsmith.server.dtos.AutoCommitProgressDTO;
import com.appsmith.server.dtos.GitCommitDTO;
import com.appsmith.server.dtos.GitConnectDTO;
@ -107,4 +108,7 @@ public interface CommonGitServiceCE {
Mono<AutoCommitProgressDTO> getAutoCommitProgress(String applicationId, ArtifactType artifactType);
Mono<Boolean> autoCommitApplication(String defaultApplicationId, String branchName, ArtifactType artifactType);
Mono<? extends ArtifactImportDTO> importArtifactFromGit(
String workspaceId, GitConnectDTO gitConnectDTO, ArtifactType artifactType);
}

View File

@ -0,0 +1,3 @@
package com.appsmith.server.git.common;
public interface CommonGitServiceCECompatible extends CommonGitServiceCE {}

View File

@ -1,7 +1,8 @@
package com.appsmith.server.services.ce_compatible;
package com.appsmith.server.git.common;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.server.configurations.EmailConfig;
import com.appsmith.server.datasources.base.DatasourceService;
import com.appsmith.server.domains.Application;
import com.appsmith.server.exports.internal.ExportService;
import com.appsmith.server.git.GitRedisUtils;
@ -9,13 +10,15 @@ import com.appsmith.server.git.autocommit.helpers.GitAutoCommitHelper;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.plugins.base.PluginService;
import com.appsmith.server.repositories.GitDeployKeysRepository;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.GitArtifactHelper;
import com.appsmith.server.services.SessionUserService;
import com.appsmith.server.services.UserDataService;
import com.appsmith.server.services.UserService;
import com.appsmith.server.services.ce.CommonGitServiceCEImpl;
import com.appsmith.server.services.WorkspaceService;
import com.appsmith.server.solutions.DatasourcePermission;
import io.micrometer.observation.ObservationRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -37,6 +40,10 @@ public class CommonGitServiceCECompatibleImpl extends CommonGitServiceCEImpl imp
TransactionalOperator transactionalOperator,
AnalyticsService analyticsService,
ObservationRegistry observationRegistry,
WorkspaceService workspaceService,
DatasourceService datasourceService,
DatasourcePermission datasourcePermission,
PluginService pluginService,
ExportService exportService,
ImportService importService,
GitExecutor gitExecutor,
@ -54,6 +61,10 @@ public class CommonGitServiceCECompatibleImpl extends CommonGitServiceCEImpl imp
transactionalOperator,
analyticsService,
observationRegistry,
workspaceService,
datasourceService,
datasourcePermission,
pluginService,
exportService,
importService,
gitExecutor,

View File

@ -1,4 +1,4 @@
package com.appsmith.server.services.ce;
package com.appsmith.server.git.common;
import com.appsmith.external.constants.AnalyticsEvents;
import com.appsmith.external.constants.ErrorReferenceDocUrl;
@ -10,12 +10,15 @@ import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.git.constants.GitConstants;
import com.appsmith.external.git.constants.GitConstants.GitCommandConstants;
import com.appsmith.external.git.constants.GitSpan;
import com.appsmith.external.models.Datasource;
import com.appsmith.external.models.DatasourceStorage;
import com.appsmith.server.acl.AclPermission;
import com.appsmith.server.configurations.EmailConfig;
import com.appsmith.server.constants.ArtifactType;
import com.appsmith.server.constants.Assets;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.constants.GitDefaultCommitMessage;
import com.appsmith.server.datasources.base.DatasourceService;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.ApplicationMode;
import com.appsmith.server.domains.Artifact;
@ -24,9 +27,13 @@ import com.appsmith.server.domains.GitArtifactMetadata;
import com.appsmith.server.domains.GitAuth;
import com.appsmith.server.domains.GitDeployKeys;
import com.appsmith.server.domains.GitProfile;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.User;
import com.appsmith.server.domains.UserData;
import com.appsmith.server.domains.Workspace;
import com.appsmith.server.dtos.ApplicationImportDTO;
import com.appsmith.server.dtos.ArtifactExchangeJson;
import com.appsmith.server.dtos.ArtifactImportDTO;
import com.appsmith.server.dtos.AutoCommitProgressDTO;
import com.appsmith.server.dtos.GitCommitDTO;
import com.appsmith.server.dtos.GitConnectDTO;
@ -44,12 +51,15 @@ import com.appsmith.server.helpers.GitDeployKeyGenerator;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.helpers.GitUtils;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.plugins.base.PluginService;
import com.appsmith.server.repositories.GitDeployKeysRepository;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.GitArtifactHelper;
import com.appsmith.server.services.SessionUserService;
import com.appsmith.server.services.UserDataService;
import com.appsmith.server.services.UserService;
import com.appsmith.server.services.WorkspaceService;
import com.appsmith.server.solutions.DatasourcePermission;
import io.micrometer.observation.ObservationRegistry;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@ -95,6 +105,7 @@ import static com.appsmith.external.git.constants.ce.GitConstantsCE.MERGE_CONFLI
import static com.appsmith.external.git.constants.ce.GitSpanCE.OPS_COMMIT;
import static com.appsmith.external.git.constants.ce.GitSpanCE.OPS_STATUS;
import static com.appsmith.git.constants.AppsmithBotAsset.APPSMITH_BOT_USERNAME;
import static com.appsmith.server.constants.ArtifactType.APPLICATION;
import static com.appsmith.server.constants.SerialiseArtifactObjective.VERSION_CONTROL;
import static com.appsmith.server.constants.ce.FieldNameCE.DEFAULT;
import static java.lang.Boolean.FALSE;
@ -120,6 +131,11 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
protected final AnalyticsService analyticsService;
private final ObservationRegistry observationRegistry;
private final WorkspaceService workspaceService;
private final DatasourceService datasourceService;
private final DatasourcePermission datasourcePermission;
private final PluginService pluginService;
private final ExportService exportService;
private final ImportService importService;
@ -899,7 +915,12 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
.switchIfEmpty(
Mono.error(new AppsmithException(AppsmithError.INVALID_GIT_CONFIGURATION, GIT_PROFILE_ERROR)));
final String browserSupportedUrl = GitUtils.convertSshUrlToBrowserSupportedUrl(gitConnectDTO.getRemoteUrl());
String browserSupportedUrl;
try {
browserSupportedUrl = GitUtils.convertSshUrlToBrowserSupportedUrl(gitConnectDTO.getRemoteUrl());
} catch (AppsmithException error) {
return Mono.error(error);
}
Mono<Boolean> isPrivateRepoMono =
GitUtils.isRepoPrivate(browserSupportedUrl).cache();
@ -1017,7 +1038,7 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
new AppsmithException(AppsmithError.INVALID_GIT_REPO)));
} else {
GitArtifactMetadata gitArtifactMetadata = artifact.getGitArtifactMetadata();
gitArtifactMetadata.setDefaultArtifactId(artifactId);
gitArtifactMetadata.setDefaultApplicationId(artifactId);
gitArtifactMetadata.setBranchName(defaultBranch);
gitArtifactMetadata.setDefaultBranchName(defaultBranch);
gitArtifactMetadata.setRemoteUrl(gitConnectDTO.getRemoteUrl());
@ -1167,7 +1188,7 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
/**
* @param commitDTO information required for making a commit
* @param defaultArtifactId application branch on which the commit needs to be done
* @param defaultArtifactId application branch on which the commit needs to be done
* @param branchName branch name for the commit flow
* @param doAmend if we want to amend the commit with the earlier one, used in connect flow
* @param isFileLock boolean value indicates whether the file lock is needed to complete the operation
@ -1233,7 +1254,6 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
// Check if the repo is public for current artifact and if the user have changed the access after
// the connection
final String workspaceId = defaultArtifact.getWorkspaceId();
return GitUtils.isRepoPrivate(defaultGitMetadata.getBrowserSupportedRemoteUrl())
.flatMap(isPrivate -> {
// Check the repo limit if the visibility status is updated, or it is private
@ -1252,9 +1272,9 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
gitArtifactHelper.isPrivateRepoLimitReached(savedArtifact, false));
});
})
.then(gitArtifactHelper.getArtifactByDefaultIdAndBranchName(
.flatMap(artifact -> gitArtifactHelper.getArtifactByDefaultIdAndBranchName(
defaultArtifactId, branchName, artifactEditPermission))
.flatMap((branchedArtifact) -> {
.flatMap(branchedArtifact -> {
GitArtifactMetadata gitArtifactMetadata = branchedArtifact.getGitArtifactMetadata();
if (gitArtifactMetadata == null) {
return Mono.error(
@ -1286,14 +1306,8 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
GitArtifactMetadata gitData = branchedArtifact.getGitArtifactMetadata();
Path baseRepoSuffix = gitArtifactHelper.getRepoSuffixPath(
branchedArtifact.getWorkspaceId(), gitData.getDefaultArtifactId(), gitData.getRepoName());
Mono<Path> repoPathMono;
try {
repoPathMono = commonGitFileUtils.saveArtifactToLocalRepoWithAnalytics(
baseRepoSuffix, artifactExchangeJson, gitData.getBranchName());
} catch (IOException | GitAPIException e) {
return Mono.error(e);
}
Mono<Path> repoPathMono = commonGitFileUtils.saveArtifactToLocalRepoWithAnalytics(
baseRepoSuffix, artifactExchangeJson, gitData.getBranchName());
gitData.setLastCommittedAt(Instant.now());
// We don't require to check for permission from this point because, permission is already
@ -1355,7 +1369,7 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
.then(Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED, "commit", error.getMessage())));
});
return Mono.zip(gitCommitMono, Mono.just(branchedArtifact));
return Mono.zip(gitCommitMono, gitArtifactHelper.getArtifactById(branchedArtifact.getId(), null));
})
.flatMap(tuple -> {
String commitStatus = tuple.getT1();
@ -1499,14 +1513,14 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
.checkoutToBranch(
baseRepoSuffix,
artifact.getGitArtifactMetadata().getBranchName())
.then(gitExecutor
.then(Mono.defer(() -> gitExecutor
.pushApplication(
baseRepoSuffix,
gitData.getRemoteUrl(),
gitAuth.getPublicKey(),
gitAuth.getPrivateKey(),
gitData.getBranchName())
.zipWith(Mono.just(artifact)))
.zipWith(Mono.just(artifact))))
.onErrorResume(error -> addAnalyticsForGitOperation(
AnalyticsEvents.GIT_PUSH,
artifact,
@ -1559,7 +1573,7 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
}
GitArtifactHelper<?> gitArtifactHelper = getArtifactGitService(artifact.getArtifactType());
return gitArtifactHelper.publishArtifact(artifact);
return gitArtifactHelper.publishArtifact(artifact, true);
}
/**
@ -1612,8 +1626,8 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
GitArtifactHelper<?> gitArtifactHelper = getArtifactGitService(artifactType);
AclPermission artifactEditPermission = gitArtifactHelper.getArtifactEditPermission();
Mono<? extends Artifact> sourceArtifactMono = gitArtifactHelper.getArtifactByDefaultIdAndBranchName(
defaultArtifactId, branchName, artifactEditPermission);
Mono<? extends Artifact> sourceArtifactMono =
gitArtifactHelper.getArtifactById(defaultArtifactId, artifactEditPermission);
return sourceArtifactMono.flatMap(sourceArtifact -> checkoutBranch(sourceArtifact, branchName, addFileLock));
}
@ -1689,11 +1703,8 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
Mono<? extends Artifact> defaultArtifactMono =
gitArtifactHelper.getArtifactById(defaultArtifactId, artifactEditPermission);
Mono<? extends Artifact> checkoutRemoteBranchMono = addFileLock(
defaultArtifactId, GitCommandConstants.CHECKOUT_BRANCH)
.zipWith(defaultArtifactMono)
.flatMap(tuple2 -> {
Artifact artifact = tuple2.getT2();
Mono<? extends Artifact> checkoutRemoteBranchMono = defaultArtifactMono
.flatMap(artifact -> {
GitArtifactMetadata gitArtifactMetadata = artifact.getGitArtifactMetadata();
String repoName = gitArtifactMetadata.getRepoName();
@ -1776,9 +1787,7 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
artifact1,
Boolean.TRUE.equals(
artifact1.getGitArtifactMetadata().getIsRepoPrivate())))
.map(gitArtifactHelper::updateArtifactWithDefaultReponseUtils)
.flatMap(artifact1 ->
releaseFileLock(defaultArtifactId).then(Mono.just(artifact1)));
.map(gitArtifactHelper::updateArtifactWithDefaultReponseUtils);
})
.tag(GitConstants.GitMetricConstants.CHECKOUT_REMOTE, TRUE.toString())
.name(GitSpan.OPS_CHECKOUT_BRANCH)
@ -1978,8 +1987,7 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
branchDTO.getBranchName())
.flatMap(newBranchArtifact -> {
// Commit and push for new branch created this is to avoid issues when user tries to
// create a
// new branch from uncommitted branch
// create a new branch from uncommitted branch
GitArtifactMetadata gitData = newBranchArtifact.getGitArtifactMetadata();
GitCommitDTO commitDTO = new GitCommitDTO();
commitDTO.setCommitMessage(DEFAULT_COMMIT_MESSAGE
@ -2957,16 +2965,11 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
branchedGitArtifactMetadata.getDefaultArtifactId(),
branchedGitArtifactMetadata.getRepoName());
try {
return Mono.zip(
commonGitFileUtils.saveArtifactToLocalRepoWithAnalytics(
repoSuffix, artifactExchangeJson, branchName),
Mono.just(branchedGitArtifactMetadata),
Mono.just(repoSuffix));
} catch (IOException | GitAPIException e) {
return Mono.error(
new AppsmithException(AppsmithError.GIT_ACTION_FAILED, "checkout", e.getMessage()));
}
return Mono.zip(
commonGitFileUtils.saveArtifactToLocalRepoWithAnalytics(
repoSuffix, artifactExchangeJson, branchName),
Mono.just(branchedGitArtifactMetadata),
Mono.just(repoSuffix));
})
.flatMap(tuple -> {
GitArtifactMetadata gitData = tuple.getT2();
@ -3489,4 +3492,281 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
return Flux.merge(eventSenderMonos).then();
}
@Override
public Mono<? extends ArtifactImportDTO> importArtifactFromGit(
String workspaceId, GitConnectDTO gitConnectDTO, ArtifactType artifactType) {
// 1. Check private repo limit for workspace
// 2. Create dummy application, clone repo from remote
// 3. Re-hydrate application to DB from local repo
// 1. Save the ssh keys in application object with other details
// 2. During import-export need to handle the DS(empty vs non-empty)
// 4. Return application
GitArtifactHelper<?> gitArtifactHelper = getArtifactGitService(artifactType);
if (StringUtils.isEmptyOrNull(gitConnectDTO.getRemoteUrl())) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "Remote Url"));
}
if (StringUtils.isEmptyOrNull(workspaceId)) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, "Invalid workspace id"));
}
Mono<Workspace> workspaceMono = workspaceService
.findById(workspaceId, AclPermission.WORKSPACE_CREATE_APPLICATION)
.switchIfEmpty(Mono.error(
new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId)));
final String repoName = GitUtils.getRepoName(gitConnectDTO.getRemoteUrl());
Mono<Boolean> isPrivateRepoMono = GitUtils.isRepoPrivate(
GitUtils.convertSshUrlToBrowserSupportedUrl(gitConnectDTO.getRemoteUrl()))
.cache();
Mono<? extends ArtifactImportDTO> importedArtifactMono = workspaceMono
.then(getSSHKeyForCurrentUser())
.zipWith(isPrivateRepoMono)
.switchIfEmpty(
Mono.error(
new AppsmithException(
AppsmithError.INVALID_GIT_CONFIGURATION,
"Unable to find git configuration for logged-in user. Please contact Appsmith team for support")))
// Check the limit for number of private repo
.flatMap(tuple -> {
// Check if the repo is public
GitAuth gitAuth = tuple.getT1();
boolean isRepoPrivate = tuple.getT2();
Mono<? extends Artifact> createArtifactMono = gitArtifactHelper
.createArtifactForImport(workspaceId, repoName)
.cache();
if (!isRepoPrivate) {
return Mono.just(gitAuth).zipWith(createArtifactMono);
}
return gitPrivateRepoHelper
.isRepoLimitReached(workspaceId, true)
.zipWith(createArtifactMono)
.flatMap(tuple2 -> {
Boolean isRepoLimitReached = tuple2.getT1();
Artifact createdArtifact = tuple2.getT2();
if (FALSE.equals(isRepoLimitReached)) {
return Mono.just(gitAuth).zipWith(createArtifactMono);
}
return addAnalyticsForGitOperation(
AnalyticsEvents.GIT_IMPORT,
createdArtifact,
AppsmithError.GIT_APPLICATION_LIMIT_ERROR.getErrorType(),
AppsmithError.GIT_APPLICATION_LIMIT_ERROR.getMessage(),
true)
.flatMap(user -> Mono.error(
new AppsmithException(AppsmithError.GIT_APPLICATION_LIMIT_ERROR)));
});
})
.flatMap(tuple -> {
GitAuth gitAuth = tuple.getT1();
Artifact artifact = tuple.getT2();
Path repoSuffix =
gitArtifactHelper.getRepoSuffixPath(artifact.getWorkspaceId(), artifact.getId(), repoName);
Mono<Map<String, GitProfile>> profileMono =
updateOrCreateGitProfileForCurrentUser(gitConnectDTO.getGitProfile(), artifact.getId());
Mono<String> defaultBranchMono = gitExecutor
.cloneRemoteIntoArtifactRepo(
repoSuffix,
gitConnectDTO.getRemoteUrl(),
gitAuth.getPrivateKey(),
gitAuth.getPublicKey())
.onErrorResume(error -> {
log.error("Error while cloning the remote repo, {}", error.getMessage());
return addAnalyticsForGitOperation(
AnalyticsEvents.GIT_IMPORT,
artifact,
error.getClass().getName(),
error.getMessage(),
false)
.flatMap(user -> commonGitFileUtils
.deleteLocalRepo(repoSuffix)
.then(gitArtifactHelper.deleteArtifact(artifact.getId())))
.flatMap(artifact1 -> {
if (error instanceof TransportException) {
return Mono.error(new AppsmithException(
AppsmithError.INVALID_GIT_SSH_CONFIGURATION));
} else if (error instanceof InvalidRemoteException) {
return Mono.error(new AppsmithException(
AppsmithError.INVALID_PARAMETER, "remote url"));
} else if (error instanceof TimeoutException) {
return Mono.error(
new AppsmithException(AppsmithError.GIT_EXECUTION_TIMEOUT));
}
return Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED, "clone", error));
});
});
return defaultBranchMono.zipWith(isPrivateRepoMono).flatMap(tuple2 -> {
String defaultBranch = tuple2.getT1();
boolean isRepoPrivate = tuple2.getT2();
GitArtifactMetadata gitArtifactMetadata = new GitArtifactMetadata();
gitArtifactMetadata.setGitAuth(gitAuth);
gitArtifactMetadata.setDefaultApplicationId(artifact.getId());
gitArtifactMetadata.setBranchName(defaultBranch);
gitArtifactMetadata.setDefaultBranchName(defaultBranch);
gitArtifactMetadata.setRemoteUrl(gitConnectDTO.getRemoteUrl());
gitArtifactMetadata.setRepoName(repoName);
gitArtifactMetadata.setBrowserSupportedRemoteUrl(
GitUtils.convertSshUrlToBrowserSupportedUrl(gitConnectDTO.getRemoteUrl()));
gitArtifactMetadata.setIsRepoPrivate(isRepoPrivate);
gitArtifactMetadata.setLastCommittedAt(Instant.now());
artifact.setGitArtifactMetadata(gitArtifactMetadata);
return Mono.just(artifact).zipWith(profileMono);
});
})
.flatMap(objects -> {
Artifact artifact = objects.getT1();
GitArtifactMetadata gitArtifactMetadata = artifact.getGitArtifactMetadata();
String defaultBranch = gitArtifactMetadata.getDefaultBranchName();
Mono<List<Datasource>> datasourceMono = datasourceService
.getAllByWorkspaceIdWithStorages(workspaceId, datasourcePermission.getEditPermission())
.collectList();
Mono<List<Plugin>> pluginMono =
pluginService.getDefaultPlugins().collectList();
Mono<? extends ArtifactExchangeJson> applicationJsonMono = commonGitFileUtils
.reconstructArtifactExchangeJsonFromGitRepoWithAnalytics(
workspaceId,
artifact.getId(),
gitArtifactMetadata.getRepoName(),
defaultBranch,
artifactType)
.onErrorResume(error -> {
log.error("Error while constructing artifact from git repo", error);
return deleteArtifactCreatedFromGitImport(
artifact.getId(),
artifact.getWorkspaceId(),
gitArtifactMetadata.getRepoName(),
artifactType)
.flatMap(application1 -> Mono.error(new AppsmithException(
AppsmithError.GIT_FILE_SYSTEM_ERROR, error.getMessage())));
});
return Mono.zip(applicationJsonMono, datasourceMono, pluginMono)
.flatMap(data -> {
ArtifactExchangeJson artifactExchangeJson = data.getT1();
List<Datasource> datasourceList = data.getT2();
List<Plugin> pluginList = data.getT3();
if (Optional.ofNullable(artifactExchangeJson.getArtifact())
.isEmpty()
|| gitArtifactHelper.isContextInArtifactEmpty(artifactExchangeJson)) {
return deleteArtifactCreatedFromGitImport(
artifact.getId(),
artifact.getWorkspaceId(),
gitArtifactMetadata.getRepoName(),
artifactType)
.then(Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED,
"import",
"Cannot import app from an empty repo")));
}
// If there is an existing datasource with the same name but a different type from that
// in the repo, the import api should fail
if (checkIsDatasourceNameConflict(
datasourceList, artifactExchangeJson.getDatasourceList(), pluginList)) {
return deleteArtifactCreatedFromGitImport(
artifact.getId(),
artifact.getWorkspaceId(),
gitArtifactMetadata.getRepoName(),
artifactType)
.then(Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED,
"import",
"Datasource already exists with the same name")));
}
artifactExchangeJson.getArtifact().setGitArtifactMetadata(gitArtifactMetadata);
return importService
.importArtifactInWorkspaceFromGit(
workspaceId, artifact.getId(), artifactExchangeJson, defaultBranch)
.onErrorResume(throwable -> deleteArtifactCreatedFromGitImport(
artifact.getId(),
artifact.getWorkspaceId(),
gitArtifactMetadata.getRepoName(),
artifactType)
.flatMap(application1 -> Mono.error(new AppsmithException(
AppsmithError.GIT_FILE_SYSTEM_ERROR, throwable.getMessage()))));
});
})
.flatMap(artifact -> gitArtifactHelper.publishArtifact(artifact, false))
// Add un-configured datasource to the list to response
.flatMap(artifact -> importService.getArtifactImportDTO(
artifact.getWorkspaceId(), artifact.getId(), artifact, APPLICATION))
.map(importableArtifactDTO -> (ApplicationImportDTO) importableArtifactDTO)
// Add analytics event
.flatMap(applicationImportDTO -> {
Application application = applicationImportDTO.getApplication();
return addAnalyticsForGitOperation(
AnalyticsEvents.GIT_IMPORT,
application,
application.getGitApplicationMetadata().getIsRepoPrivate())
.thenReturn(applicationImportDTO);
});
return Mono.create(
sink -> importedArtifactMono.subscribe(sink::success, sink::error, null, sink.currentContext()));
}
private Mono<GitAuth> getSSHKeyForCurrentUser() {
return sessionUserService
.getCurrentUser()
.flatMap(user -> gitDeployKeysRepository.findByEmail(user.getEmail()))
.map(GitDeployKeys::getGitAuth);
}
private Mono<? extends Artifact> deleteArtifactCreatedFromGitImport(
String artifactId, String workspaceId, String repoName, ArtifactType artifactType) {
GitArtifactHelper<?> gitArtifactHelper = getArtifactGitService(artifactType);
Path repoSuffix = Paths.get(workspaceId, artifactId, repoName);
return commonGitFileUtils.deleteLocalRepo(repoSuffix).then(gitArtifactHelper.deleteArtifact(artifactId));
}
private boolean checkIsDatasourceNameConflict(
List<Datasource> existingDatasources,
List<DatasourceStorage> importedDatasources,
List<Plugin> pluginList) {
// If we have an existing datasource with the same name but a different type from that in the repo, the import
// api should fail
for (DatasourceStorage datasourceStorage : importedDatasources) {
// Collect the datasource(existing in workspace) which has same as of imported datasource
// As names are unique we will need filter first element to check if the plugin id is matched
Datasource filteredDatasource = existingDatasources.stream()
.filter(datasource1 -> datasource1.getName().equals(datasourceStorage.getName()))
.findFirst()
.orElse(null);
// Check if both of the datasource's are of the same plugin type
if (filteredDatasource != null) {
long matchCount = pluginList.stream()
.filter(plugin -> {
final String pluginReference =
plugin.getPluginName() == null ? plugin.getPackageName() : plugin.getPluginName();
return plugin.getId().equals(filteredDatasource.getPluginId())
&& !datasourceStorage.getPluginId().equals(pluginReference);
})
.count();
if (matchCount > 0) {
return true;
}
}
}
return false;
}
}

View File

@ -1,8 +1,9 @@
package com.appsmith.server.services;
package com.appsmith.server.git.common;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.git.service.GitExecutorImpl;
import com.appsmith.server.configurations.EmailConfig;
import com.appsmith.server.datasources.base.DatasourceService;
import com.appsmith.server.domains.Application;
import com.appsmith.server.exports.internal.ExportService;
import com.appsmith.server.git.GitRedisUtils;
@ -10,8 +11,15 @@ import com.appsmith.server.git.autocommit.helpers.GitAutoCommitHelper;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.plugins.base.PluginService;
import com.appsmith.server.repositories.GitDeployKeysRepository;
import com.appsmith.server.services.ce_compatible.CommonGitServiceCECompatibleImpl;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.GitArtifactHelper;
import com.appsmith.server.services.SessionUserService;
import com.appsmith.server.services.UserDataService;
import com.appsmith.server.services.UserService;
import com.appsmith.server.services.WorkspaceService;
import com.appsmith.server.solutions.DatasourcePermission;
import io.micrometer.observation.ObservationRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Import;
@ -35,6 +43,10 @@ public class CommonGitServiceImpl extends CommonGitServiceCECompatibleImpl imple
TransactionalOperator transactionalOperator,
AnalyticsService analyticsService,
ObservationRegistry observationRegistry,
WorkspaceService workspaceService,
DatasourceService datasourceService,
DatasourcePermission datasourcePermission,
PluginService pluginService,
ExportService exportService,
ImportService importService,
GitExecutor gitExecutor,
@ -52,6 +64,10 @@ public class CommonGitServiceImpl extends CommonGitServiceCECompatibleImpl imple
transactionalOperator,
analyticsService,
observationRegistry,
workspaceService,
datasourceService,
datasourcePermission,
pluginService,
exportService,
importService,
gitExecutor,

View File

@ -6,7 +6,6 @@ import com.appsmith.server.applications.git.ApplicationGitFileUtilsImpl;
import com.appsmith.server.helpers.ce.CommonGitFileUtilsCE;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.SessionUserService;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
@ -20,8 +19,7 @@ public class CommonGitFileUtils extends CommonGitFileUtilsCE {
ApplicationGitFileUtilsImpl applicationGitFileUtils,
FileInterface fileUtils,
AnalyticsService analyticsService,
SessionUserService sessionUserService,
Gson gson) {
super(applicationGitFileUtils, fileUtils, analyticsService, sessionUserService, gson);
SessionUserService sessionUserService) {
super(applicationGitFileUtils, fileUtils, analyticsService, sessionUserService);
}
}

View File

@ -1,29 +0,0 @@
package com.appsmith.server.helpers;
import com.appsmith.external.git.FileInterface;
import com.appsmith.git.files.FileUtilsImpl;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.helpers.ce.GitFileUtilsCE;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.SessionUserService;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@Import({FileUtilsImpl.class})
public class GitFileUtils extends GitFileUtilsCE {
public GitFileUtils(
FileInterface fileUtils,
AnalyticsService analyticsService,
SessionUserService sessionUserService,
NewActionService newActionService,
ActionCollectionService actionCollectionService,
Gson gson) {
super(fileUtils, analyticsService, sessionUserService, newActionService, actionCollectionService, gson);
}
}

View File

@ -161,7 +161,7 @@ public class GitUtils {
public static boolean isApplicationConnectedToGit(Application application) {
GitArtifactMetadata metadata = application.getGitApplicationMetadata();
return metadata != null
&& !StringUtils.isEmptyOrNull(metadata.getDefaultApplicationId())
&& !StringUtils.isEmptyOrNull(metadata.getDefaultArtifactId())
&& !StringUtils.isEmptyOrNull(metadata.getRemoteUrl());
}

View File

@ -52,7 +52,6 @@ public class CommonGitFileUtilsCE {
private final FileInterface fileUtils;
private final AnalyticsService analyticsService;
private final SessionUserService sessionUserService;
private final Gson gson;
// Number of seconds after lock file is stale
@Value("${appsmith.index.lock.file.time}")
@ -93,8 +92,7 @@ public class CommonGitFileUtilsCE {
}
public Mono<Path> saveArtifactToLocalRepoWithAnalytics(
Path baseRepoSuffix, ArtifactExchangeJson artifactExchangeJson, String branchName)
throws IOException, GitAPIException {
Path baseRepoSuffix, ArtifactExchangeJson artifactExchangeJson, String branchName) {
/*
1. Checkout to branch

View File

@ -1,743 +0,0 @@
package com.appsmith.server.helpers.ce;
import com.appsmith.external.constants.AnalyticsEvents;
import com.appsmith.external.git.FileInterface;
import com.appsmith.external.helpers.Stopwatch;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.external.models.BaseDomain;
import com.appsmith.external.models.DatasourceStorage;
import com.appsmith.external.models.PluginType;
import com.appsmith.git.files.FileUtilsImpl;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.ApplicationPage;
import com.appsmith.server.domains.CustomJSLib;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
import com.appsmith.server.domains.Theme;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.CollectionUtils;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.SessionUserService;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;
import org.apache.commons.collections.PredicateUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import reactor.core.Exceptions;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.appsmith.external.git.constants.GitConstants.NAME_SEPARATOR;
import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNestedNonNullProperties;
import static com.appsmith.external.helpers.AppsmithBeanUtils.copyProperties;
import static com.appsmith.server.constants.FieldName.ACTION_COLLECTION_LIST;
import static com.appsmith.server.constants.FieldName.ACTION_LIST;
import static com.appsmith.server.constants.FieldName.CUSTOM_JS_LIB_LIST;
import static com.appsmith.server.constants.FieldName.DATASOURCE_LIST;
import static com.appsmith.server.constants.FieldName.DECRYPTED_FIELDS;
import static com.appsmith.server.constants.FieldName.EDIT_MODE_THEME;
import static com.appsmith.server.constants.FieldName.EXPORTED_APPLICATION;
import static com.appsmith.server.constants.FieldName.PAGE_LIST;
@Slf4j
@RequiredArgsConstructor
@Component
@Import({FileUtilsImpl.class})
public class GitFileUtilsCE {
private final FileInterface fileUtils;
private final AnalyticsService analyticsService;
private final SessionUserService sessionUserService;
private final NewActionService newActionService;
private final ActionCollectionService actionCollectionService;
private final Gson gson;
// Number of seconds after lock file is stale
@Value("${appsmith.index.lock.file.time}")
public final int INDEX_LOCK_FILE_STALE_TIME = 300;
// Only include the application helper fields in metadata object
protected Set<String> getBlockedMetadataFields() {
return Set.of(
EXPORTED_APPLICATION,
DATASOURCE_LIST,
PAGE_LIST,
ACTION_LIST,
ACTION_COLLECTION_LIST,
DECRYPTED_FIELDS,
EDIT_MODE_THEME,
CUSTOM_JS_LIB_LIST);
}
/**
* This method will save the complete application in the local repo directory.
* Path to repo will be : ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/{application_data}
*
* @param baseRepoSuffix path suffix used to create a local repo path
* @param applicationJson application reference object from which entire application can be rehydrated
* @param branchName name of the branch for the current application
* @return repo path where the application is stored
*/
public Mono<Path> saveApplicationToLocalRepo(
Path baseRepoSuffix, ApplicationJson applicationJson, String branchName)
throws IOException, GitAPIException {
/*
1. Checkout to branch
2. Create application reference for appsmith-git module
3. Save application to git repo
*/
ApplicationGitReference applicationReference = createApplicationReference(applicationJson);
// Save application to git repo
try {
return fileUtils.saveApplicationToGitRepo(baseRepoSuffix, applicationReference, branchName);
} catch (IOException | GitAPIException e) {
log.error("Error occurred while saving files to local git repo: ", e);
throw Exceptions.propagate(e);
}
}
public Mono<Path> saveApplicationToLocalRepoWithAnalytics(
Path baseRepoSuffix, ApplicationJson applicationJson, String branchName)
throws IOException, GitAPIException {
/*
1. Checkout to branch
2. Create application reference for appsmith-git module
3. Save application to git repo
*/
Stopwatch stopwatch = new Stopwatch(AnalyticsEvents.GIT_SERIALIZE_APP_RESOURCES_TO_LOCAL_FILE.getEventName());
// Save application to git repo
try {
Mono<Path> repoPathMono = saveApplicationToLocalRepo(baseRepoSuffix, applicationJson, branchName);
return Mono.zip(repoPathMono, sessionUserService.getCurrentUser()).flatMap(tuple -> {
stopwatch.stopTimer();
Path repoPath = tuple.getT1();
// Path to repo will be : ./container-volumes/git-repo/workspaceId/defaultApplicationId/repoName/
final Map<String, Object> data = Map.of(
FieldName.APPLICATION_ID,
repoPath.getParent().getFileName().toString(),
FieldName.ORGANIZATION_ID,
repoPath.getParent().getParent().getFileName().toString(),
FieldName.FLOW_NAME,
stopwatch.getFlow(),
"executionTime",
stopwatch.getExecutionTime());
return analyticsService
.sendEvent(
AnalyticsEvents.UNIT_EXECUTION_TIME.getEventName(),
tuple.getT2().getUsername(),
data)
.thenReturn(repoPath);
});
} catch (IOException | GitAPIException e) {
log.error("Error occurred while saving files to local git repo: ", e);
throw Exceptions.propagate(e);
}
}
public Mono<Path> saveApplicationToLocalRepo(
String workspaceId,
String defaultApplicationId,
String repoName,
ApplicationJson applicationJson,
String branchName)
throws GitAPIException, IOException {
Path baseRepoSuffix = Paths.get(workspaceId, defaultApplicationId, repoName);
return saveApplicationToLocalRepo(baseRepoSuffix, applicationJson, branchName);
}
/**
* Method to convert application resources to the structure which can be serialised by appsmith-git module for
* serialisation
*
* @param applicationJson application resource including actions, jsobjects, pages
* @return resource which can be saved to file system
*/
public ApplicationGitReference createApplicationReference(ApplicationJson applicationJson) {
ApplicationGitReference applicationReference = new ApplicationGitReference();
applicationReference.setModifiedResources(applicationJson.getModifiedResources());
setApplicationInApplicationReference(applicationJson, applicationReference);
setThemesInApplicationReference(applicationJson, applicationReference);
setApplicationMetadataInApplicationReference(applicationJson, applicationReference);
setNewPagesInApplicationReference(applicationJson, applicationReference);
setNewActionsInApplicationReference(applicationJson, applicationReference);
setActionCollectionsInApplicationReference(applicationJson, applicationReference);
setDatasourcesInApplicationReference(applicationJson, applicationReference);
setCustomJSLibsInApplicationReference(applicationJson, applicationReference);
return applicationReference;
}
private void setApplicationInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
Application application = applicationJson.getExportedApplication();
removeUnwantedFieldsFromApplication(application);
// Pass application reference
applicationReference.setApplication(applicationJson.getExportedApplication());
}
private void setApplicationMetadataInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
// Pass metadata
Iterable<String> keys = getAllFields(applicationJson)
.map(Field::getName)
.filter(name -> !getBlockedMetadataFields().contains(name))
.collect(Collectors.toList());
ApplicationJson applicationMetadata = new ApplicationJson();
applicationJson.setModifiedResources(null);
copyProperties(applicationJson, applicationMetadata, keys);
applicationReference.setMetadata(applicationMetadata);
}
private void setThemesInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
// No need to commit publish mode theme as it leads to conflict resolution at both the places if any
applicationJson.setPublishedTheme(null);
// Remove internal fields from the themes
removeUnwantedFieldsFromBaseDomain(applicationJson.getEditModeTheme());
applicationReference.setTheme(applicationJson.getEditModeTheme());
}
private void setCustomJSLibsInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
Map<String, Object> resourceMap = new HashMap<>();
applicationJson.getCustomJSLibList().forEach(jsLib -> {
removeUnwantedFieldsFromBaseDomain(jsLib);
resourceMap.put(jsLib.getUidString(), jsLib);
});
applicationReference.setJsLibraries(resourceMap);
}
private void setDatasourcesInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
Map<String, Object> resourceMap = new HashMap<>();
// Send datasources
applicationJson.getDatasourceList().forEach(datasource -> {
removeUnwantedFieldsFromDatasource(datasource);
resourceMap.put(datasource.getName(), datasource);
});
applicationReference.setDatasources(resourceMap);
}
private void setActionCollectionsInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
Map<String, Object> resourceMap = new HashMap<>();
Map<String, String> resourceMapActionCollectionBody = new HashMap<>();
// Insert JSOObjects and also assign the keys which later will be used for saving the resource in actual
// filepath
// JSObjectName_pageName => nomenclature for the keys
applicationJson.getActionCollectionList().stream()
// As we are expecting the commit will happen only after the application is published, so we can safely
// assume if the unpublished version is deleted entity should not be committed to git
.filter(collection -> collection.getUnpublishedCollection() != null
&& collection.getUnpublishedCollection().getDeletedAt() == null)
.peek(actionCollection ->
actionCollectionService.generateActionCollectionByViewMode(actionCollection, false))
.forEach(actionCollection -> {
String prefix = actionCollection.getUnpublishedCollection().getUserExecutableName()
+ NAME_SEPARATOR
+ actionCollection.getUnpublishedCollection().getPageId();
removeUnwantedFieldFromActionCollection(actionCollection);
String body = actionCollection.getUnpublishedCollection().getBody() != null
? actionCollection.getUnpublishedCollection().getBody()
: "";
actionCollection.getUnpublishedCollection().setBody(null);
resourceMapActionCollectionBody.put(prefix, body);
resourceMap.put(prefix, actionCollection);
});
applicationReference.setActionCollections(resourceMap);
applicationReference.setActionCollectionBody(resourceMapActionCollectionBody);
}
private void setNewPagesInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
// Insert only active pages which will then be committed to repo as individual file
Map<String, Object> resourceMap = new HashMap<>();
Map<String, String> dslBody = new HashMap<>();
applicationJson.getPageList().stream()
// As we are expecting the commit will happen only after the application is published, so we can safely
// assume if the unpublished version is deleted entity should not be committed to git
.filter(newPage -> newPage.getUnpublishedPage() != null
&& newPage.getUnpublishedPage().getDeletedAt() == null)
.forEach(newPage -> {
String pageName = newPage.getUnpublishedPage() != null
? newPage.getUnpublishedPage().getName()
: newPage.getPublishedPage().getName();
removeUnwantedFieldsFromPage(newPage);
JSONObject dsl =
newPage.getUnpublishedPage().getLayouts().get(0).getDsl();
// Get MainContainer widget data, remove the children and club with Canvas.json file
JSONObject mainContainer = new JSONObject(dsl);
mainContainer.remove("children");
newPage.getUnpublishedPage().getLayouts().get(0).setDsl(mainContainer);
// pageName will be used for naming the json file
dslBody.put(pageName, dsl.toString());
resourceMap.put(pageName, newPage);
});
applicationReference.setPages(resourceMap);
applicationReference.setPageDsl(dslBody);
}
private void setNewActionsInApplicationReference(
ApplicationJson applicationJson, ApplicationGitReference applicationReference) {
Map<String, Object> resourceMap = new HashMap<>();
Map<String, String> resourceMapBody = new HashMap<>();
// Insert active actions and also assign the keys which later will be used for saving the resource in actual
// filepath
// For actions, we are referring to validNames to maintain unique file names as just name
// field don't guarantee unique constraint for actions within JSObject
// queryValidName_pageName => nomenclature for the keys
applicationJson.getActionList().stream()
// As we are expecting the commit will happen only after the application is published, so we can safely
// assume if the unpublished version is deleted entity should not be committed to git
.filter(newAction -> newAction.getUnpublishedAction() != null
&& newAction.getUnpublishedAction().getDeletedAt() == null)
.peek(newAction -> newActionService.generateActionByViewMode(newAction, false))
.forEach(newAction -> {
String prefix;
if (newAction.getUnpublishedAction() != null) {
prefix = newAction.getUnpublishedAction().getUserExecutableName()
+ NAME_SEPARATOR
+ newAction.getUnpublishedAction().getPageId();
} else {
prefix = newAction.getPublishedAction().getUserExecutableName()
+ NAME_SEPARATOR
+ newAction.getPublishedAction().getPageId();
}
removeUnwantedFieldFromAction(newAction);
String body = newAction.getUnpublishedAction().getActionConfiguration() != null
&& newAction
.getUnpublishedAction()
.getActionConfiguration()
.getBody()
!= null
? newAction
.getUnpublishedAction()
.getActionConfiguration()
.getBody()
: "";
// This is a special case where we are handling REMOTE type plugins based actions such as Twilio
// The user configured values are stored in a attribute called formData which is a map unlike the
// body
if (PluginType.REMOTE.equals(newAction.getPluginType())
&& newAction.getUnpublishedAction().getActionConfiguration() != null
&& newAction
.getUnpublishedAction()
.getActionConfiguration()
.getFormData()
!= null) {
body = new Gson()
.toJson(
newAction
.getUnpublishedAction()
.getActionConfiguration()
.getFormData(),
Map.class);
newAction
.getUnpublishedAction()
.getActionConfiguration()
.setFormData(null);
}
// This is a special case where we are handling JS actions as we don't want to commit the body of JS
// actions
if (PluginType.JS.equals(newAction.getPluginType())) {
if (newAction.getUnpublishedAction().getActionConfiguration() != null) {
newAction
.getUnpublishedAction()
.getActionConfiguration()
.setBody(null);
newAction.getUnpublishedAction().setJsonPathKeys(null);
}
} else {
// For the regular actions we save the body field to git repo
resourceMapBody.put(prefix, body);
}
resourceMap.put(prefix, newAction);
});
applicationReference.setActions(resourceMap);
applicationReference.setActionBody(resourceMapBody);
}
protected Stream<Field> getAllFields(ApplicationJson applicationJson) {
Class<?> currentType = applicationJson.getClass();
Set<Class<?>> classes = new HashSet<>();
while (currentType != null) {
classes.add(currentType);
currentType = currentType.getSuperclass();
}
return classes.stream().flatMap(currentClass -> Arrays.stream(currentClass.getDeclaredFields()));
}
/**
* Method to reconstruct the application from the local git repo
*
* @param workspaceId To which workspace application needs to be rehydrated
* @param defaultApplicationId Root application for the current branched application
* @param branchName for which branch the application needs to rehydrate
* @return application reference from which entire application can be rehydrated
*/
public Mono<ApplicationJson> reconstructApplicationJsonFromGitRepoWithAnalytics(
String workspaceId, String defaultApplicationId, String repoName, String branchName) {
Stopwatch stopwatch = new Stopwatch(AnalyticsEvents.GIT_DESERIALIZE_APP_RESOURCES_FROM_FILE.getEventName());
return Mono.zip(
reconstructApplicationJsonFromGitRepo(workspaceId, defaultApplicationId, repoName, branchName),
sessionUserService.getCurrentUser())
.flatMap(tuple -> {
stopwatch.stopTimer();
final Map<String, Object> data = Map.of(
FieldName.APPLICATION_ID,
defaultApplicationId,
FieldName.ORGANIZATION_ID,
workspaceId,
FieldName.FLOW_NAME,
stopwatch.getFlow(),
"executionTime",
stopwatch.getExecutionTime());
return analyticsService
.sendEvent(
AnalyticsEvents.UNIT_EXECUTION_TIME.getEventName(),
tuple.getT2().getUsername(),
data)
.thenReturn(tuple.getT1());
});
}
public Mono<ApplicationJson> reconstructApplicationJsonFromGitRepo(
String workspaceId, String defaultApplicationId, String repoName, String branchName) {
Mono<ApplicationGitReference> appReferenceMono = fileUtils.reconstructApplicationReferenceFromGitRepo(
workspaceId, defaultApplicationId, repoName, branchName);
return appReferenceMono.map(applicationReference -> {
// Extract application metadata from the json
ApplicationJson metadata =
getApplicationResource(applicationReference.getMetadata(), ApplicationJson.class);
ApplicationJson applicationJson = getApplicationJsonFromGitReference(applicationReference);
copyNestedNonNullProperties(metadata, applicationJson);
return applicationJson;
});
}
protected <T> List<T> getApplicationResource(Map<String, Object> resources, Type type) {
List<T> deserializedResources = new ArrayList<>();
if (!CollectionUtils.isNullOrEmpty(resources)) {
for (Map.Entry<String, Object> resource : resources.entrySet()) {
deserializedResources.add(getApplicationResource(resource.getValue(), type));
}
}
return deserializedResources;
}
public <T> T getApplicationResource(Object resource, Type type) {
if (resource == null) {
return null;
}
return gson.fromJson(gson.toJson(resource), type);
}
/**
* Once the user connects the existing application to a remote repo, we will initialize the repo with Readme.md -
* Url to the deployed app(view and edit mode)
* Link to discord channel for support
* Link to appsmith documentation for Git related operations
* Welcome message
*
* @param baseRepoSuffix path suffix used to create a branch repo path as per worktree implementation
* @param viewModeUrl URL to deployed version of the application view only mode
* @param editModeUrl URL to deployed version of the application edit mode
* @return Path where the Application is stored
*/
public Mono<Path> initializeReadme(Path baseRepoSuffix, String viewModeUrl, String editModeUrl) throws IOException {
return fileUtils
.initializeReadme(baseRepoSuffix, viewModeUrl, editModeUrl)
.onErrorResume(e -> Mono.error(new AppsmithException(AppsmithError.GIT_FILE_SYSTEM_ERROR, e)));
}
/**
* When the user clicks on detach remote, we need to remove the repo from the file system
*
* @param baseRepoSuffix path suffix used to create a branch repo path as per worktree implementation
* @return success on remove of file system
*/
public Mono<Boolean> deleteLocalRepo(Path baseRepoSuffix) {
return fileUtils.deleteLocalRepo(baseRepoSuffix);
}
public Mono<Boolean> checkIfDirectoryIsEmpty(Path baseRepoSuffix) throws IOException {
return fileUtils
.checkIfDirectoryIsEmpty(baseRepoSuffix)
.onErrorResume(e -> Mono.error(new AppsmithException(AppsmithError.GIT_FILE_SYSTEM_ERROR, e)));
}
protected void removeUnwantedFieldsFromBaseDomain(BaseDomain baseDomain) {
baseDomain.setPolicies(null);
baseDomain.setUserPermissions(null);
}
private void removeUnwantedFieldsFromDatasource(DatasourceStorage datasource) {
datasource.setInvalids(null);
removeUnwantedFieldsFromBaseDomain(datasource);
}
private void removeUnwantedFieldsFromPage(NewPage page) {
// As we are publishing the app and then committing to git we expect the published and unpublished PageDTO will
// be same, so we only commit unpublished PageDTO.
page.setPublishedPage(null);
removeUnwantedFieldsFromBaseDomain(page);
}
private void removeUnwantedFieldsFromApplication(Application application) {
// Don't commit application name as while importing we are using the repoName as application name
application.setName(null);
application.setPublishedPages(null);
application.setIsPublic(null);
application.setSlug(null);
application.setPublishedApplicationDetail(null);
removeUnwantedFieldsFromBaseDomain(application);
// we can call the sanitiseToExportDBObject() from BaseDomain as well here
}
private void removeUnwantedFieldFromAction(NewAction action) {
// As we are publishing the app and then committing to git we expect the published and unpublished ActionDTO
// will be same, so we only commit unpublished ActionDTO.
action.setPublishedAction(null);
action.getUnpublishedAction().sanitiseToExportDBObject();
removeUnwantedFieldsFromBaseDomain(action);
}
private void removeUnwantedFieldFromActionCollection(ActionCollection actionCollection) {
// As we are publishing the app and then committing to git we expect the published and unpublished
// ActionCollectionDTO will be same, so we only commit unpublished ActionCollectionDTO.
actionCollection.setPublishedCollection(null);
actionCollection.getUnpublishedCollection().sanitiseForExport();
removeUnwantedFieldsFromBaseDomain(actionCollection);
}
protected ApplicationJson getApplicationJsonFromGitReference(ApplicationGitReference applicationReference) {
ApplicationJson applicationJson = new ApplicationJson();
setApplicationInApplicationJson(applicationReference, applicationJson);
setThemesInApplicationJson(applicationReference, applicationJson);
setCustomJsLibsInApplicationJson(applicationReference, applicationJson);
setNewPagesInApplicationJson(applicationReference, applicationJson);
setNewActionsInApplicationJson(applicationReference, applicationJson);
setActionCollectionsInApplicationJson(applicationReference, applicationJson);
setDatasourcesInApplicationJson(applicationReference, applicationJson);
return applicationJson;
}
private void setApplicationInApplicationJson(
ApplicationGitReference applicationReference, ApplicationJson applicationJson) {
// Extract application data from the json
Application application = getApplicationResource(applicationReference.getApplication(), Application.class);
applicationJson.setExportedApplication(application);
if (application != null && !CollectionUtils.isNullOrEmpty(application.getPages())) {
// Remove null values
org.apache.commons.collections.CollectionUtils.filter(
application.getPages(), PredicateUtils.notNullPredicate());
// Create a deep clone of application pages to update independently
application.setViewMode(false);
final List<ApplicationPage> applicationPages =
new ArrayList<>(application.getPages().size());
application
.getPages()
.forEach(applicationPage ->
applicationPages.add(gson.fromJson(gson.toJson(applicationPage), ApplicationPage.class)));
application.setPublishedPages(applicationPages);
}
}
private void setThemesInApplicationJson(
ApplicationGitReference applicationReference, ApplicationJson applicationJson) {
applicationJson.setEditModeTheme(getApplicationResource(applicationReference.getTheme(), Theme.class));
// Clone the edit mode theme to published theme as both should be same for git connected application because we
// do deploy and push as a single operation
applicationJson.setPublishedTheme(applicationJson.getEditModeTheme());
}
private void setDatasourcesInApplicationJson(
ApplicationGitReference applicationReference, ApplicationJson applicationJson) {
// Extract datasources
applicationJson.setDatasourceList(
getApplicationResource(applicationReference.getDatasources(), DatasourceStorage.class));
}
private void setActionCollectionsInApplicationJson(
ApplicationGitReference applicationReference, ApplicationJson applicationJson) {
// Extract actionCollection
if (CollectionUtils.isNullOrEmpty(applicationReference.getActionCollections())) {
applicationJson.setActionCollectionList(new ArrayList<>());
} else {
Map<String, String> actionCollectionBody = applicationReference.getActionCollectionBody();
List<ActionCollection> actionCollections =
getApplicationResource(applicationReference.getActionCollections(), ActionCollection.class);
// Remove null values if present
org.apache.commons.collections.CollectionUtils.filter(actionCollections, PredicateUtils.notNullPredicate());
actionCollections.forEach(actionCollection -> {
// Set the js object body to the unpublished collection
// Since file version v3 we are splitting the js object code and metadata separately
String keyName = actionCollection.getUnpublishedCollection().getName()
+ actionCollection.getUnpublishedCollection().getPageId();
if (actionCollectionBody != null && actionCollectionBody.containsKey(keyName)) {
actionCollection.getUnpublishedCollection().setBody(actionCollectionBody.get(keyName));
}
// As we are publishing the app and then committing to git we expect the published and unpublished
// actionCollectionDTO will be same, so we create a deep copy for the published version for
// actionCollection from unpublishedActionCollectionDTO
actionCollection.setPublishedCollection(gson.fromJson(
gson.toJson(actionCollection.getUnpublishedCollection()), ActionCollectionDTO.class));
});
applicationJson.setActionCollectionList(actionCollections);
}
}
private void setNewActionsInApplicationJson(
ApplicationGitReference applicationReference, ApplicationJson applicationJson) {
// Extract actions
if (CollectionUtils.isNullOrEmpty(applicationReference.getActions())) {
applicationJson.setActionList(new ArrayList<>());
} else {
Map<String, String> actionBody = applicationReference.getActionBody();
List<NewAction> actions = getApplicationResource(applicationReference.getActions(), NewAction.class);
// Remove null values if present
org.apache.commons.collections.CollectionUtils.filter(actions, PredicateUtils.notNullPredicate());
actions.forEach(newAction -> {
// With the file version v4 we have split the actions and metadata separately into two files
// So we need to set the body to the unpublished action
String keyName = newAction.getUnpublishedAction().getName()
+ newAction.getUnpublishedAction().getPageId();
if (actionBody != null
&& (actionBody.containsKey(keyName))
&& !StringUtils.isEmpty(actionBody.get(keyName))) {
// For REMOTE plugin like Twilio the user actions are stored in key value pairs and hence they need
// to be
// deserialized separately unlike the body which is stored as string in the db.
if (newAction.getPluginType().toString().equals("REMOTE")) {
Map<String, Object> formData = gson.fromJson(actionBody.get(keyName), Map.class);
newAction
.getUnpublishedAction()
.getActionConfiguration()
.setFormData(formData);
} else {
newAction
.getUnpublishedAction()
.getActionConfiguration()
.setBody(actionBody.get(keyName));
}
}
// As we are publishing the app and then committing to git we expect the published and unpublished
// actionDTO will be same, so we create a deep copy for the published version for action from
// unpublishedActionDTO
newAction.setPublishedAction(
gson.fromJson(gson.toJson(newAction.getUnpublishedAction()), ActionDTO.class));
});
applicationJson.setActionList(actions);
}
}
private void setCustomJsLibsInApplicationJson(
ApplicationGitReference applicationReference, ApplicationJson applicationJson) {
List<CustomJSLib> customJSLibList =
getApplicationResource(applicationReference.getJsLibraries(), CustomJSLib.class);
// remove the duplicate js libraries if there is any
List<CustomJSLib> customJSLibListWithoutDuplicates = new ArrayList<>(new HashSet<>(customJSLibList));
applicationJson.setCustomJSLibList(customJSLibListWithoutDuplicates);
}
private void setNewPagesInApplicationJson(
ApplicationGitReference applicationReference, ApplicationJson applicationJson) {
// Extract pages
List<NewPage> pages = getApplicationResource(applicationReference.getPages(), NewPage.class);
// Remove null values
org.apache.commons.collections.CollectionUtils.filter(pages, PredicateUtils.notNullPredicate());
// Set the DSL to page object before saving
Map<String, String> pageDsl = applicationReference.getPageDsl();
pages.forEach(page -> {
JSONParser jsonParser = new JSONParser();
try {
if (pageDsl != null && pageDsl.get(page.getUnpublishedPage().getName()) != null) {
page.getUnpublishedPage().getLayouts().get(0).setDsl((JSONObject) jsonParser.parse(
pageDsl.get(page.getUnpublishedPage().getName())));
}
} catch (ParseException e) {
log.error(
"Error parsing the page dsl for page: {}",
page.getUnpublishedPage().getName(),
e);
throw new AppsmithException(
AppsmithError.JSON_PROCESSING_ERROR,
page.getUnpublishedPage().getName());
}
});
pages.forEach(newPage -> {
// As we are publishing the app and then committing to git we expect the published and unpublished PageDTO
// will be same, so we create a deep copy for the published version for page from the unpublishedPageDTO
newPage.setPublishedPage(gson.fromJson(gson.toJson(newPage.getUnpublishedPage()), PageDTO.class));
});
applicationJson.setPageList(pages);
}
public Mono<Long> deleteIndexLockFile(Path path) {
return fileUtils.deleteIndexLockFile(path, INDEX_LOCK_FILE_STALE_TIME);
}
}

View File

@ -295,8 +295,8 @@ public class ResponseUtilsCE {
public Application updateApplicationWithDefaultResources(Application application) {
if (application.getGitApplicationMetadata() != null
&& !StringUtils.isEmpty(application.getGitApplicationMetadata().getDefaultApplicationId())) {
application.setId(application.getGitApplicationMetadata().getDefaultApplicationId());
&& !StringUtils.isEmpty(application.getGitApplicationMetadata().getDefaultArtifactId())) {
application.setId(application.getGitApplicationMetadata().getDefaultArtifactId());
}
if (!CollectionUtils.isEmpty(application.getPages())) {
application.getPages().forEach(page -> {

View File

@ -479,7 +479,7 @@ public class NewPageImportableServiceCEImpl implements ImportableServiceCE<NewPa
}
if (application.getGitApplicationMetadata() != null) {
final String defaultApplicationId =
application.getGitApplicationMetadata().getDefaultApplicationId();
application.getGitApplicationMetadata().getDefaultArtifactId();
return newPageService
.findByGitSyncIdAndDefaultApplicationId(
defaultApplicationId, newPage.getGitSyncId(), Optional.empty())

View File

@ -133,8 +133,13 @@ public class CustomApplicationRepositoryCEImpl extends BaseAppsmithRepositoryImp
AclPermission aclPermission) {
return queryBuilder()
.criteria(Bridge.equal(
Application.Fields.gitApplicationMetadata_defaultApplicationId, defaultApplicationId)
.criteria(Bridge.or(
Bridge.equal(
Application.Fields.gitApplicationMetadata_defaultApplicationId,
defaultApplicationId),
Bridge.equal(
Application.Fields.gitApplicationMetadata_defaultArtifactId,
defaultApplicationId))
.equal(Application.Fields.gitApplicationMetadata_branchName, branchName))
.fields(projectionFieldNames)
.permission(aclPermission)

View File

@ -8,8 +8,8 @@ import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.git.autocommit.helpers.AutoCommitEligibilityHelper;
import com.appsmith.server.git.autocommit.helpers.GitAutoCommitHelper;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.ResponseUtils;
import com.appsmith.server.layouts.UpdateLayoutService;
import com.appsmith.server.newactions.base.NewActionService;
@ -48,7 +48,7 @@ public class ApplicationPageServiceImpl extends ApplicationPageServiceCEImpl imp
NewPageService newPageService,
NewActionService newActionService,
ActionCollectionService actionCollectionService,
GitFileUtils gitFileUtils,
CommonGitFileUtils commonGitFileUtils,
ThemeService themeService,
ResponseUtils responseUtils,
WorkspacePermission workspacePermission,
@ -80,7 +80,7 @@ public class ApplicationPageServiceImpl extends ApplicationPageServiceCEImpl imp
newPageService,
newActionService,
actionCollectionService,
gitFileUtils,
commonGitFileUtils,
themeService,
responseUtils,
workspacePermission,

View File

@ -1,5 +0,0 @@
package com.appsmith.server.services;
import com.appsmith.server.services.ce_compatible.CommonGitServiceCECompatible;
public interface CommonGitService extends CommonGitServiceCECompatible {}

View File

@ -1,5 +0,0 @@
package com.appsmith.server.services;
import com.appsmith.server.services.ce.GitServiceCE;
public interface GitService extends GitServiceCE {}

View File

@ -1,91 +0,0 @@
package com.appsmith.server.services;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.git.service.GitExecutorImpl;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.configurations.EmailConfig;
import com.appsmith.server.datasources.base.DatasourceService;
import com.appsmith.server.exports.internal.ExportService;
import com.appsmith.server.git.GitRedisUtils;
import com.appsmith.server.git.autocommit.helpers.GitAutoCommitHelper;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.helpers.ResponseUtils;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.plugins.base.PluginService;
import com.appsmith.server.repositories.GitDeployKeysRepository;
import com.appsmith.server.services.ce_compatible.GitServiceCECompatibleImpl;
import com.appsmith.server.solutions.ApplicationPermission;
import com.appsmith.server.solutions.DatasourcePermission;
import com.appsmith.server.solutions.WorkspacePermission;
import io.micrometer.observation.ObservationRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;
import org.springframework.transaction.reactive.TransactionalOperator;
@Slf4j
@Service
@Import({GitExecutorImpl.class})
public class GitServiceImpl extends GitServiceCECompatibleImpl implements GitService {
public GitServiceImpl(
UserService userService,
UserDataService userDataService,
SessionUserService sessionUserService,
ApplicationService applicationService,
ApplicationPageService applicationPageService,
NewPageService newPageService,
NewActionService newActionService,
ActionCollectionService actionCollectionService,
GitFileUtils fileUtils,
ImportService importService,
ExportService exportService,
GitExecutor gitExecutor,
ResponseUtils responseUtils,
EmailConfig emailConfig,
AnalyticsService analyticsService,
GitDeployKeysRepository gitDeployKeysRepository,
DatasourceService datasourceService,
PluginService pluginService,
DatasourcePermission datasourcePermission,
ApplicationPermission applicationPermission,
WorkspacePermission workspacePermission,
WorkspaceService workspaceService,
GitRedisUtils gitRedisUtils,
ObservationRegistry observationRegistry,
GitPrivateRepoHelper gitPrivateRepoHelper,
TransactionalOperator transactionalOperator,
GitAutoCommitHelper gitAutoCommitHelper) {
super(
userService,
userDataService,
sessionUserService,
applicationService,
applicationPageService,
newPageService,
newActionService,
actionCollectionService,
fileUtils,
importService,
exportService,
gitExecutor,
responseUtils,
emailConfig,
analyticsService,
gitDeployKeysRepository,
datasourceService,
pluginService,
datasourcePermission,
applicationPermission,
workspacePermission,
workspaceService,
gitRedisUtils,
observationRegistry,
gitPrivateRepoHelper,
transactionalOperator,
gitAutoCommitHelper);
}
}

View File

@ -37,8 +37,8 @@ import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.git.autocommit.helpers.AutoCommitEligibilityHelper;
import com.appsmith.server.git.autocommit.helpers.GitAutoCommitHelper;
import com.appsmith.server.helpers.CollectionUtils;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.GitUtils;
import com.appsmith.server.helpers.ResponseUtils;
import com.appsmith.server.helpers.UserPermissionUtils;
@ -111,7 +111,7 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
private final NewPageService newPageService;
private final NewActionService newActionService;
private final ActionCollectionService actionCollectionService;
private final GitFileUtils gitFileUtils;
private final CommonGitFileUtils commonGitFileUtils;
private final ThemeService themeService;
private final ResponseUtils responseUtils;
private final WorkspacePermission workspacePermission;
@ -603,7 +603,7 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
GitArtifactMetadata gitData = application.getGitApplicationMetadata();
if (GitUtils.isApplicationConnectedToGit(application)) {
return applicationService.findAllApplicationsByDefaultApplicationId(
gitData.getDefaultApplicationId(), applicationPermission.getDeletePermission());
gitData.getDefaultArtifactId(), applicationPermission.getDeletePermission());
}
return Flux.fromIterable(List.of(application));
})
@ -615,13 +615,13 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
.flatMap(application -> {
GitArtifactMetadata gitData = application.getGitApplicationMetadata();
if (gitData != null
&& !StringUtils.isEmpty(gitData.getDefaultApplicationId())
&& !StringUtils.isEmpty(gitData.getDefaultArtifactId())
&& !StringUtils.isEmpty(gitData.getRepoName())) {
String repoName = gitData.getRepoName();
Path repoPath =
Paths.get(application.getWorkspaceId(), gitData.getDefaultApplicationId(), repoName);
Paths.get(application.getWorkspaceId(), gitData.getDefaultArtifactId(), repoName);
// Delete git repo from local
return gitFileUtils.deleteLocalRepo(repoPath).then(Mono.just(application));
return commonGitFileUtils.deleteLocalRepo(repoPath).then(Mono.just(application));
}
return Mono.just(application);
});
@ -741,7 +741,7 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
DefaultResources defaults = new DefaultResources();
GitArtifactMetadata gitData = application.getGitApplicationMetadata();
if (gitData != null) {
defaults.setApplicationId(gitData.getDefaultApplicationId());
defaults.setApplicationId(gitData.getDefaultArtifactId());
defaults.setBranchName(gitData.getBranchName());
} else {
defaults.setApplicationId(applicationId);

View File

@ -2,6 +2,7 @@ package com.appsmith.server.services.ce;
import com.appsmith.server.acl.AclPermission;
import com.appsmith.server.domains.Artifact;
import com.appsmith.server.dtos.ArtifactExchangeJson;
import com.appsmith.server.dtos.GitAuthDTO;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -57,5 +58,11 @@ public interface GitArtifactHelperCE<T extends Artifact> {
Mono<T> isPrivateRepoLimitReached(Artifact artifact, boolean isClearCache);
Mono<T> publishArtifact(Artifact artifact);
Mono<T> publishArtifact(Artifact artifact, Boolean publishedManually);
Mono<T> createArtifactForImport(String workspaceId, String repoName);
Mono<T> deleteArtifact(String artifactId);
Boolean isContextInArtifactEmpty(ArtifactExchangeJson artifactExchangeJson);
}

View File

@ -1,93 +0,0 @@
package com.appsmith.server.services.ce;
import com.appsmith.external.dtos.GitBranchDTO;
import com.appsmith.external.dtos.GitLogDTO;
import com.appsmith.external.dtos.GitStatusDTO;
import com.appsmith.external.dtos.MergeStatusDTO;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.GitArtifactMetadata;
import com.appsmith.server.domains.GitAuth;
import com.appsmith.server.domains.GitProfile;
import com.appsmith.server.dtos.ApplicationImportDTO;
import com.appsmith.server.dtos.AutoCommitProgressDTO;
import com.appsmith.server.dtos.GitCommitDTO;
import com.appsmith.server.dtos.GitConnectDTO;
import com.appsmith.server.dtos.GitDocsDTO;
import com.appsmith.server.dtos.GitMergeDTO;
import com.appsmith.server.dtos.GitPullDTO;
import org.eclipse.jgit.lib.BranchTrackingStatus;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Map;
public interface GitServiceCE {
Mono<Map<String, GitProfile>> updateOrCreateGitProfileForCurrentUser(GitProfile gitProfile);
Mono<Map<String, GitProfile>> updateOrCreateGitProfileForCurrentUser(
GitProfile gitProfile, String defaultApplicationId);
Mono<GitProfile> getDefaultGitProfileOrCreateIfEmpty();
Mono<GitProfile> getGitProfileForUser(String defaultApplicationId);
Mono<Application> connectApplicationToGit(String defaultApplicationId, GitConnectDTO gitConnectDTO, String origin);
Mono<Application> updateGitMetadata(String applicationId, GitArtifactMetadata gitArtifactMetadata);
Mono<String> commitApplication(
GitCommitDTO commitDTO, String defaultApplicationId, String branchName, boolean doAmend);
Mono<String> commitApplication(GitCommitDTO commitDTO, String defaultApplicationId, String branchName);
Mono<List<GitLogDTO>> getCommitHistory(String defaultApplicationId, String branchName);
Mono<String> pushApplication(String defaultApplicationId, String branchName);
Mono<Application> detachRemote(String defaultApplicationId);
Mono<Application> createBranch(String defaultApplicationId, GitBranchDTO branchDTO, String srcBranch);
Mono<Application> checkoutBranch(String defaultApplicationId, String branchName, boolean addFileLock);
Mono<GitPullDTO> pullApplication(String defaultApplicationId, String branchName);
Mono<List<GitBranchDTO>> listBranchForApplication(
String defaultApplicationId, Boolean pruneBranches, String currentBranch);
Mono<GitArtifactMetadata> getGitApplicationMetadata(String defaultApplicationId);
Mono<GitStatusDTO> getStatus(String defaultApplicationId, boolean compareRemote, String branchName);
Mono<MergeStatusDTO> mergeBranch(String applicationId, GitMergeDTO gitMergeDTO);
Mono<MergeStatusDTO> isBranchMergeable(String applicationId, GitMergeDTO gitMergeDTO);
Mono<String> createConflictedBranch(String defaultApplicationId, String branchName);
// TODO
Mono<ApplicationImportDTO> importApplicationFromGit(String organisationId, GitConnectDTO gitConnectDTO);
Mono<GitAuth> generateSSHKey(String keyType);
Mono<Boolean> testConnection(String defaultApplicationId);
Mono<Application> deleteBranch(String defaultApplicationId, String branchName);
Mono<Application> discardChanges(String defaultApplicationId, String branchName);
Mono<List<GitDocsDTO>> getGitDocUrls();
Mono<BranchTrackingStatus> fetchRemoteChanges(String defaultApplicationId, String branchName, boolean isFileLock);
Mono<List<String>> updateProtectedBranches(String defaultApplicationId, List<String> branchNames);
Mono<List<String>> getProtectedBranches(String defaultApplicationId);
Mono<AutoCommitProgressDTO> getAutoCommitProgress(String applicationId);
Mono<Boolean> autoCommitApplication(String defaultApplicationId, String branchName);
Mono<Boolean> toggleAutoCommitEnabled(String defaultApplicationId);
}

View File

@ -1,5 +0,0 @@
package com.appsmith.server.services.ce_compatible;
import com.appsmith.server.services.ce.CommonGitServiceCE;
public interface CommonGitServiceCECompatible extends CommonGitServiceCE {}

View File

@ -1,5 +0,0 @@
package com.appsmith.server.services.ce_compatible;
import com.appsmith.server.services.ce.GitServiceCE;
public interface GitServiceCECompatible extends GitServiceCE {}

View File

@ -1,93 +0,0 @@
package com.appsmith.server.services.ce_compatible;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.configurations.EmailConfig;
import com.appsmith.server.datasources.base.DatasourceService;
import com.appsmith.server.exports.internal.ExportService;
import com.appsmith.server.git.GitRedisUtils;
import com.appsmith.server.git.autocommit.helpers.GitAutoCommitHelper;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.helpers.ResponseUtils;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.plugins.base.PluginService;
import com.appsmith.server.repositories.GitDeployKeysRepository;
import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.ApplicationPageService;
import com.appsmith.server.services.SessionUserService;
import com.appsmith.server.services.UserDataService;
import com.appsmith.server.services.UserService;
import com.appsmith.server.services.WorkspaceService;
import com.appsmith.server.services.ce.GitServiceCEImpl;
import com.appsmith.server.solutions.ApplicationPermission;
import com.appsmith.server.solutions.DatasourcePermission;
import com.appsmith.server.solutions.WorkspacePermission;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.reactive.TransactionalOperator;
@Service
public class GitServiceCECompatibleImpl extends GitServiceCEImpl implements GitServiceCECompatible {
public GitServiceCECompatibleImpl(
UserService userService,
UserDataService userDataService,
SessionUserService sessionUserService,
ApplicationService applicationService,
ApplicationPageService applicationPageService,
NewPageService newPageService,
NewActionService newActionService,
ActionCollectionService actionCollectionService,
GitFileUtils fileUtils,
ImportService importService,
ExportService exportService,
GitExecutor gitExecutor,
ResponseUtils responseUtils,
EmailConfig emailConfig,
AnalyticsService analyticsService,
GitDeployKeysRepository gitDeployKeysRepository,
DatasourceService datasourceService,
PluginService pluginService,
DatasourcePermission datasourcePermission,
ApplicationPermission applicationPermission,
WorkspacePermission workspacePermission,
WorkspaceService workspaceService,
GitRedisUtils gitRedisUtils,
ObservationRegistry observationRegistry,
GitPrivateRepoHelper gitPrivateRepoHelper,
TransactionalOperator transactionalOperator,
GitAutoCommitHelper gitAutoCommitHelper) {
super(
userService,
userDataService,
sessionUserService,
applicationService,
applicationPageService,
newPageService,
newActionService,
actionCollectionService,
fileUtils,
importService,
exportService,
gitExecutor,
responseUtils,
emailConfig,
analyticsService,
gitDeployKeysRepository,
datasourceService,
pluginService,
datasourcePermission,
applicationPermission,
workspacePermission,
workspaceService,
gitRedisUtils,
observationRegistry,
gitPrivateRepoHelper,
transactionalOperator,
gitAutoCommitHelper);
}
}

View File

@ -11,7 +11,7 @@ import com.appsmith.server.exceptions.AppsmithErrorCode;
import com.appsmith.server.exports.internal.ExportService;
import com.appsmith.server.exports.internal.partial.PartialExportService;
import com.appsmith.server.fork.internal.ApplicationForkingService;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.imports.internal.partial.PartialImportService;
@ -83,7 +83,7 @@ public class ApplicationControllerTest {
AnalyticsService analyticsService;
@MockBean
GitFileUtils gitFileUtils;
CommonGitFileUtils commonGitFileUtils;
@MockBean
SessionUserService sessionUserService;

View File

@ -18,13 +18,13 @@ import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.AutoCommitTriggerDTO;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.git.autocommit.helpers.AutoCommitEligibilityHelper;
import com.appsmith.server.git.common.CommonGitService;
import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.migrations.JsonSchemaMigration;
import com.appsmith.server.migrations.JsonSchemaVersions;
import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.services.ApplicationPageService;
import com.appsmith.server.services.CommonGitService;
import com.appsmith.server.services.FeatureFlagService;
import com.appsmith.server.services.UserDataService;
import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper;

View File

@ -19,7 +19,6 @@ import com.appsmith.server.git.AutoCommitEventHandlerImpl;
import com.appsmith.server.git.GitRedisUtils;
import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.helpers.GitFileUtils;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.migrations.JsonSchemaMigration;
import com.appsmith.server.migrations.JsonSchemaVersions;
@ -83,9 +82,6 @@ public class AutoCommitEventHandlerImplTest {
@MockBean
DSLMigrationUtils dslMigrationUtils;
@SpyBean
GitFileUtils gitFileUtils;
@SpyBean
FileInterface fileUtils;
@ -120,7 +116,6 @@ public class AutoCommitEventHandlerImplTest {
gitRedisUtils,
redisUtils,
dslMigrationUtils,
gitFileUtils,
commonGitFileUtils,
gitExecutor,
projectProperties,
@ -221,8 +216,8 @@ public class AutoCommitEventHandlerImplTest {
Mockito.when(dslMigrationUtils.migratePageDsl(any(JSONObject.class))).thenReturn(Mono.just(dslAfterMigration));
doReturn(Mono.just(baseRepoSuffix))
.when(gitFileUtils)
.saveApplicationToLocalRepo(
.when(commonGitFileUtils)
.saveArtifactToLocalRepo(
autoCommitEvent.getWorkspaceId(),
autoCommitEvent.getApplicationId(),
autoCommitEvent.getRepoName(),
@ -319,8 +314,8 @@ public class AutoCommitEventHandlerImplTest {
ArtifactType.APPLICATION);
doReturn(Mono.just(baseRepoSuffix))
.when(gitFileUtils)
.saveApplicationToLocalRepo(
.when(commonGitFileUtils)
.saveArtifactToLocalRepo(
autoCommitEvent.getWorkspaceId(),
autoCommitEvent.getApplicationId(),
autoCommitEvent.getRepoName(),
@ -394,8 +389,8 @@ public class AutoCommitEventHandlerImplTest {
ArtifactType.APPLICATION);
doReturn(Mono.just(baseRepoSuffix))
.when(gitFileUtils)
.saveApplicationToLocalRepo(
.when(commonGitFileUtils)
.saveArtifactToLocalRepo(
autoCommitEvent.getWorkspaceId(),
autoCommitEvent.getApplicationId(),
autoCommitEvent.getRepoName(),
@ -440,8 +435,8 @@ public class AutoCommitEventHandlerImplTest {
autoCommitEvent.getBranchName());
doReturn(Mono.just(baseRepoSuffix))
.when(gitFileUtils)
.saveApplicationToLocalRepo(
.when(commonGitFileUtils)
.saveArtifactToLocalRepo(
anyString(), anyString(), anyString(), any(ApplicationJson.class), anyString());
ApplicationJson applicationJson1 = new ApplicationJson();

View File

@ -11,9 +11,9 @@ import com.appsmith.server.domains.GitProfile;
import com.appsmith.server.dtos.AutoCommitProgressDTO;
import com.appsmith.server.events.AutoCommitEvent;
import com.appsmith.server.git.AutoCommitEventHandler;
import com.appsmith.server.git.common.CommonGitService;
import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.services.CommonGitService;
import com.appsmith.server.services.FeatureFlagService;
import com.appsmith.server.services.UserDataService;
import com.appsmith.server.solutions.ApplicationPermission;

View File

@ -2,6 +2,7 @@ package com.appsmith.server.helpers;
import com.appsmith.external.git.FileInterface;
import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.server.constants.ArtifactType;
import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
@ -52,7 +53,7 @@ public class GitFileUtilsTest {
FileInterface fileInterface;
@Autowired
GitFileUtils gitFileUtils;
CommonGitFileUtils commonGitFileUtils;
@Autowired
AnalyticsService analyticsService;
@ -90,7 +91,8 @@ public class GitFileUtilsTest {
@Test
public void getSerializableResource_allEntitiesArePresentForApplication_keysIncludesSeparator() {
ApplicationJson validAppJson = createAppJson(filePath).block();
ApplicationGitReference applicationGitReference = gitFileUtils.createApplicationReference(validAppJson);
ApplicationGitReference applicationGitReference =
(ApplicationGitReference) commonGitFileUtils.createArtifactReference(validAppJson);
List<String> pageNames = validAppJson.getPageList().stream()
.map(newPage -> newPage.getUnpublishedPage().getName())
@ -149,7 +151,8 @@ public class GitFileUtilsTest {
.get(validAppJson.getActionCollectionList().size() - 1);
deletedCollection.getUnpublishedCollection().setDeletedAt(Instant.now());
ApplicationGitReference applicationGitReference = gitFileUtils.createApplicationReference(validAppJson);
ApplicationGitReference applicationGitReference =
(ApplicationGitReference) commonGitFileUtils.createArtifactReference(validAppJson);
Map<String, Object> actions = applicationGitReference.getActions();
for (Map.Entry<String, Object> entry : actions.entrySet()) {
@ -187,7 +190,7 @@ public class GitFileUtilsTest {
Mockito.any(Path.class), Mockito.any(ApplicationGitReference.class), Mockito.anyString()))
.thenReturn(Mono.just(Path.of("orgId", "appId", "repoName")));
Mono<Path> resultMono = gitFileUtils.saveApplicationToLocalRepoWithAnalytics(
Mono<Path> resultMono = commonGitFileUtils.saveArtifactToLocalRepoWithAnalytics(
Path.of("orgId/appId/repoName"), validAppJson, "gitFileTest");
StepVerifier.create(resultMono)
@ -240,8 +243,10 @@ public class GitFileUtilsTest {
Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()))
.thenReturn(Mono.just(applicationReference));
Mono<ApplicationJson> resultMono = gitFileUtils
.reconstructApplicationJsonFromGitRepoWithAnalytics("orgId", "appId", "repoName", "branch")
Mono<ApplicationJson> resultMono = commonGitFileUtils
.reconstructArtifactExchangeJsonFromGitRepoWithAnalytics(
"orgId", "appId", "repoName", "branch", ArtifactType.APPLICATION)
.map(artifactExchangeJson -> (ApplicationJson) artifactExchangeJson)
.cache();
StepVerifier.create(resultMono)

View File

@ -8,7 +8,7 @@ import com.appsmith.server.domains.UserData;
import com.appsmith.server.dtos.RecentlyUsedEntityDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.ApplicationRepository;
import com.appsmith.server.git.common.CommonGitService;
import com.appsmith.server.repositories.AssetRepository;
import com.appsmith.server.repositories.UserDataRepository;
import org.assertj.core.api.AssertionsForClassTypes;
@ -61,13 +61,7 @@ public class UserDataServiceTest {
private AssetRepository assetRepository;
@Autowired
private AssetService assetService;
@Autowired
private ApplicationRepository applicationRepository;
@Autowired
private GitService gitService;
private CommonGitService commonGitService;
private Mono<User> userMono;
@ -448,7 +442,7 @@ public class UserDataServiceTest {
GitProfile gitGlobalConfigDTO = createGitProfile(null, "Test 1");
Mono<Map<String, GitProfile>> userDataMono =
gitService.updateOrCreateGitProfileForCurrentUser(gitGlobalConfigDTO);
commonGitService.updateOrCreateGitProfileForCurrentUser(gitGlobalConfigDTO);
StepVerifier.create(userDataMono)
.expectErrorMatches(throwable -> throwable instanceof AppsmithException
&& throwable.getMessage().contains(AppsmithError.INVALID_PARAMETER.getMessage("Author Email")))
@ -461,7 +455,7 @@ public class UserDataServiceTest {
GitProfile gitProfileDTO = createGitProfile(null, null);
Mono<Map<String, GitProfile>> userDataMono =
gitService.updateOrCreateGitProfileForCurrentUser(gitProfileDTO, "defaultAppId");
commonGitService.updateOrCreateGitProfileForCurrentUser(gitProfileDTO, "defaultAppId");
StepVerifier.create(userDataMono)
.assertNext(gitProfileMap -> {
AssertionsForClassTypes.assertThat(gitProfileMap).isNotNull();
@ -483,7 +477,7 @@ public class UserDataServiceTest {
GitProfile gitGlobalConfigDTO = createGitProfile("test@appsmith.com", null);
Mono<Map<String, GitProfile>> userDataMono =
gitService.updateOrCreateGitProfileForCurrentUser(gitGlobalConfigDTO);
commonGitService.updateOrCreateGitProfileForCurrentUser(gitGlobalConfigDTO);
StepVerifier.create(userDataMono)
.expectErrorMatches(throwable -> throwable instanceof AppsmithException
&& throwable.getMessage().contains(AppsmithError.INVALID_PARAMETER.getMessage("Author Name")))
@ -494,7 +488,7 @@ public class UserDataServiceTest {
@WithUserDetails(value = "api_user")
public void getAndUpdateDefaultGitProfile_fallbackValueFromUserProfileIfEmpty_updateWithProfile() {
Mono<GitProfile> gitConfigMono = gitService.getDefaultGitProfileOrCreateIfEmpty();
Mono<GitProfile> gitConfigMono = commonGitService.getDefaultGitProfileOrCreateIfEmpty();
Mono<User> userData = userDataService
.getForCurrentUser()
@ -511,7 +505,7 @@ public class UserDataServiceTest {
GitProfile gitGlobalConfigDTO = createGitProfile("test@appsmith.com", "Test 1");
Mono<Map<String, GitProfile>> gitProfilesMono =
gitService.updateOrCreateGitProfileForCurrentUser(gitGlobalConfigDTO);
commonGitService.updateOrCreateGitProfileForCurrentUser(gitGlobalConfigDTO);
StepVerifier.create(gitProfilesMono)
.assertNext(gitProfileMap -> {