diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java index f7c41b0fc6..1e49974b28 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java @@ -778,41 +778,68 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { JsonNode expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":true, \"D\":\"stringValue\"}}"); Assert.assertEquals(expectedSettings, updatedSettings); - JsonNode patchedSettings = mapper.readTree("{\"B\":{\"C\":false, \"D\":\"stringValue2\"}}"); + JsonNode patchedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\":\"stringValue2\"}}"); doPut("/api/user/settings", patchedSettings); updatedSettings = doGet("/api/user/settings", JsonNode.class); - expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\":\"stringValue2\"}}"); + expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\":\"stringValue2\"}}"); Assert.assertEquals(expectedSettings, updatedSettings); patchedSettings = mapper.readTree("{\"B.D\": \"stringValue3\"}"); doPut("/api/user/settings", patchedSettings); updatedSettings = doGet("/api/user/settings", JsonNode.class); - expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\": \"stringValue3\"}}"); + expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\": \"stringValue3\"}}"); Assert.assertEquals(expectedSettings, updatedSettings); patchedSettings = mapper.readTree("{\"B.D\": {\"E\": 76, \"F\": 92}}"); doPut("/api/user/settings", patchedSettings); updatedSettings = doGet("/api/user/settings", JsonNode.class); - expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\": {\"E\":76, \"F\": 92}}}"); + expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\": {\"E\":76, \"F\": 92}}}"); Assert.assertEquals(expectedSettings, updatedSettings); patchedSettings = mapper.readTree("{\"B.D.E\": 100}"); doPut("/api/user/settings", patchedSettings); updatedSettings = doGet("/api/user/settings", JsonNode.class); - expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":false, \"D\": {\"E\":100, \"F\": 92}}}"); + expectedSettings = mapper.readTree("{\"A\":11, \"B\":{\"C\":false, \"D\": {\"E\":100, \"F\": 92}}}"); Assert.assertEquals(expectedSettings, updatedSettings); } @Test - public void testShouldNotUpdateUserSettingsWithNoExistingPath() throws Exception { + public void testShouldCreatePathIfNotExists() throws Exception { loginCustomerUser(); - JsonNode userSettings = mapper.readTree("{\"A\":5, \"B\":{\"C\":true, \"D\":\"stringValue\"}}"); + JsonNode userSettings = mapper.readTree("{\"A\":5}"); JsonNode savedSettings = doPost("/api/user/settings", userSettings, JsonNode.class); Assert.assertEquals(userSettings, savedSettings); - JsonNode newSettings = mapper.readTree("{\"A.E\":10}"); - doPut("/api/user/settings", newSettings).andExpect(status().isBadRequest()); + JsonNode newSettings = mapper.readTree("{\"B\":{\"C\": 10}}"); + doPut("/api/user/settings", newSettings); + JsonNode updatedSettings = doGet("/api/user/settings", JsonNode.class); + JsonNode expectedSettings = mapper.readTree("{\"A\":5, \"B\":{\"C\": 10}}"); + Assert.assertEquals(expectedSettings, updatedSettings); + + newSettings = mapper.readTree("{\"B.K\":true}"); + doPut("/api/user/settings", newSettings); + updatedSettings = doGet("/api/user/settings", JsonNode.class); + expectedSettings = mapper.readTree("{\"A\":5, \"B\":{\"C\": 10, \"K\": true}}"); + Assert.assertEquals(expectedSettings, updatedSettings); + + newSettings = mapper.readTree("{\"B\":{}}"); + doPut("/api/user/settings", newSettings); + updatedSettings = doGet("/api/user/settings", JsonNode.class); + expectedSettings = mapper.readTree("{\"A\":5, \"B\":{}}"); + Assert.assertEquals(expectedSettings, updatedSettings); + + newSettings = mapper.readTree("{\"F.G\":\"string\"}"); + doPut("/api/user/settings", newSettings); + updatedSettings = doGet("/api/user/settings", JsonNode.class); + expectedSettings = mapper.readTree("{\"A\":5, \"B\":{}, \"F\":{\"G\": \"string\"}}"); + Assert.assertEquals(expectedSettings, updatedSettings); + + newSettings = mapper.readTree("{\"F\":{\"G\":\"string2\"}}"); + doPut("/api/user/settings", newSettings); + updatedSettings = doGet("/api/user/settings", JsonNode.class); + expectedSettings = mapper.readTree("{\"A\":5, \"B\":{}, \"F\":{\"G\": \"string2\"}}"); + Assert.assertEquals(expectedSettings, updatedSettings); } @Test diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsServiceImpl.java index a87d53e49d..593a8846cc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsServiceImpl.java @@ -37,6 +37,7 @@ import org.thingsboard.server.dao.exception.DataValidationException; import java.util.ArrayList; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -135,7 +136,7 @@ public class UserSettingsServiceImpl extends AbstractCachedService fieldNames = updateNode.fieldNames(); while (fieldNames.hasNext()) { String fieldName = fieldNames.next(); - validatePathExists(dcOldSettings, fieldName); + createPathIfNotExists(dcOldSettings, "$."+ fieldName); dcOldSettings = dcOldSettings.set("$." + fieldName, getValueByNodeType(updateNode.get(fieldName))); } try { @@ -145,11 +146,15 @@ public class UserSettingsServiceImpl extends AbstractCachedService()); + return path; } }