From a25e328b7c6c7bf503f0b137f13e600895abe729 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Sat, 11 Feb 2023 00:20:00 +0200 Subject: [PATCH] fixed update settings method --- .../server/controller/UserController.java | 31 ++++++---- .../controller/BaseUserControllerTest.java | 31 +++++----- .../server/dao/user/UserSettingsService.java | 5 +- .../dao/user/UserSettingsServiceImpl.java | 58 +++++++++++++------ 4 files changed, 80 insertions(+), 45 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index ed55bcf324..a38ef27d62 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -92,7 +92,8 @@ import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LI public class UserController extends BaseController { public static final String USER_ID = "userId"; - public static final String JSON_PATHS = "jsonPaths"; + public static final String PATH = "path"; + public static final String PATHS = "paths"; public static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!"; public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; @@ -406,13 +407,21 @@ public class UserController extends BaseController { "{A:10, B:{C:10, D:5}}, E:6") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PutMapping(value = "/user/settings") - public JsonNode putUserSettings(@RequestBody JsonNode settings) throws ThingsboardException { + public void putUserSettings(@RequestBody JsonNode settings) throws ThingsboardException { SecurityUser currentUser = getCurrentUser(); + userSettingsService.updateUserSettings(currentUser.getTenantId(), currentUser.getId(), settings); + } - UserSettings userSettings = new UserSettings(); - userSettings.setSettings(settings); - userSettings.setUserId(currentUser.getId()); - return userSettingsService.updateUserSettings(currentUser.getTenantId(), userSettings).getSettings(); + @ApiOperation(value = "Update user settings (saveUserSettings)", + notes = "Update user settings for authorized user. Only specified json elements will be updated." + + "Example: you have such settings: {A:5, B:{C:10, D:5}}. Updating it with {A:10, E:6} will result in" + + "{A:10, B:{C:10, D:5}}, E:6") + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @PutMapping(value = "/user/settings/{path}") + public void putUserSettings(@ApiParam(value = PATH) + @PathVariable(PATH) String path, @RequestBody JsonNode settings) throws ThingsboardException { + SecurityUser currentUser = getCurrentUser(); + userSettingsService.updateUserSettings(currentUser.getTenantId(), currentUser.getId(), path, settings); } @ApiOperation(value = "Get user settings (getUserSettings)", @@ -430,12 +439,12 @@ public class UserController extends BaseController { notes = "Delete user settings by specifying list of json element xpaths. \n " + "Example: to delete B and C element in { \"A\": {\"B\": 5}, \"C\": 15} send A.B,C in jsonPaths request parameter" ) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @RequestMapping(value = "/user/settings/{jsonPaths}", method = RequestMethod.DELETE) - public void deleteUserSettings( @ApiParam(value = JSON_PATHS) - @PathVariable(JSON_PATHS) String jsonPaths) throws ThingsboardException { - checkParameter(USER_ID, jsonPaths); + @RequestMapping(value = "/user/settings/{paths}", method = RequestMethod.DELETE) + public void deleteUserSettings(@ApiParam(value = PATHS) + @PathVariable(PATHS) String paths) throws ThingsboardException { + checkParameter(USER_ID, paths); SecurityUser currentUser = getCurrentUser(); - userSettingsService.deleteUserSettings(currentUser.getTenantId(), currentUser.getId(), Arrays.asList(jsonPaths.split(","))); + userSettingsService.deleteUserSettings(currentUser.getTenantId(), currentUser.getId(), Arrays.asList(paths.split(","))); } } 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 81111d2de4..4679ee4411 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java @@ -759,30 +759,33 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { public void testUpdateUserSettings() throws Exception { loginCustomerUser(); - JsonNode userSettings = mapper.readTree("{\"A\":5, \"B\":10, \"E\":18}"); + JsonNode userSettings = mapper.readTree("{\"A\":5, \"B\":{\"C\":5, \"D\":5}}"); JsonNode savedSettings = doPost("/api/user/settings", userSettings, JsonNode.class); Assert.assertEquals(userSettings, savedSettings); - JsonNode newSettings = mapper.readTree("{\"A\":10, \"B\":10, \"C\":{\"D\": 16}}"); - JsonNode updatedSettings = doPut("/api/user/settings", newSettings, JsonNode.class); - JsonNode expectedSettings = mapper.readTree("{\"A\":10, \"B\":10, \"C\":{\"D\": 16}, \"E\":18}"); + JsonNode newSettings = mapper.readTree("{\"A\":10}"); + doPut("/api/user/settings", newSettings); + JsonNode updatedSettings = doGet("/api/user/settings", JsonNode.class); + JsonNode expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"C\":5, \"D\":5}}"); Assert.assertEquals(expectedSettings, updatedSettings); - JsonNode patchedSettings = mapper.readTree("\"C\":{\"E\": 22}}"); - updatedSettings = doPut("/api/user/settings", patchedSettings, JsonNode.class); - expectedSettings = mapper.readTree("{\"A\":10, \"B\":10, \"C\":{\"E\": 22}, \"E\":18}"); + JsonNode patchedSettings = mapper.readTree("{\"B\":{\"E\": 22}}"); + doPut("/api/user/settings", patchedSettings); + updatedSettings = doGet("/api/user/settings", JsonNode.class); + expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"E\": 22}}"); Assert.assertEquals(expectedSettings, updatedSettings); - patchedSettings = mapper.readTree("\"C.D\": 16}}"); - updatedSettings = doPut("/api/user/settings", patchedSettings, JsonNode.class); - expectedSettings = mapper.readTree("{\"A\":10, \"B\":10, \"C\":{\"D\": 16, \"E\": 22}, \"E\":18}"); + patchedSettings = mapper.readTree("{\"I\": 56}"); + doPut("/api/user/settings/B.E", patchedSettings); + updatedSettings = doGet("/api/user/settings", JsonNode.class); + expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"E\": {\"I\":56}}}"); Assert.assertEquals(expectedSettings, updatedSettings); - patchedSettings = mapper.readTree("\"C.D\": {\"A\":5}}}"); - updatedSettings = doPut("/api/user/settings", patchedSettings, JsonNode.class); - expectedSettings = mapper.readTree("{\"A\":10, \"B\":10, \"C\":{\"D\": {\"A\":5}, \"E\": 22}, \"E\":18}"); + patchedSettings = mapper.readTree("{\"I\": 76, \"F\": 92}"); + doPut("/api/user/settings/B.E", patchedSettings); + updatedSettings = doGet("/api/user/settings", JsonNode.class); + expectedSettings = mapper.readTree("{\"A\":10, \"B\":{\"E\": {\"I\":76, \"F\": 92}}}"); Assert.assertEquals(expectedSettings, updatedSettings); - } @Test diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserSettingsService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserSettingsService.java index 30f9b9334a..0b2c6f5aef 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserSettingsService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserSettingsService.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.dao.user; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.security.UserSettings; @@ -23,7 +25,8 @@ import java.util.List; public interface UserSettingsService { - UserSettings updateUserSettings(TenantId tenantId, UserSettings userSettings); + void updateUserSettings(TenantId tenantId, UserId userId, JsonNode settings); + void updateUserSettings(TenantId tenantId, UserId userId, String path, JsonNode settings); UserSettings saveUserSettings(TenantId tenantId, UserSettings userSettings); 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 dc1e18352c..0c41589b95 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 @@ -15,6 +15,8 @@ */ package org.thingsboard.server.dao.user; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -33,6 +35,7 @@ import org.thingsboard.server.dao.entity.AbstractCachedService; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; import static org.thingsboard.server.dao.service.Validator.validateId; @@ -51,13 +54,37 @@ public class UserSettingsServiceImpl extends AbstractCachedService>(){})); + try { + newUserSettings.setSettings(new ObjectMapper().readValue(dcSettings.jsonString(), ObjectNode.class)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + doSaveUserSettings(tenantId, newUserSettings); } @Override @@ -78,11 +105,11 @@ public class UserSettingsServiceImpl extends AbstractCachedService fieldNames = updateNode.fieldNames(); while (fieldNames.hasNext()) { String fieldName = fieldNames.next(); - JsonNode jsonNode = mainNode.get(fieldName); - if (jsonNode != null && jsonNode.isObject()) { - merge(jsonNode, updateNode.get(fieldName)); - } else { - if (mainNode instanceof ObjectNode) { - JsonNode value = updateNode.get(fieldName); - ((ObjectNode) mainNode).set(fieldName, value); - } - } + JsonNode value = updateNode.get(fieldName); + ((ObjectNode) mainNode).set(fieldName, value); } return mainNode; }