diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/constants/CommonConstants.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/constants/CommonConstants.java index 4f71fbf877..8df84c9b8e 100644 --- a/app/server/appsmith-git/src/main/java/com/appsmith/git/constants/CommonConstants.java +++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/constants/CommonConstants.java @@ -25,7 +25,7 @@ public class CommonConstants { public static final String DELIMITER_PATH = "/"; public static final String EMPTY_STRING = ""; public static final String FILE_MIGRATION_MESSAGE = - "Some of the changes above are due to an improved file structure designed to reduce merge conflicts. You can safely commit them to your repository."; + "Some of the changes above are due to an improved file structure. You can safely commit them to your repository."; public static final String TABS_WIDGET = "TABS_WIDGET"; diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java index d888d1d70e..ace1607049 100644 --- a/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java +++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/helpers/FileUtilsImpl.java @@ -47,8 +47,11 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.util.Arrays; +import java.util.Base64; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -304,7 +307,9 @@ public class FileUtilsImpl implements FileInterface { Boolean isResourceUpdated = !CollectionUtils.isEmpty(updatedResources.get(CUSTOM_JS_LIB_LIST)) ? updatedResources.get(CUSTOM_JS_LIB_LIST).contains(uidString) : Boolean.FALSE; - String fileNameWithExtension = uidString.replaceAll("/", "_") + CommonConstants.JSON_EXTENSION; + + String fileNameWithExtension = getJsLibFileName(uidString) + CommonConstants.JSON_EXTENSION; + Path jsLibSpecificFile = jsLibDirectory.resolve(fileNameWithExtension); if (isResourceUpdated) { saveResource(jsLibEntry.getValue(), jsLibSpecificFile, gson); @@ -1108,4 +1113,33 @@ public class FileUtilsImpl implements FileInterface { return Mono.just(0L); } } + + /** + * We use UID string for custom js lib. UID strings are in this format: {libname}_{url to the lib src}. + * This method converts this uid string into a valid file name so that there is no unsupported character in the + * file name for any OS. + * This method returns a string in the format: {libname}_{base64 encoded hash of uid string} + * @param uidString UID string value of a JS lib + * @return String + */ + public static String getJsLibFileName(String uidString) { + int firstUnderscoreIndex = uidString.indexOf('_'); // this finds the first occurrence of "_" + String prefix; + if (firstUnderscoreIndex != -1) { + prefix = uidString.substring(0, firstUnderscoreIndex); // we're getting the prefix from the uidString + } else { + prefix = "jslib"; + } + + StringBuilder stringBuilder = new StringBuilder(prefix); + stringBuilder.append("_"); + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(uidString.getBytes(StandardCharsets.UTF_8)); + stringBuilder.append(Base64.getUrlEncoder().withoutPadding().encodeToString(hash)); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Failed to hash URL string", e); + } + return stringBuilder.toString(); + } } diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java index 2c00f0a1e3..869630eb42 100644 --- a/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java +++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/service/GitExecutorImpl.java @@ -60,6 +60,8 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import static com.appsmith.git.constants.CommonConstants.FILE_MIGRATION_MESSAGE; + @RequiredArgsConstructor @Component @Slf4j @@ -552,6 +554,17 @@ public class GitExecutorImpl implements GitExecutor { modifiedDatasources++; } else if (x.contains(GitDirectories.JS_LIB_DIRECTORY + CommonConstants.DELIMITER_PATH)) { modifiedJSLibs++; + // remove this code in future when all the older format js libs are migrated to new + // format + + if (x.contains("js.json")) { + /* + As this updated filename has color(:), it means this is the older format js + lib file that we're going to rename with the format without colon. + Hence, we need to show a message to user saying this might be a system level change. + */ + response.setMigrationMessage(FILE_MIGRATION_MESSAGE); + } } } response.setModified(modifiedAssets); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java index cb152fe03c..f672f34664 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitFileUtils.java @@ -539,7 +539,11 @@ public class GitFileUtils { List customJSLibList = getApplicationResource(applicationReference.getJsLibraries(), CustomJSLib.class); - applicationJson.setCustomJSLibList(customJSLibList); + + // remove the duplicate js libraries if there is any + List customJSLibListWithoutDuplicates = new ArrayList<>(new HashSet<>(customJSLibList)); + + applicationJson.setCustomJSLibList(customJSLibListWithoutDuplicates); // Extract pages List pages = getApplicationResource(applicationReference.getPages(), NewPage.class);