diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 23331d95f4..737e6d54d5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -117,7 +117,7 @@ public class WidgetsBundleController extends BaseController { checkParameter("widgetsBundleId", strWidgetsBundleId); WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); WidgetsBundle widgetsBundle = checkWidgetsBundleId(widgetsBundleId, Operation.DELETE); - tbWidgetsBundleService.delete(widgetsBundle); + tbWidgetsBundleService.delete(widgetsBundle, getCurrentUser()); } @ApiOperation(value = "Get Widget Bundles (getWidgetsBundles)", diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java index ffd667bfec..7cc150b746 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/DefaultWidgetsBundleService.java @@ -17,9 +17,10 @@ package org.thingsboard.server.service.entitiy.widgets.bundle; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.edge.EdgeEventActionType; -import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -34,17 +35,31 @@ public class DefaultWidgetsBundleService extends AbstractTbEntityService impleme @Override public WidgetsBundle save(WidgetsBundle widgetsBundle, User user) throws Exception { - WidgetsBundle savedWidgetsBundle = checkNotNull(widgetsBundleService.saveWidgetsBundle(widgetsBundle)); - autoCommit(user, savedWidgetsBundle.getId()); - notificationEntityService.notifySendMsgToEdgeService(widgetsBundle.getTenantId(), savedWidgetsBundle.getId(), - widgetsBundle.getId() == null ? EdgeEventActionType.ADDED : EdgeEventActionType.UPDATED); - return savedWidgetsBundle; + ActionType actionType = widgetsBundle.getId() == null ? ActionType.ADDED : ActionType.UPDATED; + TenantId tenantId = widgetsBundle.getTenantId(); + try { + WidgetsBundle savedWidgetsBundle = checkNotNull(widgetsBundleService.saveWidgetsBundle(widgetsBundle)); + autoCommit(user, savedWidgetsBundle.getId()); + notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, savedWidgetsBundle.getId(), + savedWidgetsBundle, user, actionType, true, null); + return savedWidgetsBundle; + } catch (Exception e) { + notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.WIDGETS_BUNDLE), widgetsBundle, actionType, user, e); + throw e; + } } @Override - public void delete(WidgetsBundle widgetsBundle) throws ThingsboardException { - widgetsBundleService.deleteWidgetsBundle(widgetsBundle.getTenantId(), widgetsBundle.getId()); - notificationEntityService.notifySendMsgToEdgeService(widgetsBundle.getTenantId(), widgetsBundle.getId(), - EdgeEventActionType.DELETED); + public void delete(WidgetsBundle widgetsBundle, User user) { + TenantId tenantId = widgetsBundle.getTenantId(); + try { + widgetsBundleService.deleteWidgetsBundle(widgetsBundle.getTenantId(), widgetsBundle.getId()); + notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, null, widgetsBundle.getId(), widgetsBundle, + user, ActionType.DELETED, true, null); + } catch (Exception e) { + notificationEntityService.logEntityAction(tenantId, emptyId(EntityType.WIDGETS_BUNDLE), + ActionType.DELETED, user, e, widgetsBundle.getId()); + throw e; + } } } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/TbWidgetsBundleService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/TbWidgetsBundleService.java index 446010b61c..d60bc66d66 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/TbWidgetsBundleService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/widgets/bundle/TbWidgetsBundleService.java @@ -15,13 +15,8 @@ */ package org.thingsboard.server.service.entitiy.widgets.bundle; -import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.widget.WidgetsBundle; +import org.thingsboard.server.service.entitiy.SimpleTbEntityService; -public interface TbWidgetsBundleService { - - WidgetsBundle save(WidgetsBundle entity, User currentUser) throws Exception; - - void delete(WidgetsBundle entity) throws ThingsboardException; +public interface TbWidgetsBundleService extends SimpleTbEntityService { } diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java index 5dee2b69b0..6e181044c7 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java @@ -20,6 +20,7 @@ import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.info.DeviceActivityNotificationInfo; @@ -41,6 +42,9 @@ public class DeviceActivityTriggerProcessor implements RuleEngineMsgNotification @Override public boolean matchesFilter(RuleEngineMsgTrigger trigger, DeviceActivityNotificationRuleTriggerConfig triggerConfig) { + if (trigger.getMsg().getOriginator().getEntityType() != EntityType.DEVICE) { + return false; + } DeviceEvent event = trigger.getMsg().getType().equals(DataConstants.ACTIVITY_EVENT) ? DeviceEvent.ACTIVE : DeviceEvent.INACTIVE; if (!triggerConfig.getNotifyOn().contains(event)) { return false; diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 1c1d2df504..2e0a626b6c 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -607,6 +607,7 @@ spring: username: "${SPRING_DATASOURCE_USERNAME:postgres}" password: "${SPRING_DATASOURCE_PASSWORD:postgres}" hikari: + leakDetectionThreshold: "${SPRING_DATASOURCE_HIKARI_LEAK_DETECTION_THRESHOLD:0}" maximumPoolSize: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}" registerMbeans: "${SPRING_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # true - enable MBean to diagnose pools state via JMX @@ -621,6 +622,7 @@ audit-log: "device": "${AUDIT_LOG_MASK_DEVICE:W}" "asset": "${AUDIT_LOG_MASK_ASSET:W}" "dashboard": "${AUDIT_LOG_MASK_DASHBOARD:W}" + "widgets_bundle": "${AUDIT_LOG_MASK_WIDGETS_BUNDLE:W}" "customer": "${AUDIT_LOG_MASK_CUSTOMER:W}" "user": "${AUDIT_LOG_MASK_USER:W}" "rule_chain": "${AUDIT_LOG_MASK_RULE_CHAIN:W}" diff --git a/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java index ae96ee74a9..ee341fe284 100644 --- a/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/WidgetsBundleControllerTest.java @@ -21,16 +21,15 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; -import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.audit.ActionType; -import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.widget.WidgetsBundle; +import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.service.DaoSqlTest; import java.util.ArrayList; @@ -39,7 +38,6 @@ import java.util.List; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.thingsboard.server.dao.model.ModelConstants.SYSTEM_TENANT; @DaoSqlTest public class WidgetsBundleControllerTest extends AbstractControllerTest { @@ -72,7 +70,7 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { public void afterTest() throws Exception { loginSysAdmin(); - doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) + doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) .andExpect(status().isOk()); } @@ -81,14 +79,14 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { WidgetsBundle widgetsBundle = new WidgetsBundle(); widgetsBundle.setTitle("My widgets bundle"); - Mockito.reset(tbClusterService); + Mockito.reset(tbClusterService, auditLogService); WidgetsBundle savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); - testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(savedWidgetsBundle, savedWidgetsBundle, - savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), - ActionType.ADDED, ActionType.ADDED, 0, 1, 0); - Mockito.reset(tbClusterService); + testNotifyEntityAllOneTime(savedWidgetsBundle, savedWidgetsBundle.getId(), savedWidgetsBundle.getId(), savedTenant.getId(), + tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED); + + Mockito.reset(tbClusterService, auditLogService); Assert.assertNotNull(savedWidgetsBundle); Assert.assertNotNull(savedWidgetsBundle.getId()); @@ -103,25 +101,26 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { WidgetsBundle foundWidgetsBundle = doGet("/api/widgetsBundle/" + savedWidgetsBundle.getId().getId().toString(), WidgetsBundle.class); Assert.assertEquals(foundWidgetsBundle.getTitle(), savedWidgetsBundle.getTitle()); - testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(savedWidgetsBundle, savedWidgetsBundle, - savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), - ActionType.UPDATED, ActionType.UPDATED, 0, 1, 0); + testNotifyEntityAllOneTime(savedWidgetsBundle, savedWidgetsBundle.getId(), savedWidgetsBundle.getId(), savedTenant.getId(), + tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED); } - @Test - public void testSaveWidgetBundleWithViolationOfLengthValidation() throws Exception { - WidgetsBundle widgetsBundle = new WidgetsBundle(); - widgetsBundle.setTitle(StringUtils.randomAlphabetic(300)); + @Test + public void testSaveWidgetBundleWithViolationOfLengthValidation() throws Exception { + WidgetsBundle widgetsBundle = new WidgetsBundle(); + widgetsBundle.setTitle(StringUtils.randomAlphabetic(300)); - Mockito.reset(tbClusterService); + Mockito.reset(tbClusterService, auditLogService); - String msgError = msgErrorFieldLength("title"); - doPost("/api/widgetsBundle", widgetsBundle) - .andExpect(status().isBadRequest()) - .andExpect(statusReason(containsString(msgError))); + String msgError = msgErrorFieldLength("title"); + doPost("/api/widgetsBundle", widgetsBundle) + .andExpect(status().isBadRequest()) + .andExpect(statusReason(containsString(msgError))); - testNotifyEntityNever(widgetsBundle.getId(), widgetsBundle); - } + testNotifyEntityEqualsOneTimeServiceNeverError(widgetsBundle, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, + new DataValidationException("Validation error: title length must be equal or less than 255")); + } @Test public void testUpdateWidgetsBundleFromDifferentTenant() throws Exception { @@ -131,7 +130,7 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { loginDifferentTenant(); - Mockito.reset(tbClusterService); + Mockito.reset(tbClusterService, auditLogService); doPost("/api/widgetsBundle", savedWidgetsBundle) .andExpect(status().isForbidden()) @@ -157,26 +156,25 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { WidgetsBundle widgetsBundle = new WidgetsBundle(); widgetsBundle.setTitle("My widgets bundle"); - Mockito.reset(tbClusterService, auditLogService); - WidgetsBundle savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); - doDelete("/api/widgetsBundle/"+savedWidgetsBundle.getId().getId().toString()) + Mockito.reset(tbClusterService, auditLogService); + + doDelete("/api/widgetsBundle/" + savedWidgetsBundle.getId().getId().toString()) .andExpect(status().isOk()); String savedWidgetsBundleIdStr = savedWidgetsBundle.getId().getId().toString(); + + testNotifyEntityAllOneTime(savedWidgetsBundle, savedWidgetsBundle.getId(), savedWidgetsBundle.getId(), savedTenant.getId(), + tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.DELETED); + doGet("/api/widgetsBundle/" + savedWidgetsBundleIdStr) .andExpect(status().isNotFound()) .andExpect(statusReason(containsString(msgErrorNoFound("Widgets bundle", savedWidgetsBundleIdStr)))); - - testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(savedWidgetsBundle, savedWidgetsBundle, - savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), - ActionType.DELETED, ActionType.DELETED, 0, 1, 0); } @Test public void testSaveWidgetsBundleWithEmptyTitle() throws Exception { - Mockito.reset(tbClusterService, auditLogService); WidgetsBundle widgetsBundle = new WidgetsBundle(); @@ -184,7 +182,9 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { .andExpect(status().isBadRequest()) .andExpect(statusReason(containsString("Widgets bundle title " + msgErrorShouldBeSpecified))); - testNotifyEntityNever(widgetsBundle.getId(), widgetsBundle); + testNotifyEntityEqualsOneTimeServiceNeverError(widgetsBundle, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, + new DataValidationException("Widgets bundle title should be specified!")); } @Test @@ -194,13 +194,14 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { WidgetsBundle savedWidgetsBundle = doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class); savedWidgetsBundle.setAlias("new_alias"); - Mockito.clearInvocations(tbClusterService); + Mockito.reset(tbClusterService, auditLogService); doPost("/api/widgetsBundle", savedWidgetsBundle) .andExpect(status().isBadRequest()) .andExpect(statusReason(containsString("Update of widgets bundle alias is prohibited"))); - - testNotifyEntityNever(savedWidgetsBundle.getId(), savedWidgetsBundle); + testNotifyEntityEqualsOneTimeServiceNeverError(savedWidgetsBundle, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED, + new DataValidationException("Update of widgets bundle alias is prohibited!")); } @Test @@ -209,22 +210,17 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { login(tenantAdmin.getEmail(), "testPassword1"); List sysWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference<>(){}); - - Mockito.reset(tbClusterService); + new TypeReference<>() { + }); int cntEntity = 73; List widgetsBundles = new ArrayList<>(); - for (int i=0;i loadedWidgetsBundles = new ArrayList<>(); @@ -232,7 +228,8 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { PageData pageData; do { pageData = doGetTypedWithPageLink("/api/widgetsBundles?", - new TypeReference<>(){}, pageLink); + new TypeReference<>() { + }, pageLink); loadedWidgetsBundles.addAll(pageData.getData()); if (pageData.hasNext()) { pageLink = pageLink.nextPageLink(); @@ -251,13 +248,14 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { loginSysAdmin(); List sysWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference<>(){}); + new TypeReference<>() { + }); int cntEntity = 120; List createdWidgetsBundles = new ArrayList<>(); - for (int i=0;i pageData; do { pageData = doGetTypedWithPageLink("/api/widgetsBundles?", - new TypeReference<>(){}, pageLink); + new TypeReference<>() { + }, pageLink); loadedWidgetsBundles.addAll(pageData.getData()); if (pageData.hasNext()) { pageLink = pageLink.nextPageLink(); @@ -281,22 +280,17 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { Assert.assertEquals(widgetsBundles, loadedWidgetsBundles); - Mockito.reset(tbClusterService); - for (WidgetsBundle widgetsBundle : createdWidgetsBundles) { - doDelete("/api/widgetsBundle/"+widgetsBundle.getId().getId().toString()) + doDelete("/api/widgetsBundle/" + widgetsBundle.getId().getId().toString()) .andExpect(status().isOk()); } - testNotifyManyEntityManyTimeMsgToEdgeServiceEntityEqAny(new WidgetsBundle(), new WidgetsBundle(), - SYSTEM_TENANT, (CustomerId) createEntityId_NULL_UUID(new Customer()), null, SYS_ADMIN_EMAIL, - ActionType.DELETED, ActionType.DELETED, 0, cntEntity, 0); - pageLink = new PageLink(17); loadedWidgetsBundles.clear(); do { pageData = doGetTypedWithPageLink("/api/widgetsBundles?", - new TypeReference>(){}, pageLink); + new TypeReference>() { + }, pageLink); loadedWidgetsBundles.addAll(pageData.getData()); if (pageData.hasNext()) { pageLink = pageLink.nextPageLink(); @@ -316,19 +310,21 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { login(tenantAdmin.getEmail(), "testPassword1"); List sysWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference>(){}); + new TypeReference>() { + }); List widgetsBundles = new ArrayList<>(); - for (int i=0;i<73;i++) { + for (int i = 0; i < 73; i++) { WidgetsBundle widgetsBundle = new WidgetsBundle(); - widgetsBundle.setTitle("Widgets bundle"+i); + widgetsBundle.setTitle("Widgets bundle" + i); widgetsBundles.add(doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class)); } widgetsBundles.addAll(sysWidgetsBundles); List loadedWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference<>(){}); + new TypeReference<>() { + }); Collections.sort(widgetsBundles, idComparator); Collections.sort(loadedWidgetsBundles, idComparator); @@ -343,12 +339,13 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { List sysWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference<>(){}); + new TypeReference<>() { + }); List createdSystemWidgetsBundles = new ArrayList<>(); - for (int i=0;i<82;i++) { + for (int i = 0; i < 82; i++) { WidgetsBundle widgetsBundle = new WidgetsBundle(); - widgetsBundle.setTitle("Sys widgets bundle"+i); + widgetsBundle.setTitle("Sys widgets bundle" + i); createdSystemWidgetsBundles.add(doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class)); } @@ -360,14 +357,15 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { login(tenantAdmin.getEmail(), "testPassword1"); - for (int i=0;i<127;i++) { + for (int i = 0; i < 127; i++) { WidgetsBundle widgetsBundle = new WidgetsBundle(); - widgetsBundle.setTitle("Tenant widgets bundle"+i); + widgetsBundle.setTitle("Tenant widgets bundle" + i); widgetsBundles.add(doPost("/api/widgetsBundle", widgetsBundle, WidgetsBundle.class)); } List loadedWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference>(){}); + new TypeReference>() { + }); Collections.sort(widgetsBundles, idComparator); Collections.sort(loadedWidgetsBundles, idComparator); @@ -377,7 +375,8 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { loginSysAdmin(); loadedWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference>(){}); + new TypeReference<>() { + }); Collections.sort(systemWidgetsBundles, idComparator); Collections.sort(loadedWidgetsBundles, idComparator); @@ -385,12 +384,13 @@ public class WidgetsBundleControllerTest extends AbstractControllerTest { Assert.assertEquals(systemWidgetsBundles, loadedWidgetsBundles); for (WidgetsBundle widgetsBundle : createdSystemWidgetsBundles) { - doDelete("/api/widgetsBundle/"+widgetsBundle.getId().getId().toString()) + doDelete("/api/widgetsBundle/" + widgetsBundle.getId().getId().toString()) .andExpect(status().isOk()); } loadedWidgetsBundles = doGetTyped("/api/widgetsBundles?", - new TypeReference<>(){}); + new TypeReference<>() { + }); Collections.sort(sysWidgetsBundles, idComparator); Collections.sort(loadedWidgetsBundles, idComparator); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 122716181c..4898bd6525 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -58,9 +58,8 @@ public class ModelConstants { public static final String LAST_UPDATE_TS_COLUMN = "last_update_ts"; /** - * Cassandra user constants. + * User constants. */ - public static final String USER_COLUMN_FAMILY_NAME = "user"; public static final String USER_PG_HIBERNATE_COLUMN_FAMILY_NAME = "tb_user"; public static final String USER_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String USER_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; @@ -70,12 +69,8 @@ public class ModelConstants { public static final String USER_LAST_NAME_PROPERTY = "last_name"; public static final String USER_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; - public static final String USER_BY_EMAIL_COLUMN_FAMILY_NAME = "user_by_email"; - public static final String USER_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "user_by_tenant_and_search_text"; - public static final String USER_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "user_by_customer_and_search_text"; - /** - * Cassandra user_credentials constants. + * User_credentials constants. */ public static final String USER_CREDENTIALS_COLUMN_FAMILY_NAME = "user_credentials"; public static final String USER_CREDENTIALS_USER_ID_PROPERTY = USER_ID_PROPERTY; @@ -85,10 +80,6 @@ public class ModelConstants { public static final String USER_CREDENTIALS_RESET_TOKEN_PROPERTY = "reset_token"; public static final String USER_CREDENTIALS_ADDITIONAL_PROPERTY = "additional_info"; - public static final String USER_CREDENTIALS_BY_USER_COLUMN_FAMILY_NAME = "user_credentials_by_user"; - public static final String USER_CREDENTIALS_BY_ACTIVATE_TOKEN_COLUMN_FAMILY_NAME = "user_credentials_by_activate_token"; - public static final String USER_CREDENTIALS_BY_RESET_TOKEN_COLUMN_FAMILY_NAME = "user_credentials_by_reset_token"; - /** * User settings constants. */ @@ -98,7 +89,7 @@ public class ModelConstants { public static final String USER_SETTINGS_SETTINGS = "settings"; /** - * Cassandra admin_settings constants. + * Admin_settings constants. */ public static final String ADMIN_SETTINGS_COLUMN_FAMILY_NAME = "admin_settings"; @@ -106,10 +97,8 @@ public class ModelConstants { public static final String ADMIN_SETTINGS_KEY_PROPERTY = "key"; public static final String ADMIN_SETTINGS_JSON_VALUE_PROPERTY = "json_value"; - public static final String ADMIN_SETTINGS_BY_KEY_COLUMN_FAMILY_NAME = "admin_settings_by_key"; - /** - * Cassandra contact constants. + * Contact constants. */ public static final String COUNTRY_PROPERTY = "country"; public static final String STATE_PROPERTY = "state"; @@ -121,7 +110,7 @@ public class ModelConstants { public static final String EMAIL_PROPERTY = "email"; /** - * Cassandra tenant constants. + * Tenant constants. */ public static final String TENANT_COLUMN_FAMILY_NAME = "tenant"; public static final String TENANT_TITLE_PROPERTY = TITLE_PROPERTY; @@ -129,8 +118,6 @@ public class ModelConstants { public static final String TENANT_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; public static final String TENANT_TENANT_PROFILE_ID_PROPERTY = "tenant_profile_id"; - public static final String TENANT_BY_REGION_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "tenant_by_region_and_search_text"; - /** * Tenant profile constants. */ @@ -139,25 +126,20 @@ public class ModelConstants { public static final String TENANT_PROFILE_PROFILE_DATA_PROPERTY = "profile_data"; public static final String TENANT_PROFILE_DESCRIPTION_PROPERTY = "description"; public static final String TENANT_PROFILE_IS_DEFAULT_PROPERTY = "is_default"; - public static final String TENANT_PROFILE_ISOLATED_TB_CORE = "isolated_tb_core"; public static final String TENANT_PROFILE_ISOLATED_TB_RULE_ENGINE = "isolated_tb_rule_engine"; /** - * Cassandra customer constants. + * Customer constants. */ public static final String CUSTOMER_COLUMN_FAMILY_NAME = "customer"; public static final String CUSTOMER_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String CUSTOMER_TITLE_PROPERTY = TITLE_PROPERTY; public static final String CUSTOMER_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; - public static final String CUSTOMER_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "customer_by_tenant_and_search_text"; - public static final String CUSTOMER_BY_TENANT_AND_TITLE_VIEW_NAME = "customer_by_tenant_and_title"; - /** - * Cassandra device constants. + * Device constants. */ public static final String DEVICE_COLUMN_FAMILY_NAME = "device"; - public static final String DEVICE_FAMILY_NAME = "device"; public static final String DEVICE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String DEVICE_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; public static final String DEVICE_NAME_PROPERTY = "name"; @@ -174,13 +156,6 @@ public class ModelConstants { public static final String DEVICE_DEVICE_PROFILE_NAME_PROPERTY = "device_profile_name"; public static final String DEVICE_ACTIVE_PROPERTY = "active"; - public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; - public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text"; - public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text"; - public static final String DEVICE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_by_type_and_search_text"; - public static final String DEVICE_BY_TENANT_AND_NAME_VIEW_NAME = "device_by_tenant_and_name"; - public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant"; - public static final String DEVICE_INFO_VIEW_COLUMN_FAMILY_NAME = "device_info_view"; /** @@ -198,7 +173,6 @@ public class ModelConstants { public static final String DEVICE_PROFILE_IS_DEFAULT_PROPERTY = "is_default"; public static final String DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY = "default_rule_chain_id"; public static final String DEVICE_PROFILE_DEFAULT_DASHBOARD_ID_PROPERTY = "default_dashboard_id"; - public static final String DEVICE_PROFILE_DEFAULT_QUEUE_ID_PROPERTY = "default_queue_id"; public static final String DEVICE_PROFILE_DEFAULT_QUEUE_NAME_PROPERTY = "default_queue_name"; public static final String DEVICE_PROFILE_PROVISION_DEVICE_KEY = "provision_device_key"; public static final String DEVICE_PROFILE_FIRMWARE_ID_PROPERTY = "firmware_id"; @@ -220,44 +194,28 @@ public class ModelConstants { public static final String ASSET_PROFILE_DEFAULT_EDGE_RULE_CHAIN_ID_PROPERTY = "default_edge_rule_chain_id"; /** - * Cassandra entityView constants. + * Entity view constants. */ public static final String ENTITY_VIEW_TABLE_FAMILY_NAME = "entity_view"; public static final String ENTITY_VIEW_ENTITY_ID_PROPERTY = ENTITY_ID_COLUMN; public static final String ENTITY_VIEW_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String ENTITY_VIEW_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; public static final String ENTITY_VIEW_NAME_PROPERTY = DEVICE_NAME_PROPERTY; - public static final String ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_CF = "entity_view_by_tenant_and_customer"; - public static final String ENTITY_VIEW_BY_TENANT_AND_CUSTOMER_AND_TYPE_CF = "entity_view_by_tenant_and_customer_and_type"; - public static final String ENTITY_VIEW_BY_TENANT_AND_ENTITY_ID_CF = "entity_view_by_tenant_and_entity_id"; public static final String ENTITY_VIEW_KEYS_PROPERTY = "keys"; - public static final String ENTITY_VIEW_TYPE_PROPERTY = "type"; public static final String ENTITY_VIEW_START_TS_PROPERTY = "start_ts"; public static final String ENTITY_VIEW_END_TS_PROPERTY = "end_ts"; public static final String ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; - public static final String ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_CF = "entity_view_by_tenant_and_search_text"; - public static final String ENTITY_VIEW_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_CF = "entity_view_by_tenant_by_type_and_search_text"; - public static final String ENTITY_VIEW_BY_TENANT_AND_NAME = "entity_view_by_tenant_and_name"; /** - * Cassandra audit log constants. + * Audit log constants. */ public static final String AUDIT_LOG_COLUMN_FAMILY_NAME = "audit_log"; - - public static final String AUDIT_LOG_BY_ENTITY_ID_CF = "audit_log_by_entity_id"; - public static final String AUDIT_LOG_BY_CUSTOMER_ID_CF = "audit_log_by_customer_id"; - public static final String AUDIT_LOG_BY_USER_ID_CF = "audit_log_by_user_id"; - public static final String AUDIT_LOG_BY_TENANT_ID_CF = "audit_log_by_tenant_id"; - public static final String AUDIT_LOG_BY_TENANT_ID_PARTITIONS_CF = "audit_log_by_tenant_id_partitions"; - - public static final String AUDIT_LOG_ID_PROPERTY = ID_PROPERTY; public static final String AUDIT_LOG_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String AUDIT_LOG_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; public static final String AUDIT_LOG_ENTITY_TYPE_PROPERTY = ENTITY_TYPE_PROPERTY; public static final String AUDIT_LOG_ENTITY_ID_PROPERTY = ENTITY_ID_COLUMN; public static final String AUDIT_LOG_ENTITY_NAME_PROPERTY = "entity_name"; public static final String AUDIT_LOG_USER_ID_PROPERTY = USER_ID_PROPERTY; - public static final String AUDIT_LOG_PARTITION_PROPERTY = "partition"; public static final String AUDIT_LOG_USER_NAME_PROPERTY = "user_name"; public static final String AUDIT_LOG_ACTION_TYPE_PROPERTY = "action_type"; public static final String AUDIT_LOG_ACTION_DATA_PROPERTY = "action_data"; @@ -265,7 +223,7 @@ public class ModelConstants { public static final String AUDIT_LOG_ACTION_FAILURE_DETAILS_PROPERTY = "action_failure_details"; /** - * Cassandra asset constants. + * Asset constants. */ public static final String ASSET_COLUMN_FAMILY_NAME = "asset"; public static final String ASSET_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; @@ -277,23 +235,8 @@ public class ModelConstants { public static final String ASSET_ASSET_PROFILE_ID_PROPERTY = "asset_profile_id"; - public static final String ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_and_search_text"; - public static final String ASSET_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_tenant_by_type_and_search_text"; - public static final String ASSET_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_and_search_text"; - public static final String ASSET_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "asset_by_customer_by_type_and_search_text"; - public static final String ASSET_BY_TENANT_AND_NAME_VIEW_NAME = "asset_by_tenant_and_name"; - public static final String ASSET_TYPES_BY_TENANT_VIEW_NAME = "asset_types_by_tenant"; - - /** - * Cassandra entity_subtype constants. - */ - public static final String ENTITY_SUBTYPE_COLUMN_FAMILY_NAME = "entity_subtype"; - public static final String ENTITY_SUBTYPE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; - public static final String ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY = ENTITY_TYPE_PROPERTY; - public static final String ENTITY_SUBTYPE_TYPE_PROPERTY = "type"; - /** - * Cassandra alarm constants. + * Alarm constants. */ public static final String ENTITY_ALARM_COLUMN_FAMILY_NAME = "entity_alarm"; public static final String ALARM_COLUMN_FAMILY_NAME = "alarm"; @@ -324,12 +267,6 @@ public class ModelConstants { public static final String ALARM_PROPAGATE_TO_TENANT_PROPERTY = "propagate_to_tenant"; public static final String ALARM_PROPAGATE_RELATION_TYPES = "propagate_relation_types"; - public static final String ALARM_OPERATION_RESULT_PROPERTY = "operation_result"; - - public static final String ALARM_BY_ID_VIEW_NAME = "alarm_by_id"; - - public static final String ALARM_COMMENT_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; - public static final String ALARM_COMMENT_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY; public static final String ALARM_COMMENT_COLUMN_FAMILY_NAME = "alarm_comment"; public static final String ALARM_COMMENT_ALARM_ID = "alarm_id"; public static final String ALARM_COMMENT_USER_ID = USER_ID_PROPERTY; @@ -337,7 +274,7 @@ public class ModelConstants { public static final String ALARM_COMMENT_COMMENT = "comment"; /** - * Cassandra entity relation constants. + * Entity relation constants. */ public static final String RELATION_COLUMN_FAMILY_NAME = "relation"; public static final String RELATION_FROM_ID_PROPERTY = "from_id"; @@ -347,12 +284,8 @@ public class ModelConstants { public static final String RELATION_TYPE_PROPERTY = "relation_type"; public static final String RELATION_TYPE_GROUP_PROPERTY = "relation_type_group"; - public static final String RELATION_BY_TYPE_AND_CHILD_TYPE_VIEW_NAME = "relation_by_type_and_child_type"; - public static final String RELATION_REVERSE_VIEW_NAME = "reverse_relation"; - - /** - * Cassandra device_credentials constants. + * Device_credentials constants. */ public static final String DEVICE_CREDENTIALS_COLUMN_FAMILY_NAME = "device_credentials"; public static final String DEVICE_CREDENTIALS_DEVICE_ID_PROPERTY = DEVICE_ID_PROPERTY; @@ -360,11 +293,8 @@ public class ModelConstants { public static final String DEVICE_CREDENTIALS_CREDENTIALS_ID_PROPERTY = "credentials_id"; public static final String DEVICE_CREDENTIALS_CREDENTIALS_VALUE_PROPERTY = "credentials_value"; - public static final String DEVICE_CREDENTIALS_BY_DEVICE_COLUMN_FAMILY_NAME = "device_credentials_by_device"; - public static final String DEVICE_CREDENTIALS_BY_CREDENTIALS_ID_COLUMN_FAMILY_NAME = "device_credentials_by_credentials_id"; - /** - * Cassandra widgets_bundle constants. + * Widgets_bundle constants. */ public static final String WIDGETS_BUNDLE_COLUMN_FAMILY_NAME = "widgets_bundle"; public static final String WIDGETS_BUNDLE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; @@ -373,11 +303,8 @@ public class ModelConstants { public static final String WIDGETS_BUNDLE_IMAGE_PROPERTY = "image"; public static final String WIDGETS_BUNDLE_DESCRIPTION = "description"; - public static final String WIDGETS_BUNDLE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "widgets_bundle_by_tenant_and_search_text"; - public static final String WIDGETS_BUNDLE_BY_TENANT_AND_ALIAS_COLUMN_FAMILY_NAME = "widgets_bundle_by_tenant_and_alias"; - /** - * Cassandra widget_type constants. + * Widget_type constants. */ public static final String WIDGET_TYPE_COLUMN_FAMILY_NAME = "widget_type"; public static final String WIDGET_TYPE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; @@ -388,10 +315,8 @@ public class ModelConstants { public static final String WIDGET_TYPE_DESCRIPTION_PROPERTY = "description"; public static final String WIDGET_TYPE_DESCRIPTOR_PROPERTY = "descriptor"; - public static final String WIDGET_TYPE_BY_TENANT_AND_ALIASES_COLUMN_FAMILY_NAME = "widget_type_by_tenant_and_aliases"; - /** - * Cassandra dashboard constants. + * Dashboard constants. */ public static final String DASHBOARD_COLUMN_FAMILY_NAME = "dashboard"; public static final String DASHBOARD_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; @@ -402,10 +327,8 @@ public class ModelConstants { public static final String DASHBOARD_MOBILE_HIDE_PROPERTY = "mobile_hide"; public static final String DASHBOARD_MOBILE_ORDER_PROPERTY = "mobile_order"; - public static final String DASHBOARD_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "dashboard_by_tenant_and_search_text"; - /** - * Cassandra plugin component metadata constants. + * Plugin component metadata constants. */ public static final String COMPONENT_DESCRIPTOR_COLUMN_FAMILY_NAME = "component_descriptor"; public static final String COMPONENT_DESCRIPTOR_TYPE_PROPERTY = "type"; @@ -416,12 +339,8 @@ public class ModelConstants { public static final String COMPONENT_DESCRIPTOR_CONFIGURATION_DESCRIPTOR_PROPERTY = "configuration_descriptor"; public static final String COMPONENT_DESCRIPTOR_ACTIONS_PROPERTY = "actions"; - public static final String COMPONENT_DESCRIPTOR_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "component_desc_by_type_search_text"; - public static final String COMPONENT_DESCRIPTOR_BY_SCOPE_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "component_desc_by_scope_type_search_text"; - public static final String COMPONENT_DESCRIPTOR_BY_ID = "component_desc_by_id"; - /** - * Cassandra event constants. + * Event constants. */ public static final String ERROR_EVENT_TABLE_NAME = "error_event"; public static final String LC_EVENT_TABLE_NAME = "lc_event"; @@ -432,7 +351,6 @@ public class ModelConstants { public static final String EVENT_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String EVENT_SERVICE_ID_PROPERTY = "service_id"; public static final String EVENT_ENTITY_ID_PROPERTY = "entity_id"; - public static final String EVENT_BODY_PROPERTY = "body"; public static final String EVENT_MESSAGES_PROCESSED_COLUMN_NAME = "e_messages_processed"; public static final String EVENT_ERRORS_OCCURRED_COLUMN_NAME = "e_errors_occurred"; @@ -457,7 +375,7 @@ public class ModelConstants { public static final String SINGLETON_MODE = "singleton_mode"; /** - * Cassandra rule chain constants. + * Rule chain constants. */ public static final String RULE_CHAIN_COLUMN_FAMILY_NAME = "rule_chain"; public static final String RULE_CHAIN_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; @@ -467,11 +385,8 @@ public class ModelConstants { public static final String RULE_CHAIN_ROOT_PROPERTY = "root"; public static final String RULE_CHAIN_CONFIGURATION_PROPERTY = "configuration"; - public static final String RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "rule_chain_by_tenant_and_search_text"; - public static final String RULE_CHAIN_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "rule_chain_by_tenant_by_type_and_search_text"; - /** - * Cassandra rule node constants. + * Rule node constants. */ public static final String RULE_NODE_COLUMN_FAMILY_NAME = "rule_node"; public static final String RULE_NODE_CHAIN_ID_PROPERTY = "rule_chain_id"; @@ -480,7 +395,7 @@ public class ModelConstants { public static final String RULE_NODE_CONFIGURATION_PROPERTY = "configuration"; /** - * Rule node state constants. + * Node state constants. */ public static final String RULE_NODE_STATE_TABLE_NAME = "rule_node_state"; public static final String RULE_NODE_STATE_NODE_ID_PROPERTY = "rule_node_id"; @@ -491,7 +406,6 @@ public class ModelConstants { /** * OAuth2 client registration constants. */ - public static final String OAUTH2_PARAMS_COLUMN_FAMILY_NAME = "oauth2_params"; public static final String OAUTH2_PARAMS_ENABLED_PROPERTY = "enabled"; public static final String OAUTH2_PARAMS_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; @@ -503,12 +417,8 @@ public class ModelConstants { public static final String OAUTH2_PKG_NAME_PROPERTY = "pkg_name"; public static final String OAUTH2_APP_SECRET_PROPERTY = "app_secret"; - public static final String OAUTH2_CLIENT_REGISTRATION_INFO_COLUMN_FAMILY_NAME = "oauth2_client_registration_info"; - public static final String OAUTH2_CLIENT_REGISTRATION_COLUMN_FAMILY_NAME = "oauth2_client_registration"; public static final String OAUTH2_CLIENT_REGISTRATION_TEMPLATE_COLUMN_FAMILY_NAME = "oauth2_client_registration_template"; - public static final String OAUTH2_ENABLED_PROPERTY = "enabled"; public static final String OAUTH2_TEMPLATE_PROVIDER_ID_PROPERTY = "provider_id"; - public static final String OAUTH2_CLIENT_REGISTRATION_INFO_ID_PROPERTY = "client_registration_info_id"; public static final String OAUTH2_DOMAIN_NAME_PROPERTY = "domain_name"; public static final String OAUTH2_DOMAIN_SCHEME_PROPERTY = "domain_scheme"; public static final String OAUTH2_CLIENT_ID_PROPERTY = "client_id"; @@ -613,12 +523,6 @@ public class ModelConstants { public static final String EDGE_LABEL_PROPERTY = "label"; public static final String EDGE_TYPE_PROPERTY = "type"; public static final String EDGE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; - public static final String EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_tenant_and_search_text"; - public static final String EDGE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_tenant_by_type_and_search_text"; - public static final String EDGE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_customer_and_search_text"; - public static final String EDGE_BY_CUSTOMER_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_customer_by_type_and_search_text"; - public static final String EDGE_BY_TENANT_AND_NAME_VIEW_NAME = "edge_by_tenant_and_name"; - public static final String EDGE_BY_ROUTING_KEY_VIEW_NAME = "edge_by_routing_key"; public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key"; public static final String EDGE_SECRET_PROPERTY = "secret"; @@ -635,13 +539,11 @@ public class ModelConstants { public static final String EDGE_EVENT_ENTITY_ID_PROPERTY = "entity_id"; public static final String EDGE_EVENT_BODY_PROPERTY = "body"; - public static final String EDGE_EVENT_BY_ID_VIEW_NAME = "edge_event_by_id"; - public static final String EXTERNAL_ID_PROPERTY = "external_id"; /** * User auth settings constants. - * */ + */ public static final String USER_AUTH_SETTINGS_COLUMN_FAMILY_NAME = "user_auth_settings"; public static final String USER_AUTH_SETTINGS_USER_ID_PROPERTY = USER_ID_PROPERTY; public static final String USER_AUTH_SETTINGS_TWO_FA_SETTINGS = "two_fa_settings"; @@ -649,7 +551,6 @@ public class ModelConstants { /** * Cassandra attributes and timeseries constants. */ - public static final String ATTRIBUTES_KV_CF = "attributes_kv_cf"; public static final String TS_KV_CF = "ts_kv_cf"; public static final String TS_KV_PARTITIONS_CF = "ts_kv_partitions_cf"; public static final String TS_KV_LATEST_CF = "ts_kv_latest_cf"; @@ -671,7 +572,6 @@ public class ModelConstants { /** * Queue constants. */ - public static final String QUEUE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String QUEUE_NAME_PROPERTY = "name"; public static final String QUEUE_TOPIC_PROPERTY = "topic"; @@ -684,11 +584,9 @@ public class ModelConstants { public static final String QUEUE_COLUMN_FAMILY_NAME = "queue"; public static final String QUEUE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; - /** * Notification constants - * */ - + */ public static final String NOTIFICATION_TARGET_TABLE_NAME = "notification_target"; public static final String NOTIFICATION_TARGET_CONFIGURATION_PROPERTY = "configuration"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java index 40867951ca..92537dc850 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java @@ -19,7 +19,6 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -import org.springframework.data.jpa.repository.query.Procedure; import org.springframework.data.repository.query.Param; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.dao.model.sql.AlarmEntity; @@ -316,7 +315,9 @@ public interface AlarmRepository extends JpaRepository { @Query(value = "SELECT a FROM AlarmInfoEntity a WHERE a.tenantId = :tenantId AND a.id = :alarmId") AlarmInfoEntity findAlarmInfoById(@Param("tenantId") UUID tenantId, @Param("alarmId") UUID alarmId); - @Procedure(procedureName = "create_or_update_active_alarm") + @Query(value = "SELECT create_or_update_active_alarm(:t_id, :c_id, :a_id, :a_created_ts, :a_o_id, :a_o_type, :a_type, :a_severity, " + + ":a_start_ts, :a_end_ts, :a_details, :a_propagate, :a_propagate_to_owner, " + + ":a_propagate_to_tenant, :a_propagation_types, :a_creation_enabled)", nativeQuery = true) String createOrUpdateActiveAlarm(@Param("t_id") UUID tenantId, @Param("c_id") UUID customerId, @Param("a_id") UUID alarmId, @Param("a_created_ts") long createdTime, @Param("a_o_id") UUID originatorId, @Param("a_o_type") int originatorType, @@ -326,21 +327,22 @@ public interface AlarmRepository extends JpaRepository { @Param("a_propagate_to_tenant") boolean propagateToTenant, @Param("a_propagation_types") String propagationTypes, @Param("a_creation_enabled") boolean alarmCreationEnabled); - @Procedure(procedureName = "update_alarm") + @Query(value = "SELECT update_alarm(:t_id, :a_id, :a_severity, :a_start_ts, :a_end_ts, :a_details, :a_propagate, :a_propagate_to_owner, " + + ":a_propagate_to_tenant, :a_propagation_types)", nativeQuery = true) String updateAlarm(@Param("t_id") UUID tenantId, @Param("a_id") UUID alarmId, @Param("a_severity") String severity, @Param("a_start_ts") long startTs, @Param("a_end_ts") long endTs, @Param("a_details") String detailsAsString, @Param("a_propagate") boolean propagate, @Param("a_propagate_to_owner") boolean propagateToOwner, @Param("a_propagate_to_tenant") boolean propagateToTenant, @Param("a_propagation_types") String propagationTypes); - @Procedure(procedureName = "acknowledge_alarm") + @Query(value = "SELECT acknowledge_alarm(:t_id, :a_id, :a_ts)", nativeQuery = true) String acknowledgeAlarm(@Param("t_id") UUID tenantId, @Param("a_id") UUID alarmId, @Param("a_ts") long ts); - @Procedure(procedureName = "clear_alarm") + @Query(value = "SELECT clear_alarm(:t_id, :a_id, :a_ts, :a_details)", nativeQuery = true) String clearAlarm(@Param("t_id") UUID tenantId, @Param("a_id") UUID alarmId, @Param("a_ts") long ts, @Param("a_details") String details); - @Procedure(procedureName = "assign_alarm") + @Query(value = "SELECT assign_alarm(:t_id, :a_id, :u_id, :a_ts)", nativeQuery = true) String assignAlarm(@Param("t_id") UUID tenantId, @Param("a_id") UUID alarmId, @Param("u_id") UUID userId, @Param("a_ts") long assignTime); - @Procedure(procedureName = "unassign_alarm") + @Query(value = "SELECT unassign_alarm(:t_id, :a_id, :a_ts)", nativeQuery = true) String unassignAlarm(@Param("t_id") UUID tenantId, @Param("a_id") UUID alarmId, @Param("a_ts") long unassignTime); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java index 75778a347c..60614e8c90 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/insert/sql/SqlPartitioningRepository.java @@ -110,9 +110,12 @@ public class SqlPartitioningRepository { String tablePartition = table + "_" + partitionTs; String detachPsqlStmtStr = "ALTER TABLE " + table + " DETACH PARTITION " + tablePartition; - if (getCurrentServerVersion() >= PSQL_VERSION_14) { - detachPsqlStmtStr += " CONCURRENTLY"; - } + + // hotfix of ERROR: partition "integration_debug_event_1678323600000" already pending detach in partitioned table "public.integration_debug_event" + // https://github.com/thingsboard/thingsboard/issues/8271 + // if (getCurrentServerVersion() >= PSQL_VERSION_14) { + // detachPsqlStmtStr += " CONCURRENTLY"; + // } String dropStmtStr = "DROP TABLE " + tablePartition; try { diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/limits/DefaultRateLimitService.java b/dao/src/main/java/org/thingsboard/server/dao/util/limits/DefaultRateLimitService.java index 05825a6ff6..918f16ef19 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/util/limits/DefaultRateLimitService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/util/limits/DefaultRateLimitService.java @@ -43,7 +43,7 @@ public class DefaultRateLimitService implements RateLimitService { this.rateLimits = Caffeine.newBuilder() .expireAfterAccess(rateLimitsTtl, TimeUnit.MINUTES) .maximumSize(rateLimitsCacheMaxSize) - .build(); + .build(); } private final Cache rateLimits; diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java index 76ce467fd9..880143b58a 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestRestClient.java @@ -132,6 +132,18 @@ public class TestRestClient { .as(Device.class); } + public PageData getDevices(PageLink pageLink) { + Map params = new HashMap<>(); + addPageLinkToParam(params, pageLink); + return given().spec(requestSpec).queryParams(params) + .get("/api/tenant/devices") + .then() + .statusCode(HTTP_OK) + .extract() + .as(new TypeRef>() { + }); + } + public DeviceCredentials getDeviceCredentialsByDeviceId(DeviceId deviceId) { return given().spec(requestSpec).get("/api/device/{deviceId}/credentials", deviceId.getId()) .then() diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java index cd34e69239..eb6776a4e4 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/base/AbstractDriverBaseTest.java @@ -37,6 +37,7 @@ import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.id.AlarmId; @@ -150,6 +151,12 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { .findFirst().orElse(null); } + public Device getDeviceByName(String name) { + return testRestClient.getDevices(pageLink).getData().stream() + .filter(s -> s.getName().equals(name)) + .findFirst().orElse(null); + } + public List getRuleChainsByName(String name) { return testRestClient.getRuleChains(pageLink).getData().stream() .filter(s -> s.getName().equals(name)) @@ -269,4 +276,11 @@ abstract public class AbstractDriverBaseTest extends AbstractContainerTest { testRestClient.deleteDashboard(dashboardId); } } + + public void deleteDeviceByName(String deviceName) { + Device device = getDeviceByName(deviceName); + if (device != null) { + testRestClient.deleteDevice(device.getId()); + } + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java index 25b3aff7e1..ee89e5053d 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/CustomerPageHelper.java @@ -119,6 +119,7 @@ public class CustomerPageHelper extends CustomerPageElements { public void createCustomersUser() { plusBtn().click(); + addUserEmailField().click(); addUserEmailField().sendKeys(getRandomNumber() + "@gmail.com"); addBtnC().click(); activateWindowOkBtn().click(); diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java index b8fbda5135..030f7913c1 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageElements.java @@ -18,7 +18,7 @@ package org.thingsboard.server.msa.ui.pages; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; -public class DevicePageElements extends OtherPageElements { +public class DevicePageElements extends OtherPageElementsHelper { public DevicePageElements(WebDriver driver) { super(driver); } @@ -29,9 +29,30 @@ public class DevicePageElements extends OtherPageElements { private static final String ASSIGN_TO_CUSTOMER_BTN = "//mat-cell[contains(@class,'name')]/span[text()='%s']" + "/ancestor::mat-row//mat-icon[contains(text(),'assignment_ind')]/parent::button"; private static final String CHOOSE_CUSTOMER_FOR_ASSIGN_FIELD = "//input[@formcontrolname='entity']"; - private static final String CUSTOMER_FROM_ASSIGN_DROPDOWN = "//div[@role = 'listbox']//span[text() = '%s']"; + private static final String ENTITY_FROM_DROPDOWN = "//div[@role = 'listbox']//span[text() = '%s']"; private static final String CLOSE_DEVICE_DETAILS_VIEW = "//header//mat-icon[contains(text(),'close')]/parent::button"; private static final String SUBMIT_ASSIGN_TO_CUSTOMER_BTN = "//button[@type='submit']"; + private static final String ADD_DEVICE_BTN = "//mat-icon[text() = 'insert_drive_file']/parent::button"; + private static final String CREATE_DEVICE_NAME_FIELD = "//tb-device-wizard//input[@formcontrolname='name']"; + private static final String HEADER_NAME_VIEW = "//header//div[@class='tb-details-title']/span"; + private static final String DESCRIPTION_FIELD_CREATE_VIEW = "//tb-device-wizard//textarea[@formcontrolname='description']"; + private static final String ADD_DEVICE_VIEW = "//tb-device-wizard"; + private static final String DELETE_BTN_DETAILS_TAB = "//span[contains(text(),'Delete device')]/parent::button"; + private static final String CHECKBOX_GATEWAY_EDIT = "//mat-checkbox[@formcontrolname='gateway']//label"; + private static final String CHECKBOX_GATEWAY_CREATE = "//tb-device-wizard//mat-checkbox[@formcontrolname='gateway']//label"; + private static final String CHECKBOX_OVERWRITE_ACTIVITY_TIME_EDIT = "//mat-checkbox[@formcontrolname='overwriteActivityTime']//label"; + private static final String CHECKBOX_OVERWRITE_ACTIVITY_TIME_CREATE = "//tb-device-wizard//mat-checkbox[@formcontrolname='overwriteActivityTime']//label"; + private static final String CHECKBOX_GATEWAY_DETAILS = "//mat-checkbox[@formcontrolname='gateway']//input"; + private static final String CHECKBOX_GATEWAY_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-gateway')]//mat-icon[text() = 'check_box']"; + private static final String CHECKBOX_OVERWRITE_ACTIVITY_TIME_DETAILS = "//mat-checkbox[@formcontrolname='overwriteActivityTime']//input"; + private static final String CLEAR_PROFILE_FIELD_BTN = "//button[@aria-label='Clear']"; + private static final String DEVICE_PROFILE_REDIRECTED_BTN = "//a[@aria-label='Open device profile']"; + private static final String DEVICE_LABEL_FIELD_CREATE = "//tb-device-wizard//input[@formcontrolname='label']"; + private static final String DEVICE_LABEL_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-label')]/span"; + private static final String DEVICE_CUSTOMER_PAGE = DEVICE + "/ancestor::mat-row//mat-cell[contains(@class,'cdk-column-customerTitle')]/span"; + private static final String CUSTOMER_OPTION_BNT = "//div[text() = 'Customer']/ancestor::mat-step-header"; + private static final String ASSIGN_ON_CUSTOMER_FIELD = "//input[@formcontrolname='entity']"; + private static final String DEVICE_LABEL_EDIT = "//input[@formcontrolname='label']"; public WebElement device(String deviceName) { return waitUntilElementToBeClickable(String.format(DEVICE, deviceName)); @@ -53,8 +74,8 @@ public class DevicePageElements extends OtherPageElements { return waitUntilElementToBeClickable(CHOOSE_CUSTOMER_FOR_ASSIGN_FIELD); } - public WebElement customerFromAssignDropdown(String customerTitle) { - return waitUntilElementToBeClickable(String.format(CUSTOMER_FROM_ASSIGN_DROPDOWN, customerTitle)); + public WebElement entityFromDropdown(String customerTitle) { + return waitUntilElementToBeClickable(String.format(ENTITY_FROM_DROPDOWN, customerTitle)); } public WebElement closeDeviceDetailsViewBtn() { @@ -64,4 +85,92 @@ public class DevicePageElements extends OtherPageElements { public WebElement submitAssignToCustomerBtn() { return waitUntilElementToBeClickable(SUBMIT_ASSIGN_TO_CUSTOMER_BTN); } + + public WebElement addDeviceBtn() { + return waitUntilElementToBeClickable(ADD_DEVICE_BTN); + } + + public WebElement nameField() { + return waitUntilElementToBeClickable(CREATE_DEVICE_NAME_FIELD); + } + + public WebElement headerNameView() { + return waitUntilVisibilityOfElementLocated(HEADER_NAME_VIEW); + } + + public WebElement descriptionFieldCreateField() { + return waitUntilElementToBeClickable(DESCRIPTION_FIELD_CREATE_VIEW); + } + + public WebElement addDeviceView() { + return waitUntilPresenceOfElementLocated(ADD_DEVICE_VIEW); + } + + public WebElement deleteBtnDetailsTab() { + return waitUntilElementToBeClickable(DELETE_BTN_DETAILS_TAB); + } + + public WebElement checkboxGatewayEdit() { + return waitUntilElementToBeClickable(CHECKBOX_GATEWAY_EDIT); + } + + public WebElement checkboxGatewayCreate() { + return waitUntilElementToBeClickable(CHECKBOX_GATEWAY_CREATE); + } + + public WebElement checkboxOverwriteActivityTimeEdit() { + return waitUntilElementToBeClickable(CHECKBOX_OVERWRITE_ACTIVITY_TIME_EDIT); + } + + public WebElement checkboxOverwriteActivityTimeCreate() { + return waitUntilElementToBeClickable(CHECKBOX_OVERWRITE_ACTIVITY_TIME_CREATE); + } + + public WebElement checkboxGatewayDetailsTab() { + return waitUntilPresenceOfElementLocated(CHECKBOX_GATEWAY_DETAILS); + } + + public WebElement checkboxGatewayPage(String deviceName) { + return waitUntilPresenceOfElementLocated(String.format(CHECKBOX_GATEWAY_PAGE, deviceName)); + } + + public WebElement checkboxOverwriteActivityTimeDetails() { + return waitUntilPresenceOfElementLocated(CHECKBOX_OVERWRITE_ACTIVITY_TIME_DETAILS); + } + + public WebElement clearProfileFieldBtn() { + return waitUntilElementToBeClickable(CLEAR_PROFILE_FIELD_BTN); + } + + public WebElement deviceProfileRedirectedBtn() { + return waitUntilElementToBeClickable(DEVICE_PROFILE_REDIRECTED_BTN); + } + + public WebElement deviceLabelFieldCreate() { + return waitUntilElementToBeClickable(DEVICE_LABEL_FIELD_CREATE); + } + + public WebElement deviceLabelOnPage(String deviceName) { + return waitUntilVisibilityOfElementLocated(String.format(DEVICE_LABEL_PAGE, deviceName)); + } + + public WebElement customerOptionBtn() { + return waitUntilElementToBeClickable(CUSTOMER_OPTION_BNT); + } + + public WebElement assignOnCustomerField() { + return waitUntilElementToBeClickable(ASSIGN_ON_CUSTOMER_FIELD); + } + + public WebElement deviceCustomerOnPage(String deviceName) { + return waitUntilVisibilityOfElementLocated(String.format(DEVICE_CUSTOMER_PAGE, deviceName)); + } + + public WebElement deviceLabelEditField() { + return waitUntilElementToBeClickable(DEVICE_LABEL_EDIT); + } + + public WebElement deviceLabelDetailsField() { + return waitUntilVisibilityOfElementLocated(DEVICE_LABEL_EDIT); + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java index 19e85244cd..c6df90e0fa 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/pages/DevicePageHelper.java @@ -22,6 +22,9 @@ public class DevicePageHelper extends DevicePageElements { super(driver); } + private String description; + private String label; + public void openDeviceAlarms(String deviceName) { if (!deviceDetailsView().isDisplayed()) { device(deviceName).click(); @@ -31,7 +34,63 @@ public class DevicePageHelper extends DevicePageElements { public void assignToCustomer(String customerTitle) { chooseCustomerForAssignField().click(); - customerFromAssignDropdown(customerTitle).click(); + entityFromDropdown(customerTitle).click(); submitAssignToCustomerBtn().click(); } + + public void openCreateDeviceView() { + plusBtn().click(); + addDeviceBtn().click(); + } + + public void enterName(String deviceName) { + enterText(nameField(), deviceName); + } + + public void enterDescription(String description) { + enterText(descriptionFieldCreateField(), description); + } + + public void enterLabel(String label) { + enterText(deviceLabelFieldCreate(), label); + } + + public void deleteDeviceByRightSideBtn(String deviceName) { + deleteBtn(deviceName).click(); + warningPopUpYesBtn().click(); + } + + public void deleteDeviceFromDetailsTab() { + deleteBtnDetailsTab().click(); + warningPopUpYesBtn().click(); + } + + public void setDescription() { + scrollToElement(descriptionEntityView()); + description = descriptionEntityView().getAttribute("value"); + } + + public void setLabel() { + label = deviceLabelDetailsField().getAttribute("value"); + } + + public String getDescription() { + return description; + } + + public String getLabel() { + return label; + } + + public void changeDeviceProfile(String deviceProfileName) { + clearProfileFieldBtn().click(); + entityFromDropdown(deviceProfileName).click(); + } + + public void assignOnCustomer(String customerTitle) { + customerOptionBtn().click(); + assignOnCustomerField().click(); + entityFromList(customerTitle).click(); + sleep(2); //waiting for the action to count + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/AbstractDeviceTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/AbstractDeviceTest.java new file mode 100644 index 0000000000..3cd46fefc9 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/AbstractDeviceTest.java @@ -0,0 +1,45 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.tests.devicessmoke; + +import io.qameta.allure.Epic; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.thingsboard.server.msa.ui.base.AbstractDriverBaseTest; +import org.thingsboard.server.msa.ui.pages.DevicePageHelper; +import org.thingsboard.server.msa.ui.pages.LoginPageHelper; +import org.thingsboard.server.msa.ui.pages.SideBarMenuViewHelper; + +@Epic("Device smoke tests") +abstract public class AbstractDeviceTest extends AbstractDriverBaseTest { + + protected SideBarMenuViewHelper sideBarMenuView; + protected DevicePageHelper devicePage; + protected String deviceName; + + @BeforeClass + public void login() { + new LoginPageHelper(driver).authorizationTenant(); + sideBarMenuView = new SideBarMenuViewHelper(driver); + devicePage = new DevicePageHelper(driver); + } + + @AfterMethod + public void delete() { + deleteDeviceByName(deviceName); + deviceName = null; + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/CreateDeviceTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/CreateDeviceTest.java new file mode 100644 index 0000000000..3e4ab48f5d --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/CreateDeviceTest.java @@ -0,0 +1,214 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.tests.devicessmoke; + +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import org.testng.annotations.Test; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.thingsboard.server.msa.ui.base.AbstractBasePage.random; +import static org.thingsboard.server.msa.ui.utils.Const.DEVICE_PROFILE_IS_REQUIRED_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_DEVICE_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; +import static org.thingsboard.server.msa.ui.utils.Const.NAME_IS_REQUIRED_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.SAME_NAME_WARNING_DEVICE_MESSAGE; + +@Feature("Create device") +public class CreateDeviceTest extends AbstractDeviceTest { + + @Test(groups = "smoke") + @Description("Add device after specifying the name (text/numbers /special characters)") + public void createDevice() { + deviceName = ENTITY_NAME + random(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.addBtnC().click(); + devicePage.refreshBtn().click(); + + assertIsDisplayed(devicePage.entity(deviceName)); + } + + @Test(groups = "smoke") + @Description("Add device after specifying the name and description (text/numbers /special characters)") + public void createDeviceWithDescription() { + deviceName = ENTITY_NAME + random(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.enterDescription(deviceName); + devicePage.addBtnC().click(); + devicePage.refreshBtn().click(); + devicePage.entity(deviceName).click(); + devicePage.setHeaderName(); + + assertThat(devicePage.getHeaderName()).as("Header of device details tab").isEqualTo(deviceName); + assertThat(devicePage.descriptionEntityView().getAttribute("value")) + .as("Description in device details tab").isEqualTo(deviceName); + } + + @Test(groups = "smoke") + @Description("Add device without the name") + public void createDeviceWithoutName() { + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.nameField().click(); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.addDeviceView()); + assertThat(devicePage.errorMessage().getText()).as("Text of warning message").isEqualTo(NAME_IS_REQUIRED_MESSAGE); + } + + @Test(groups = "smoke") + @Description("Create device only with spase in name") + public void createDeviceWithOnlySpace() { + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(" "); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.warningMessage()); + assertThat(devicePage.warningMessage().getText()).as("Text of warning message").isEqualTo(EMPTY_DEVICE_MESSAGE); + assertIsDisplayed(devicePage.addDeviceView()); + } + + @Test(groups = "smoke") + @Description("Create a device with the same name") + public void createDeviceWithSameName() { + Device device = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)); + deviceName = device.getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.warningMessage()); + assertThat(devicePage.warningMessage().getText()).as("Text of warning message").isEqualTo(SAME_NAME_WARNING_DEVICE_MESSAGE); + assertIsDisplayed(devicePage.addDeviceView()); + } + + @Test(groups = "smoke") + @Description("Add device after specifying the name (text/numbers /special characters) without refresh") + public void createDeviceWithoutRefresh() { + deviceName = ENTITY_NAME + random(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.entity(deviceName)); + } + + @Test(groups = "smoke") + @Description("Add device without device profile") + public void createDeviceWithoutDeviceProfile() { + deviceName = ENTITY_NAME + random(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.clearProfileFieldBtn().click(); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.errorMessage()); + assertThat(devicePage.errorMessage().getText()).as("Text of warning message").isEqualTo(DEVICE_PROFILE_IS_REQUIRED_MESSAGE); + assertIsDisplayed(devicePage.addDeviceView()); + } + + @Test(groups = "smoke") + @Description("Add device with enabled gateway") + public void createDeviceWithEnableGateway() { + deviceName = ENTITY_NAME + random(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.checkboxGatewayCreate().click(); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.device(deviceName)); + assertIsDisplayed(devicePage.checkboxGatewayPage(deviceName)); + } + + @Test(groups = "smoke") + @Description("Add device with enabled overwrite activity time for connected") + public void createDeviceWithEnableOverwriteActivityTimeForConnected() { + deviceName = ENTITY_NAME + random(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.checkboxGatewayCreate().click(); + devicePage.checkboxOverwriteActivityTimeCreate().click(); + devicePage.addBtnC().click(); + devicePage.device(deviceName).click(); + + assertThat(devicePage.checkboxOverwriteActivityTimeDetails().getAttribute("class").contains("selected")) + .as("Overwrite activity time for connected is enable").isTrue(); + } + + @Test(groups = "smoke") + @Description("Add device with label") + public void createDeviceWithLabel() { + deviceName = ENTITY_NAME + random(); + String deviceLabel = "device label " + random(); + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.enterLabel(deviceLabel); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.deviceLabelOnPage(deviceName)); + assertThat(devicePage.deviceLabelOnPage(deviceName).getText()).as("Label added correctly").isEqualTo(deviceLabel); + } + + @Test(groups = "smoke") + @Description("Add device with assignee on customer") + public void createDeviceWithAssignee() { + deviceName = ENTITY_NAME + random(); + String customer = "Customer A"; + + sideBarMenuView.goToDevicesPage(); + devicePage.openCreateDeviceView(); + devicePage.enterName(deviceName); + devicePage.assignOnCustomer(customer); + devicePage.addBtnC().click(); + + assertIsDisplayed(devicePage.deviceCustomerOnPage(deviceName)); + assertThat(devicePage.deviceCustomerOnPage(deviceName).getText()) + .as("Customer added correctly").isEqualTo(customer); + } + + @Test(groups = "smoke") + @Description("Go to devices documentation page") + public void documentation() { + String urlPath = "docs/user-guide/ui/devices/"; + + sideBarMenuView.goToDevicesPage(); + devicePage.entity("Thermostat T1").click(); + devicePage.goToHelpPage(); + + assertThat(urlContains(urlPath)).as("Redirected URL contains " + urlPath).isTrue(); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeleteDeviceTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeleteDeviceTest.java new file mode 100644 index 0000000000..76028f0bc0 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeleteDeviceTest.java @@ -0,0 +1,75 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.tests.devicessmoke; + +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; + +@Feature("Delete device") +public class DeleteDeviceTest extends AbstractDeviceTest { + + @BeforeMethod + public void createDevice() { + Device device = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)); + deviceName = device.getName(); + } + + @Test(groups = "smoke") + @Description("Remove the device by clicking on the trash icon in the right side of device") + public void deleteDeviceByRightSideBtn() { + sideBarMenuView.goToDevicesPage(); + devicePage.deleteDeviceByRightSideBtn(deviceName); + devicePage.refreshBtn().click(); + + devicePage.assertEntityIsNotPresent(deviceName); + } + + @Test(groups = "smoke") + @Description("Remove device by mark in the checkbox and then click on the trash can icon in the menu that appears at the top") + public void deleteSelectedDevice() { + sideBarMenuView.goToDevicesPage(); + devicePage.deleteSelected(deviceName); + devicePage.refreshBtn().click(); + + devicePage.assertEntityIsNotPresent(deviceName); + } + + @Test(groups = "smoke") + @Description("Remove the device by clicking on the 'Delete device' btn in the entity view") + public void deleteDeviceFromDetailsTab() { + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.deleteDeviceFromDetailsTab(); + devicePage.refreshBtn(); + + devicePage.assertEntityIsNotPresent(deviceName); + } + + @Test(groups = "smoke") + @Description("Remove the device by clicking on the trash icon in the right side of device without refresh") + public void deleteDeviceWithoutRefresh() { + sideBarMenuView.goToDevicesPage(); + devicePage.deleteDeviceByRightSideBtn(deviceName); + + devicePage.assertEntityIsNotPresent(deviceName); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeleteSeveralDevicesTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeleteSeveralDevicesTest.java new file mode 100644 index 0000000000..48df384c63 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/DeleteSeveralDevicesTest.java @@ -0,0 +1,84 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.tests.devicessmoke; + +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; + +@Feature("Delete several devices") +public class DeleteSeveralDevicesTest extends AbstractDeviceTest { + + private String deviceName1; + private String deviceName2; + + @BeforeMethod + public void createDevices() { + Device device = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)); + Device device1 = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)); + deviceName1 = device.getName(); + deviceName2 = device1.getName(); + } + + @AfterMethod + public void deleteDevices() { + deleteDeviceByName(deviceName1); + deleteDeviceByName(deviceName2); + } + + @Test(groups = "smoke") + @Description("Remove several devices by mark in the checkbox and then click on the trash can icon in the menu " + + "that appears at the top") + public void deleteSeveralDevicesByTopBtn() { + sideBarMenuView.goToDevicesPage(); + devicePage.deleteSelected(2); + devicePage.refreshBtn().click(); + + devicePage.assertEntityIsNotPresent(deviceName1); + devicePage.assertEntityIsNotPresent(deviceName2); + } + + @Test(groups = "smoke") + @Description("Remove several devices by mark all the devices on the page by clicking in the topmost checkbox" + + " and then clicking on the trash icon in the menu that appears") + public void selectAllDevices() { + sideBarMenuView.goToDevicesPage(); + devicePage.selectAllCheckBox().click(); + devicePage.deleteSelectedBtn().click(); + + assertIsDisplayed(devicePage.warningPopUpTitle()); + assertThat(devicePage.warningPopUpTitle().getText()).as("Warning title contains true correct of selected devices") + .contains(String.valueOf(devicePage.markCheckbox().size())); + } + + @Test(groups = "smoke") + @Description("Remove several devices by mark in the checkbox and then click on the trash can icon in the menu " + + "that appears at the top without refresh") + public void deleteSeveralWithoutRefresh() { + sideBarMenuView.goToDevicesPage(); + devicePage.deleteSelected(2); + + devicePage.assertEntityIsNotPresent(deviceName1); + devicePage.assertEntityIsNotPresent(deviceName2); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/EditDeviceTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/EditDeviceTest.java new file mode 100644 index 0000000000..77bb209485 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/devicessmoke/EditDeviceTest.java @@ -0,0 +1,179 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa.ui.tests.devicessmoke; + +import io.qameta.allure.Description; +import io.qameta.allure.Feature; +import org.testng.annotations.Test; +import org.thingsboard.server.msa.ui.utils.DataProviderCredential; +import org.thingsboard.server.msa.ui.utils.EntityPrototypes; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.thingsboard.server.msa.ui.base.AbstractBasePage.getRandomNumber; +import static org.thingsboard.server.msa.ui.utils.Const.EMPTY_DEVICE_MESSAGE; +import static org.thingsboard.server.msa.ui.utils.Const.ENTITY_NAME; + +@Feature("Edit device") +public class EditDeviceTest extends AbstractDeviceTest { + + @Test(groups = "smoke") + @Description("Change name by edit menu") + public void changeName() { + String newDeviceName = "Changed" + getRandomNumber(); + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.setHeaderName(); + String nameBefore = devicePage.getHeaderName(); + devicePage.editPencilBtn().click(); + devicePage.changeNameEditMenu(newDeviceName); + devicePage.doneBtnEditView().click(); + deviceName = newDeviceName; + devicePage.setHeaderName(); + String nameAfter = devicePage.getHeaderName(); + + assertThat(nameAfter).as("The name has changed").isNotEqualTo(nameBefore); + assertThat(nameAfter).as("The name has changed correctly").isEqualTo(newDeviceName); + } + + @Test(groups = "smoke") + @Description("Delete name and save") + public void deleteName() { + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.changeNameEditMenu(""); + + assertIsDisable(devicePage.doneBtnEditViewVisible()); + } + + @Test(groups = "smoke") + @Description("Save only with space") + public void saveOnlyWithSpace() { + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.changeNameEditMenu(" "); + devicePage.doneBtnEditView().click(); + + assertIsDisplayed(devicePage.warningMessage()); + assertThat(devicePage.warningMessage().getText()).as("Text of warning message").isEqualTo(EMPTY_DEVICE_MESSAGE); + } + + @Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "editMenuDescription") + @Description("Write the description and save the changes/Change the description and save the changes/Delete the description and save the changes") + public void editDescription(String description, String newDescription, String finalDescription) { + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, description)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.descriptionEntityView().sendKeys(newDescription); + devicePage.doneBtnEditView().click(); + devicePage.setDescription(); + + assertThat(devicePage.getDescription()).as("The description changed correctly").isEqualTo(finalDescription); + } + + @Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "enable") + @Description("Enable gateway mode/Disable gateway") + public void isGateway(boolean isGateway) { + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, isGateway)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.checkboxGatewayEdit().click(); + devicePage.doneBtnEditView().click(); + + if (isGateway) { + assertThat(devicePage.checkboxGatewayDetailsTab().getAttribute("class").contains("selected")) + .as("Gateway is disable").isFalse(); + } else { + assertThat(devicePage.checkboxGatewayDetailsTab().getAttribute("class").contains("selected")) + .as("Gateway is enable").isTrue(); + } + } + + @Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "enable") + @Description("Enable overwrite activity time for connected/Disable overwrite activity time for connected") + public void isOverwriteActivityTimeForConnectedDevice(boolean isOverwriteActivityTimeForConnected) { + deviceName = testRestClient.postDevice("", + EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, true, isOverwriteActivityTimeForConnected)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.checkboxOverwriteActivityTimeEdit().click(); + devicePage.doneBtnEditView().click(); + + if (isOverwriteActivityTimeForConnected) { + assertThat(devicePage.checkboxOverwriteActivityTimeDetails().getAttribute("class").contains("selected")) + .as("Overwrite activity time for connected is disable").isFalse(); + } else { + assertThat(devicePage.checkboxOverwriteActivityTimeDetails().getAttribute("class").contains("selected")) + .as("Overwrite activity time for connected is enable").isTrue(); + } + } + + @Test(groups = "smoke") + @Description("Change device profile") + public void changeDeviceProfile() { + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.changeDeviceProfile("DEFAULT"); + devicePage.doneBtnEditView().click(); + + assertIsDisplayed(devicePage.deviceProfileRedirectedBtn()); + assertThat(devicePage.deviceProfileRedirectedBtn().getText()).as("Profile changed correctly").isEqualTo("DEFAULT"); + } + + @Test(groups = "smoke") + @Description("Save without device profile") + public void saveWithoutDeviceProfile() { + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.clearProfileFieldBtn().click(); + + assertIsDisable(devicePage.doneBtnEditViewVisible()); + } + + @Test(groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "editDeviceLabel") + @Description("Write the label and save the changes/Change the label and save the changes/Delete the label and save the changes") + public void editLabel(String label, String newLabel, String finalLabel) { + deviceName = testRestClient.postDevice("", EntityPrototypes.defaultDevicePrototype(ENTITY_NAME, "", label)).getName(); + + sideBarMenuView.goToDevicesPage(); + devicePage.entity(deviceName).click(); + devicePage.editPencilBtn().click(); + devicePage.deviceLabelEditField().sendKeys(newLabel); + devicePage.doneBtnEditView().click(); + devicePage.setLabel(); + + assertThat(devicePage.getLabel()).as("The label changed correctly").isEqualTo(finalLabel); + } +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/rulechainssmoke/RuleChainEditMenuTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/rulechainssmoke/RuleChainEditMenuTest.java index eaeaa6e61f..5882556ff8 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/rulechainssmoke/RuleChainEditMenuTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/tests/rulechainssmoke/RuleChainEditMenuTest.java @@ -99,7 +99,7 @@ public class RuleChainEditMenuTest extends AbstractRuleChainTest { assertThat(ruleChainsPage.getDescription()).as("The description changed correctly").isEqualTo(finalDescription); } - @Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "debugMode") + @Test(priority = 20, groups = "smoke", dataProviderClass = DataProviderCredential.class, dataProvider = "enable") @Description("Enable debug mode/Disable debug mode") public void debugMode(boolean debugMode) { ruleChainName = ENTITY_NAME + random(); diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java index 7b64eaa1b4..28bdac556f 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/Const.java @@ -36,10 +36,13 @@ public class Const { public static final String EMPTY_CUSTOMER_MESSAGE = "Customer title should be specified!"; public static final String EMPTY_DEVICE_PROFILE_MESSAGE = "Device profile name should be specified!"; public static final String EMPTY_ASSET_PROFILE_MESSAGE = "Asset profile name should be specified!"; + public static final String EMPTY_DEVICE_MESSAGE = "Device name should be specified!"; public static final String DELETE_RULE_CHAIN_WITH_PROFILE_MESSAGE = "The rule chain referenced by the device profiles cannot be deleted!"; public static final String SAME_NAME_WARNING_CUSTOMER_MESSAGE = "Customer with such title already exists!"; public static final String SAME_NAME_WARNING_DEVICE_PROFILE_MESSAGE = "Device profile with such name already exists!"; public static final String SAME_NAME_WARNING_ASSET_PROFILE_MESSAGE = "Asset profile with such name already exists!"; + public static final String SAME_NAME_WARNING_DEVICE_MESSAGE = "Device with such name already exists!"; public static final String PHONE_NUMBER_ERROR_MESSAGE = "Phone number is invalid or not possible"; public static final String NAME_IS_REQUIRED_MESSAGE = "Name is required."; -} \ No newline at end of file + public static final String DEVICE_PROFILE_IS_REQUIRED_MESSAGE = "Device profile is required"; +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java index 6e56abff2e..e7ee242cab 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/DataProviderCredential.java @@ -151,9 +151,19 @@ public class DataProviderCredential { } @DataProvider - public static Object[][] debugMode() { + public static Object[][] enable() { return new Object[][]{ {false}, {true}}; } + + @DataProvider + public static Object[][] editDeviceLabel() { + String newLabel = "Label" + getRandomNumber(); + String label = "Label"; + return new Object[][]{ + {"", newLabel, newLabel}, + {label, newLabel, label + newLabel}, + {label, Keys.CONTROL + "A" + Keys.BACK_SPACE, ""}}; + } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java index 6f2d9560f4..ec66442bd2 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ui/utils/EntityPrototypes.java @@ -192,6 +192,41 @@ public class EntityPrototypes { return device; } + public static Device defaultDevicePrototype(String name, String description) { + Device device = new Device(); + device.setName(name + RandomStringUtils.randomAlphanumeric(7)); + device.setType("DEFAULT"); + device.setAdditionalInfo(JacksonUtil.newObjectNode().put("description", description)); + return device; + } + + public static Device defaultDevicePrototype(String name, String description, String label) { + Device device = new Device(); + device.setName(name + RandomStringUtils.randomAlphanumeric(7)); + device.setType("DEFAULT"); + device.setAdditionalInfo(JacksonUtil.newObjectNode().put("description", description)); + device.setLabel(label); + return device; + } + + public static Device defaultDevicePrototype(String name, boolean gateway) { + Device device = new Device(); + device.setName(name + RandomStringUtils.randomAlphanumeric(7)); + device.setType("DEFAULT"); + device.setAdditionalInfo(JacksonUtil.newObjectNode().put("gateway", gateway)); + return device; + } + + public static Device defaultDevicePrototype(String name, boolean gateway, boolean overwriteActivityTime) { + Device device = new Device(); + device.setName(name + RandomStringUtils.randomAlphanumeric(7)); + device.setType("DEFAULT"); + device.setAdditionalInfo(JacksonUtil.newObjectNode() + .put("gateway", gateway) + .put("overwriteActivityTime", overwriteActivityTime)); + return device; + } + public static Asset defaultAssetPrototype(String name, CustomerId id) { Asset asset = new Asset(); asset.setName(name + RandomStringUtils.randomAlphanumeric(7)); diff --git a/msa/black-box-tests/src/test/resources/all.xml b/msa/black-box-tests/src/test/resources/all.xml index 155aac38e1..95248a6fe6 100644 --- a/msa/black-box-tests/src/test/resources/all.xml +++ b/msa/black-box-tests/src/test/resources/all.xml @@ -67,4 +67,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/msa/black-box-tests/src/test/resources/smokeDevices.xml b/msa/black-box-tests/src/test/resources/smokeDevices.xml new file mode 100644 index 0000000000..c255f9ed53 --- /dev/null +++ b/msa/black-box-tests/src/test/resources/smokeDevices.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msa/black-box-tests/src/test/resources/uiTests.xml b/msa/black-box-tests/src/test/resources/uiTests.xml index 9dbf8dfc0c..9de384d15c 100644 --- a/msa/black-box-tests/src/test/resources/uiTests.xml +++ b/msa/black-box-tests/src/test/resources/uiTests.xml @@ -62,4 +62,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/msa/tb/docker-cassandra/Dockerfile b/msa/tb/docker-cassandra/Dockerfile index 896825ffd0..2f23aec399 100644 --- a/msa/tb/docker-cassandra/Dockerfile +++ b/msa/tb/docker-cassandra/Dockerfile @@ -47,7 +47,7 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends wget nmap procps gnupg2 \ && echo "deb http://apt.postgresql.org/pub/repos/apt/ $(. /etc/os-release && echo -n $VERSION_CODENAME)-pgdg main" | tee --append /etc/apt/sources.list.d/pgdg.list > /dev/null \ && wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O- | apt-key add - \ - && echo 'deb http://downloads.apache.org/cassandra/debian 40x main' | tee --append /etc/apt/sources.list.d/cassandra.list > /dev/null \ + && echo "deb https://debian.cassandra.apache.org 40x main" | tee -a /etc/apt/sources.list.d/cassandra.sources.list > /dev/null \ && wget -q https://downloads.apache.org/cassandra/KEYS -O- | apt-key add - \ && apt-get update \ && apt-get install -y --no-install-recommends cassandra cassandra-tools postgresql-${PG_MAJOR} \ diff --git a/security.md b/security.md new file mode 100644 index 0000000000..9f917e5f00 --- /dev/null +++ b/security.md @@ -0,0 +1,17 @@ +# Security Policy + +## Reporting a Vulnerability + +Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to Thingsboard privately, +to minimize attacks against current users of Thingsboard before they are fixed. Vulnerabilities will be investigated and release as soon as possible. + +To report a vulnerability or a security-related issue, please email the private address security@thingsboard.io with the details of the vulnerability. +Emails will be addressed within 3 business days, including a detailed plan to investigate the issue and any potential workarounds to perform in the meantime. +Do not report non-security-impacting bugs through this channel. Use GitHub issues instead. + +**Proposed Email Content** +Provide a descriptive subject line and in the body of the email include the following information: + +- Basic identity information, such as your name and your affiliation or company. +- Detailed steps to reproduce the vulnerability (log errors, screenshots are all helpful to us). +- Description of the effects of the vulnerability on Thingsboard. \ No newline at end of file diff --git a/ui-ngx/src/app/shared/models/ace/tbel/worker-tbel.js b/ui-ngx/src/app/shared/models/ace/tbel/worker-tbel.js index c309eb38aa..bc22e806c3 100644 --- a/ui-ngx/src/app/shared/models/ace/tbel/worker-tbel.js +++ b/ui-ngx/src/app/shared/models/ace/tbel/worker-tbel.js @@ -5026,6 +5026,21 @@ var JSHINT = (function() { return that; }, 20); } + function nullSafeProperty(s) { + console.log("test " + s); + symbol(s, 20).exps = true; + return infix(s, function(context, left, that) { + if (state.option.bitwise) { + warning("W016", that, that.id); + } + + checkLeftSideAssign(context, left, that); + + that.right = expression(context, 10); + + return that; + }, 20); + } function suffix(s) { var x = symbol(s, 150); @@ -5539,6 +5554,9 @@ var JSHINT = (function() { bitwiseassignop("<<="); bitwiseassignop(">>="); bitwiseassignop(">>>="); + + nullSafeProperty(".?"); + infix(",", function(context, left, that) { if (state.option.nocomma) { warning("W127", that); @@ -9450,6 +9468,12 @@ Lexer.prototype = { switch (ch1) { case ".": + if (ch1 === "." && this.peek(1) === "?") { + return { + type: Token.Punctuator, + value: ".?" + }; + } if ((/^[0-9]$/).test(this.peek(1))) { return null; }