[Bug Fix Improvement] : Table widget keys are unescaped after walking through the DSL (#3908)
* WIP : untested
* Minor refactoring
* Added test case to assert escaping and unescaping of the table widget primary column keys
(cherry picked from commit 174ef284f0)
This commit is contained in:
parent
2f3c0be5b3
commit
3b83a36bd1
|
|
@ -1,12 +1,10 @@
|
|||
package com.appsmith.server.helpers;
|
||||
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.minidev.json.JSONObject;
|
||||
import net.minidev.json.parser.JSONParser;
|
||||
import net.minidev.json.parser.ParseException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -49,18 +47,31 @@ public class WidgetSpecificUtils {
|
|||
|
||||
public static JSONObject unEscapeTableWidgetPrimaryColumns(JSONObject dsl) {
|
||||
|
||||
String dslAsString;
|
||||
try {
|
||||
dslAsString = objectMapper.writeValueAsString(dsl);
|
||||
dslAsString = dslAsString.replaceAll(FieldName.MONGO_ESCAPE_ID, FieldName.MONGO_UNESCAPED_ID);
|
||||
dslAsString = dslAsString.replaceAll(FieldName.MONGO_ESCAPE_CLASS, FieldName.MONGO_UNESCAPED_CLASS);
|
||||
Set<String> keySet = dsl.keySet();
|
||||
|
||||
return (JSONObject) jsonParser.parse(dslAsString);
|
||||
if (keySet.contains(FieldName.PRIMARY_COLUMNS)) {
|
||||
Map primaryColumns = (Map) dsl.get(FieldName.PRIMARY_COLUMNS);
|
||||
|
||||
} catch (JsonProcessingException | ParseException e) {
|
||||
// Something went wrong in parsing the DSL. Return as is
|
||||
return dsl;
|
||||
Map newPrimaryColumns = new HashMap();
|
||||
|
||||
Boolean updateRequired = false;
|
||||
|
||||
for (String columnName : (Set<String>) primaryColumns.keySet()) {
|
||||
if (columnName.equals(FieldName.MONGO_ESCAPE_ID)) {
|
||||
updateRequired = true;
|
||||
newPrimaryColumns.put(FieldName.MONGO_UNESCAPED_ID, primaryColumns.get(columnName));
|
||||
} else if (columnName.equals(FieldName.MONGO_ESCAPE_CLASS)) {
|
||||
updateRequired = true;
|
||||
newPrimaryColumns.put(FieldName.MONGO_UNESCAPED_CLASS, primaryColumns.get(columnName));
|
||||
} else {
|
||||
newPrimaryColumns.put(columnName, primaryColumns.get(columnName));
|
||||
}
|
||||
}
|
||||
if (updateRequired) {
|
||||
dsl.put(FieldName.PRIMARY_COLUMNS, newPrimaryColumns);
|
||||
}
|
||||
}
|
||||
|
||||
return dsl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -694,7 +694,46 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
JSONObject dsl = layout.getDsl();
|
||||
|
||||
// Unescape specific widgets
|
||||
dsl = WidgetSpecificUtils.unEscapeTableWidgetPrimaryColumns(dsl);
|
||||
dsl = unEscapeDslKeys(dsl, layout.getMongoEscapedWidgetNames());
|
||||
|
||||
return dsl;
|
||||
}
|
||||
|
||||
private JSONObject unEscapeDslKeys(JSONObject dsl, Set<String> escapedWidgetNames) {
|
||||
|
||||
String widgetName = (String) dsl.get(FieldName.WIDGET_NAME);
|
||||
|
||||
if (widgetName == null) {
|
||||
// This isnt a valid widget configuration. No need to traverse further.
|
||||
return dsl;
|
||||
}
|
||||
|
||||
if (escapedWidgetNames.contains(widgetName)) {
|
||||
// We should escape the widget keys
|
||||
String widgetType = dsl.getAsString(FieldName.WIDGET_TYPE);
|
||||
if (widgetType.equals(FieldName.TABLE_WIDGET)) {
|
||||
// UnEscape Table widget keys
|
||||
// Since this is a table widget, it wouldnt have children. We can safely return from here with updated dsl
|
||||
return WidgetSpecificUtils.unEscapeTableWidgetPrimaryColumns(dsl);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the children of the current node in the DSL and recursively iterate over them to extract bindings
|
||||
ArrayList<Object> children = (ArrayList<Object>) dsl.get(FieldName.CHILDREN);
|
||||
ArrayList<Object> newChildren = new ArrayList<>();
|
||||
if (children != null) {
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
Map data = (Map) children.get(i);
|
||||
JSONObject object = new JSONObject();
|
||||
// If the children tag exists and there are entries within it
|
||||
if (!CollectionUtils.isEmpty(data)) {
|
||||
object.putAll(data);
|
||||
JSONObject child = unEscapeDslKeys(object, escapedWidgetNames);
|
||||
newChildren.add(child);
|
||||
}
|
||||
}
|
||||
dsl.put(FieldName.CHILDREN, newChildren);
|
||||
}
|
||||
|
||||
return dsl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.appsmith.server.services;
|
|||
import com.appsmith.external.models.ActionConfiguration;
|
||||
import com.appsmith.external.models.DatasourceConfiguration;
|
||||
import com.appsmith.server.acl.AclPermission;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.domains.Application;
|
||||
import com.appsmith.server.domains.Datasource;
|
||||
import com.appsmith.server.domains.Layout;
|
||||
|
|
@ -38,6 +39,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
|||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
|
@ -444,4 +446,42 @@ public class LayoutActionServiceTest {
|
|||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void tableWidgetKeyEscape() {
|
||||
Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())).thenReturn(Mono.just(new MockPluginExecutor()));
|
||||
|
||||
JSONObject dsl = new JSONObject();
|
||||
dsl.put("widgetName", "Table1");
|
||||
dsl.put("type", "TABLE_WIDGET");
|
||||
Map primaryColumns = new HashMap<String, Object>();
|
||||
JSONObject jsonObject = new JSONObject(Map.of("key", "value"));
|
||||
primaryColumns.put("_id", jsonObject);
|
||||
primaryColumns.put("_class", jsonObject);
|
||||
dsl.put("primaryColumns", primaryColumns);
|
||||
Layout layout = testPage.getLayouts().get(0);
|
||||
layout.setDsl(dsl);
|
||||
|
||||
Mono<LayoutDTO> updateLayoutMono = layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout).cache();
|
||||
|
||||
Mono<PageDTO> pageFromRepoMono = updateLayoutMono.then(newPageService.findPageById(testPage.getId(), READ_PAGES, false));
|
||||
|
||||
StepVerifier
|
||||
.create(Mono.zip(updateLayoutMono, pageFromRepoMono))
|
||||
.assertNext(tuple -> {
|
||||
LayoutDTO updatedLayout = tuple.getT1();
|
||||
PageDTO pageFromRepo = tuple.getT2();
|
||||
|
||||
Map primaryColumns1 = (Map) updatedLayout.getDsl().get("primaryColumns");
|
||||
assertThat(primaryColumns1.keySet()).containsAll(Set.of(FieldName.MONGO_UNESCAPED_ID, FieldName.MONGO_UNESCAPED_CLASS));
|
||||
|
||||
Map primaryColumns2 = (Map) pageFromRepo.getLayouts().get(0).getDsl().get("primaryColumns");
|
||||
assertThat(primaryColumns2.keySet()).containsAll(Set.of(FieldName.MONGO_ESCAPE_ID, FieldName.MONGO_ESCAPE_CLASS));
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user