Browse Source

Merge branch 'master' into hotfix/3.6

pull/9359/head
Andrew Shvayka 3 years ago
committed by GitHub
parent
commit
2b9575d81a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      application/pom.xml
  2. 1
      application/src/main/data/upgrade/3.6.0/schema_update.sql
  3. 54
      application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java
  4. 9
      application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java
  5. 3
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  6. 5
      application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java
  7. 5
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java
  8. 3
      application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/SystemWidgetTypesEdgeEventFetcher.java
  9. 2
      application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/SystemWidgetsBundlesEdgeEventFetcher.java
  10. 3
      application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/TenantWidgetTypesEdgeEventFetcher.java
  11. 16
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  12. 15
      application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
  13. 4
      application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java
  14. 3
      application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java
  15. 2
      common/actor/pom.xml
  16. 2
      common/cache/pom.xml
  17. 2
      common/cluster-api/pom.xml
  18. 2
      common/coap-server/pom.xml
  19. 2
      common/dao-api/pom.xml
  20. 9
      common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java
  21. 4
      common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java
  22. 2
      common/data/pom.xml
  23. 1
      common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java
  24. 4
      common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java
  25. 6
      common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java
  26. 2
      common/data/src/main/java/org/thingsboard/server/common/data/UsageInfo.java
  27. 3
      common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java
  28. 22
      common/data/src/main/java/org/thingsboard/server/common/data/widget/DeprecatedFilter.java
  29. 4
      common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java
  30. 7
      common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java
  31. 2
      common/edge-api/pom.xml
  32. 1
      common/edge-api/src/main/proto/edge.proto
  33. 2
      common/message/pom.xml
  34. 2
      common/pom.xml
  35. 2
      common/queue/pom.xml
  36. 2
      common/script/pom.xml
  37. 2
      common/script/remote-js-client/pom.xml
  38. 2
      common/script/script-api/pom.xml
  39. 20
      common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java
  40. 17
      common/script/script-api/src/main/java/org/thingsboard/script/api/js/AbstractJsInvokeService.java
  41. 17
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java
  42. 2
      common/stats/pom.xml
  43. 2
      common/transport/coap/pom.xml
  44. 2
      common/transport/http/pom.xml
  45. 2
      common/transport/lwm2m/pom.xml
  46. 2
      common/transport/mqtt/pom.xml
  47. 2
      common/transport/pom.xml
  48. 2
      common/transport/snmp/pom.xml
  49. 2
      common/transport/transport-api/pom.xml
  50. 2
      common/util/pom.xml
  51. 2
      common/version-control/pom.xml
  52. 6
      dao/pom.xml
  53. 6
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  54. 5
      dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java
  55. 9
      dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java
  56. 34
      dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeInfoEntity.java
  57. 55
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java
  58. 49
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
  59. 134
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java
  60. 31
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java
  61. 49
      dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java
  62. 3
      dao/src/main/java/org/thingsboard/server/dao/usage/BasicUsageInfoService.java
  63. 3
      dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java
  64. 16
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java
  65. 32
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java
  66. 4
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java
  67. 16
      dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java
  68. 2
      dao/src/main/resources/sql/schema-entities.sql
  69. 6
      dao/src/main/resources/sql/schema-views-and-functions.sql
  70. 8
      dao/src/test/java/org/thingsboard/server/dao/service/WidgetsBundleServiceTest.java
  71. 67
      dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
  72. 137
      dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java
  73. 2
      monitoring/pom.xml
  74. 2
      msa/black-box-tests/pom.xml
  75. 2
      msa/js-executor/package.json
  76. 2
      msa/js-executor/pom.xml
  77. 2
      msa/monitoring/pom.xml
  78. 2
      msa/pom.xml
  79. 2
      msa/tb-node/pom.xml
  80. 2
      msa/tb/pom.xml
  81. 2
      msa/transport/coap/pom.xml
  82. 2
      msa/transport/http/pom.xml
  83. 2
      msa/transport/lwm2m/pom.xml
  84. 2
      msa/transport/mqtt/pom.xml
  85. 2
      msa/transport/pom.xml
  86. 2
      msa/transport/snmp/pom.xml
  87. 2
      msa/vc-executor-docker/pom.xml
  88. 2
      msa/vc-executor/pom.xml
  89. 2
      msa/web-ui/package.json
  90. 2
      msa/web-ui/pom.xml
  91. 4
      netty-mqtt/pom.xml
  92. 8
      pom.xml
  93. 2
      rest-client/pom.xml
  94. 2
      rule-engine/pom.xml
  95. 2
      rule-engine/rule-engine-api/pom.xml
  96. 2
      rule-engine/rule-engine-components/pom.xml
  97. 2
      tools/pom.xml
  98. 2
      transport/coap/pom.xml
  99. 2
      transport/http/pom.xml
  100. 2
      transport/lwm2m/pom.xml

2
application/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>application</artifactId> <artifactId>application</artifactId>

1
application/src/main/data/upgrade/3.6.0/schema_update.sql

@ -24,3 +24,4 @@ ALTER TABLE notification DROP CONSTRAINT IF EXISTS fk_notification_request_id;
ALTER TABLE notification DROP CONSTRAINT IF EXISTS fk_notification_recipient_id; ALTER TABLE notification DROP CONSTRAINT IF EXISTS fk_notification_recipient_id;
CREATE INDEX IF NOT EXISTS idx_notification_notification_request_id ON notification(request_id); CREATE INDEX IF NOT EXISTS idx_notification_notification_request_id ON notification(request_id);
CREATE INDEX IF NOT EXISTS idx_notification_request_tenant_id ON notification_request(tenant_id); CREATE INDEX IF NOT EXISTS idx_notification_request_tenant_id ON notification_request(tenant_id);

54
application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java

@ -28,6 +28,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -36,6 +37,7 @@ import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
@ -46,6 +48,8 @@ import org.thingsboard.server.service.entitiy.widgets.type.TbWidgetTypeService;
import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Operation;
import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.permission.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER; import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER;
@ -75,7 +79,11 @@ public class WidgetTypeController extends AutoCommitController {
private static final String WIDGET_TYPE_INFO_DESCRIPTION = "Widget Type Info is a lightweight object that represents Widget Type but does not contain the heavyweight widget descriptor JSON"; private static final String WIDGET_TYPE_INFO_DESCRIPTION = "Widget Type Info is a lightweight object that represents Widget Type but does not contain the heavyweight widget descriptor JSON";
private static final String TENANT_ONLY_PARAM_DESCRIPTION = "Optional boolean parameter indicating whether only tenant widget types should be returned"; private static final String TENANT_ONLY_PARAM_DESCRIPTION = "Optional boolean parameter indicating whether only tenant widget types should be returned";
private static final String FULL_SEARCH_PARAM_DESCRIPTION = "Optional boolean parameter indicating whether search widgets by description not only by name"; private static final String FULL_SEARCH_PARAM_DESCRIPTION = "Optional boolean parameter indicating whether search widgets by description not only by name";
private static final String DEPRECATED_FILTER_ALLOWABLE_VALUES = "ALL, ACTUAL, DEPRECATED";
private static final String DEPRECATED_FILTER_PARAM_DESCRIPTION = "Optional string parameter indicating whether to include deprecated widgets";
private static final String UPDATE_EXISTING_BY_FQN_PARAM_DESCRIPTION = "Optional boolean parameter indicating whether to update existing widget type by FQN if present instead of creating new one"; private static final String UPDATE_EXISTING_BY_FQN_PARAM_DESCRIPTION = "Optional boolean parameter indicating whether to update existing widget type by FQN if present instead of creating new one";
private static final String WIDGET_TYPE_ARRAY_DESCRIPTION = "A list of string values separated by comma ',' representing one of the widget type value";
private static final String WIDGET_TYPE_ALLOWABLE_VALUES = "timeseries, latest, control, alarm, static";
@ApiOperation(value = "Get Widget Type Details (getWidgetTypeById)", @ApiOperation(value = "Get Widget Type Details (getWidgetTypeById)",
notes = "Get the Widget Type Details based on the provided Widget Type Id. " + WIDGET_TYPE_DETAILS_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) notes = "Get the Widget Type Details based on the provided Widget Type Id. " + WIDGET_TYPE_DETAILS_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@ -166,15 +174,22 @@ public class WidgetTypeController extends AutoCommitController {
@ApiParam(value = TENANT_ONLY_PARAM_DESCRIPTION) @ApiParam(value = TENANT_ONLY_PARAM_DESCRIPTION)
@RequestParam(required = false) Boolean tenantOnly, @RequestParam(required = false) Boolean tenantOnly,
@ApiParam(value = FULL_SEARCH_PARAM_DESCRIPTION) @ApiParam(value = FULL_SEARCH_PARAM_DESCRIPTION)
@RequestParam(required = false) Boolean fullSearch) throws ThingsboardException { @RequestParam(required = false) Boolean fullSearch,
@ApiParam(value = DEPRECATED_FILTER_PARAM_DESCRIPTION, allowableValues = DEPRECATED_FILTER_ALLOWABLE_VALUES)
@RequestParam(required = false) String deprecatedFilter,
@ApiParam(value = WIDGET_TYPE_ARRAY_DESCRIPTION, allowableValues = WIDGET_TYPE_ALLOWABLE_VALUES)
@RequestParam(required = false) String[] widgetTypeList) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
List<String> widgetTypes = widgetTypeList != null ? Arrays.asList(widgetTypeList) : Collections.emptyList();
boolean fullSearchBool = fullSearch != null && fullSearch;
DeprecatedFilter widgetTypeDeprecatedFilter = StringUtils.isNotEmpty(deprecatedFilter) ? DeprecatedFilter.valueOf(deprecatedFilter) : DeprecatedFilter.ALL;
if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
return checkNotNull(widgetTypeService.findSystemWidgetTypesByPageLink(getTenantId(), fullSearch != null && fullSearch, pageLink)); return checkNotNull(widgetTypeService.findSystemWidgetTypesByPageLink(getTenantId(), fullSearchBool, widgetTypeDeprecatedFilter, widgetTypes, pageLink));
} else { } else {
if (tenantOnly != null && tenantOnly) { if (tenantOnly != null && tenantOnly) {
return checkNotNull(widgetTypeService.findTenantWidgetTypesByTenantIdAndPageLink(getTenantId(), fullSearch != null && fullSearch, pageLink)); return checkNotNull(widgetTypeService.findTenantWidgetTypesByTenantIdAndPageLink(getTenantId(), fullSearchBool, widgetTypeDeprecatedFilter, widgetTypes, pageLink));
} else { } else {
return checkNotNull(widgetTypeService.findAllTenantWidgetTypesByTenantIdAndPageLink(getTenantId(), fullSearch != null && fullSearch, pageLink)); return checkNotNull(widgetTypeService.findAllTenantWidgetTypesByTenantIdAndPageLink(getTenantId(), fullSearchBool, widgetTypeDeprecatedFilter, widgetTypes, pageLink));
} }
} }
} }
@ -272,19 +287,40 @@ public class WidgetTypeController extends AutoCommitController {
tenantId = getCurrentUser().getTenantId(); tenantId = getCurrentUser().getTenantId();
} }
WidgetsBundle widgetsBundle = checkNotNull(widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(tenantId, bundleAlias)); WidgetsBundle widgetsBundle = checkNotNull(widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(tenantId, bundleAlias));
return checkNotNull(widgetTypeService.findWidgetTypesInfosByWidgetsBundleId(getTenantId(), widgetsBundle.getId())); return checkNotNull(widgetTypeService.findWidgetTypesInfosByWidgetsBundleId(getTenantId(), widgetsBundle.getId(), false, DeprecatedFilter.ALL,
null, new PageLink(1024))).getData();
} }
@ApiOperation(value = "Get Widget Type Info objects (getBundleWidgetTypesInfos)", @ApiOperation(value = "Get Widget Type Info objects (getBundleWidgetTypesInfos)",
notes = "Get the Widget Type Info objects based on the provided parameters. " + WIDGET_TYPE_INFO_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER) notes = "Get the Widget Type Info objects based on the provided parameters. " + WIDGET_TYPE_INFO_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/widgetTypesInfos", params = {"widgetsBundleId"}, method = RequestMethod.GET) @RequestMapping(value = "/widgetTypesInfos", params = {"widgetsBundleId", "pageSize", "page"}, method = RequestMethod.GET)
@ResponseBody @ResponseBody
public List<WidgetTypeInfo> getBundleWidgetTypesInfos( public PageData<WidgetTypeInfo> getBundleWidgetTypesInfos(
@ApiParam(value = "Widget Bundle Id", required = true) @ApiParam(value = "Widget Bundle Id", required = true)
@RequestParam("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { @RequestParam("widgetsBundleId") String strWidgetsBundleId,
@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
@RequestParam int pageSize,
@ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
@RequestParam int page,
@ApiParam(value = WIDGET_TYPE_TEXT_SEARCH_DESCRIPTION)
@RequestParam(required = false) String textSearch,
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = WIDGET_TYPE_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder,
@ApiParam(value = FULL_SEARCH_PARAM_DESCRIPTION)
@RequestParam(required = false) Boolean fullSearch,
@ApiParam(value = DEPRECATED_FILTER_PARAM_DESCRIPTION, allowableValues = DEPRECATED_FILTER_ALLOWABLE_VALUES)
@RequestParam(required = false) String deprecatedFilter,
@ApiParam(value = WIDGET_TYPE_ARRAY_DESCRIPTION, allowableValues = WIDGET_TYPE_ALLOWABLE_VALUES)
@RequestParam(required = false) String[] widgetTypeList) throws ThingsboardException {
WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId));
return checkNotNull(widgetTypeService.findWidgetTypesInfosByWidgetsBundleId(getTenantId(), widgetsBundleId)); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
List<String> widgetTypes = widgetTypeList != null ? Arrays.asList(widgetTypeList) : Collections.emptyList();
DeprecatedFilter widgetTypeDeprecatedFilter = StringUtils.isNotEmpty(deprecatedFilter) ? DeprecatedFilter.valueOf(deprecatedFilter) : DeprecatedFilter.ALL;
return checkNotNull(widgetTypeService.findWidgetTypesInfosByWidgetsBundleId(getTenantId(), widgetsBundleId, fullSearch != null && fullSearch,
widgetTypeDeprecatedFilter, widgetTypes, pageLink));
} }
@ApiOperation(value = "Get Widget Type (getWidgetTypeByBundleAliasAndTypeAlias) (Deprecated)", @ApiOperation(value = "Get Widget Type (getWidgetTypeByBundleAliasAndTypeAlias) (Deprecated)",

9
application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java

@ -68,6 +68,7 @@ public class WidgetsBundleController extends BaseController {
private final TbWidgetsBundleService tbWidgetsBundleService; private final TbWidgetsBundleService tbWidgetsBundleService;
private static final String WIDGET_BUNDLE_DESCRIPTION = "Widget Bundle represents a group(bundle) of widgets. Widgets are grouped into bundle by type or use case. "; private static final String WIDGET_BUNDLE_DESCRIPTION = "Widget Bundle represents a group(bundle) of widgets. Widgets are grouped into bundle by type or use case. ";
private static final String FULL_SEARCH_PARAM_DESCRIPTION = "Optional boolean parameter indicating extended search of widget bundles by description and by name / description of related widget types";
@ApiOperation(value = "Get Widget Bundle (getWidgetsBundleById)", @ApiOperation(value = "Get Widget Bundle (getWidgetsBundleById)",
notes = "Get the Widget Bundle based on the provided Widget Bundle Id. " + WIDGET_BUNDLE_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER) notes = "Get the Widget Bundle based on the provided Widget Bundle Id. " + WIDGET_BUNDLE_DESCRIPTION + AVAILABLE_FOR_ANY_AUTHORIZED_USER)
@ -183,13 +184,15 @@ public class WidgetsBundleController extends BaseController {
@ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES) @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortProperty, @RequestParam(required = false) String sortProperty,
@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
@RequestParam(required = false) String sortOrder) throws ThingsboardException { @RequestParam(required = false) String sortOrder,
@ApiParam(value = FULL_SEARCH_PARAM_DESCRIPTION)
@RequestParam(required = false) Boolean fullSearch) throws ThingsboardException {
PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) {
return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), pageLink)); return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), fullSearch != null && fullSearch, pageLink));
} else { } else {
TenantId tenantId = getCurrentUser().getTenantId(); TenantId tenantId = getCurrentUser().getTenantId();
return checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, pageLink)); return checkNotNull(widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, fullSearch != null && fullSearch, pageLink));
} }
} }

3
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -262,6 +262,9 @@ public class ThingsboardInstallService {
databaseEntitiesUpgradeService.upgradeDatabase("3.5.1"); databaseEntitiesUpgradeService.upgradeDatabase("3.5.1");
dataUpdateService.updateData("3.5.1"); dataUpdateService.updateData("3.5.1");
systemDataLoaderService.updateDefaultNotificationConfigs(); systemDataLoaderService.updateDefaultNotificationConfigs();
case "3.6.0":
log.info("Upgrading ThingsBoard from version 3.6.0 to 3.6.1 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.6.0");
//TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache //TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache
break; break;
default: default:

5
application/src/main/java/org/thingsboard/server/service/apiusage/BaseApiUsageState.java

@ -145,6 +145,8 @@ public abstract class BaseApiUsageState {
return apiUsageState.getDbStorageState(); return apiUsageState.getDbStorageState();
case JS: case JS:
return apiUsageState.getJsExecState(); return apiUsageState.getJsExecState();
case TBEL:
return apiUsageState.getTbelExecState();
case EMAIL: case EMAIL:
return apiUsageState.getEmailExecState(); return apiUsageState.getEmailExecState();
case SMS: case SMS:
@ -171,6 +173,9 @@ public abstract class BaseApiUsageState {
case JS: case JS:
apiUsageState.setJsExecState(value); apiUsageState.setJsExecState(value);
break; break;
case TBEL:
apiUsageState.setTbelExecState(value);
break;
case EMAIL: case EMAIL:
apiUsageState.setEmailExecState(value); apiUsageState.setEmailExecState(value);
break; break;

5
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeMsgConstructor.java

@ -24,6 +24,8 @@ import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg; import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg;
import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.queue.util.TbCoreComponent;
import java.util.Arrays;
@Component @Component
@TbCoreComponent @TbCoreComponent
public class WidgetTypeMsgConstructor { public class WidgetTypeMsgConstructor {
@ -59,6 +61,9 @@ public class WidgetTypeMsgConstructor {
builder.setDescription(widgetTypeDetails.getDescription()); builder.setDescription(widgetTypeDetails.getDescription());
} }
builder.setDeprecated(widgetTypeDetails.isDeprecated()); builder.setDeprecated(widgetTypeDetails.isDeprecated());
if (widgetTypeDetails.getTags() != null) {
builder.addAllTags(Arrays.asList(widgetTypeDetails.getTags()));
}
return builder.build(); return builder.build();
} }

3
application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/SystemWidgetTypesEdgeEventFetcher.java

@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetTypeService;
@ -31,6 +32,6 @@ public class SystemWidgetTypesEdgeEventFetcher extends BaseWidgetTypesEdgeEventF
@Override @Override
protected PageData<WidgetTypeInfo> findWidgetTypes(TenantId tenantId, PageLink pageLink) { protected PageData<WidgetTypeInfo> findWidgetTypes(TenantId tenantId, PageLink pageLink) {
return widgetTypeService.findSystemWidgetTypesByPageLink(tenantId, false, pageLink); return widgetTypeService.findSystemWidgetTypesByPageLink(tenantId, false, DeprecatedFilter.ALL, null, pageLink);
} }
} }

2
application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/SystemWidgetsBundlesEdgeEventFetcher.java

@ -31,6 +31,6 @@ public class SystemWidgetsBundlesEdgeEventFetcher extends BaseWidgetsBundlesEdge
@Override @Override
protected PageData<WidgetsBundle> findWidgetsBundles(TenantId tenantId, PageLink pageLink) { protected PageData<WidgetsBundle> findWidgetsBundles(TenantId tenantId, PageLink pageLink) {
return widgetsBundleService.findSystemWidgetsBundlesByPageLink(tenantId, pageLink); return widgetsBundleService.findSystemWidgetsBundlesByPageLink(tenantId, false, pageLink);
} }
} }

3
application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/TenantWidgetTypesEdgeEventFetcher.java

@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
import org.thingsboard.server.dao.widget.WidgetTypeService; import org.thingsboard.server.dao.widget.WidgetTypeService;
@ -30,6 +31,6 @@ public class TenantWidgetTypesEdgeEventFetcher extends BaseWidgetTypesEdgeEventF
} }
@Override @Override
protected PageData<WidgetTypeInfo> findWidgetTypes(TenantId tenantId, PageLink pageLink) { protected PageData<WidgetTypeInfo> findWidgetTypes(TenantId tenantId, PageLink pageLink) {
return widgetTypeService.findTenantWidgetTypesByTenantIdAndPageLink(tenantId, false, pageLink); return widgetTypeService.findTenantWidgetTypesByTenantIdAndPageLink(tenantId, false, DeprecatedFilter.ALL, null, pageLink);
} }
} }

16
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -63,6 +63,7 @@ import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
import org.thingsboard.server.common.data.kv.BooleanDataEntry; import org.thingsboard.server.common.data.kv.BooleanDataEntry;
import org.thingsboard.server.common.data.kv.DoubleDataEntry; import org.thingsboard.server.common.data.kv.DoubleDataEntry;
import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.LongDataEntry;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.query.BooleanFilterPredicate; import org.thingsboard.server.common.data.query.BooleanFilterPredicate;
@ -83,6 +84,8 @@ import org.thingsboard.server.common.data.security.UserCredentials;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; import org.thingsboard.server.common.data.tenant.profile.TenantProfileData;
import org.thingsboard.server.common.data.tenant.profile.TenantProfileQueueConfiguration; import org.thingsboard.server.common.data.tenant.profile.TenantProfileQueueConfiguration;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.customer.CustomerService;
@ -489,10 +492,15 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
public void deleteSystemWidgetBundle(String bundleAlias) throws Exception { public void deleteSystemWidgetBundle(String bundleAlias) throws Exception {
WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(TenantId.SYS_TENANT_ID, bundleAlias); WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(TenantId.SYS_TENANT_ID, bundleAlias);
if (widgetsBundle != null) { if (widgetsBundle != null) {
var widgetTypes = widgetTypeService.findWidgetTypesInfosByWidgetsBundleId(TenantId.SYS_TENANT_ID, widgetsBundle.getId()); PageData<WidgetTypeInfo> widgetTypes;
for (var widgetType : widgetTypes) { var pageLink = new PageLink(1024);
widgetTypeService.deleteWidgetType(TenantId.SYS_TENANT_ID, widgetType.getId()); do {
} widgetTypes = widgetTypeService.findWidgetTypesInfosByWidgetsBundleId(TenantId.SYS_TENANT_ID, widgetsBundle.getId(), false, DeprecatedFilter.ALL, null, pageLink);
for (var widgetType : widgetTypes.getData()) {
widgetTypeService.deleteWidgetType(TenantId.SYS_TENANT_ID, widgetType.getId());
}
pageLink.nextPageLink();
} while (widgetTypes.hasNext());
widgetsBundleService.deleteWidgetsBundle(TenantId.SYS_TENANT_ID, widgetsBundle.getId()); widgetsBundleService.deleteWidgetsBundle(TenantId.SYS_TENANT_ID, widgetsBundle.getId());
} }
} }

15
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java

@ -777,6 +777,21 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.error("Failed updating schema!!!", e); log.error("Failed updating schema!!!", e);
} }
break; break;
case "3.6.0":
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
if (isOldSchema(conn, 3006000)) {
log.info("Updating schema ...");
schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.6.0", SCHEMA_UPDATE_SQL);
loadSql(schemaUpdateFile, conn);
conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3006001;");
log.info("Schema updated to version 3.6.1.");
} else {
log.info("Skip schema re-update to version 3.6.1. Use env flag 'SKIP_SCHEMA_VERSION_CHECK' to force the re-update.");
}
} catch (Exception e) {
log.error("Failed updating schema!!!", e);
}
break;
default: default:
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
} }

4
application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java

@ -362,6 +362,8 @@ public class DefaultMailService implements MailService {
return valueInM + " out of " + thresholdInM + " allowed messages"; return valueInM + " out of " + thresholdInM + " allowed messages";
case JS_EXEC_COUNT: case JS_EXEC_COUNT:
return valueInM + " out of " + thresholdInM + " allowed JavaScript functions"; return valueInM + " out of " + thresholdInM + " allowed JavaScript functions";
case TBEL_EXEC_COUNT:
return valueInM + " out of " + thresholdInM + " allowed Tbel functions";
case RE_EXEC_COUNT: case RE_EXEC_COUNT:
return valueInM + " out of " + thresholdInM + " allowed Rule Engine messages"; return valueInM + " out of " + thresholdInM + " allowed Rule Engine messages";
case EMAIL_EXEC_COUNT: case EMAIL_EXEC_COUNT:
@ -382,6 +384,8 @@ public class DefaultMailService implements MailService {
return recordState.getValueAsString() + " messages"; return recordState.getValueAsString() + " messages";
case JS_EXEC_COUNT: case JS_EXEC_COUNT:
return "JavaScript functions " + recordState.getValueAsString() + " times"; return "JavaScript functions " + recordState.getValueAsString() + " times";
case TBEL_EXEC_COUNT:
return "TBEL functions " + recordState.getValueAsString() + " times";
case RE_EXEC_COUNT: case RE_EXEC_COUNT:
return recordState.getValueAsString() + " Rule Engine messages"; return recordState.getValueAsString() + " Rule Engine messages";
case EMAIL_EXEC_COUNT: case EMAIL_EXEC_COUNT:

3
application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java

@ -417,6 +417,9 @@ public class HomePageApiTest extends AbstractControllerTest {
Assert.assertEquals(0, usageInfo.getJsExecutions()); Assert.assertEquals(0, usageInfo.getJsExecutions());
Assert.assertEquals(configuration.getMaxJSExecutions(), usageInfo.getMaxJsExecutions()); Assert.assertEquals(configuration.getMaxJSExecutions(), usageInfo.getMaxJsExecutions());
Assert.assertEquals(0, usageInfo.getTbelExecutions());
Assert.assertEquals(configuration.getMaxTbelExecutions(), usageInfo.getMaxTbelExecutions());
Assert.assertEquals(0, usageInfo.getEmails()); Assert.assertEquals(0, usageInfo.getEmails());
Assert.assertEquals(configuration.getMaxEmails(), usageInfo.getMaxEmails()); Assert.assertEquals(configuration.getMaxEmails(), usageInfo.getMaxEmails());

2
common/actor/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/cache/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/cluster-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/coap-server/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/dao-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

9
common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeService.java

@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
@ -39,17 +40,17 @@ public interface WidgetTypeService extends EntityDaoService {
void deleteWidgetType(TenantId tenantId, WidgetTypeId widgetTypeId); void deleteWidgetType(TenantId tenantId, WidgetTypeId widgetTypeId);
PageData<WidgetTypeInfo> findSystemWidgetTypesByPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink); PageData<WidgetTypeInfo> findSystemWidgetTypesByPageLink(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink); PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink); PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
List<WidgetType> findWidgetTypesByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId); List<WidgetType> findWidgetTypesByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId);
List<WidgetTypeDetails> findWidgetTypesDetailsByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId); List<WidgetTypeDetails> findWidgetTypesDetailsByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId);
List<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId); PageData<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
List<String> findWidgetFqnsByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId); List<String> findWidgetFqnsByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId);

4
common/dao-api/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleService.java

@ -34,13 +34,13 @@ public interface WidgetsBundleService extends EntityDaoService {
WidgetsBundle findWidgetsBundleByTenantIdAndAlias(TenantId tenantId, String alias); WidgetsBundle findWidgetsBundleByTenantIdAndAlias(TenantId tenantId, String alias);
PageData<WidgetsBundle> findSystemWidgetsBundlesByPageLink(TenantId tenantId, PageLink pageLink); PageData<WidgetsBundle> findSystemWidgetsBundlesByPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink);
List<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId); List<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId);
PageData<WidgetsBundle> findTenantWidgetsBundlesByTenantId(TenantId tenantId, PageLink pageLink); PageData<WidgetsBundle> findTenantWidgetsBundlesByTenantId(TenantId tenantId, PageLink pageLink);
PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink); PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink);
List<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(TenantId tenantId); List<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(TenantId tenantId);

2
common/data/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

1
common/data/src/main/java/org/thingsboard/server/common/data/ApiFeature.java

@ -22,6 +22,7 @@ public enum ApiFeature {
DB("dbApiState", "Telemetry persistence"), DB("dbApiState", "Telemetry persistence"),
RE("ruleEngineApiState", "Rule Engine execution"), RE("ruleEngineApiState", "Rule Engine execution"),
JS("jsExecutionApiState", "JavaScript functions execution"), JS("jsExecutionApiState", "JavaScript functions execution"),
TBEL("tbelExecutionApiState", "Tbel functions execution"),
EMAIL("emailApiState", "Email messages"), EMAIL("emailApiState", "Email messages"),
SMS("smsApiState", "SMS messages"), SMS("smsApiState", "SMS messages"),
ALARM("alarmApiState", "Alarms"); ALARM("alarmApiState", "Alarms");

4
common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageRecordKey.java

@ -24,6 +24,7 @@ public enum ApiUsageRecordKey {
STORAGE_DP_COUNT(ApiFeature.DB, "storageDataPointsCount", "storageDataPointsLimit", "data point"), STORAGE_DP_COUNT(ApiFeature.DB, "storageDataPointsCount", "storageDataPointsLimit", "data point"),
RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit", "Rule Engine execution"), RE_EXEC_COUNT(ApiFeature.RE, "ruleEngineExecutionCount", "ruleEngineExecutionLimit", "Rule Engine execution"),
JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit", "JavaScript execution"), JS_EXEC_COUNT(ApiFeature.JS, "jsExecutionCount", "jsExecutionLimit", "JavaScript execution"),
TBEL_EXEC_COUNT(ApiFeature.TBEL, "tbelExecutionCount", "tbelExecutionLimit", "Tbel execution"),
EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit", "email message"), EMAIL_EXEC_COUNT(ApiFeature.EMAIL, "emailCount", "emailLimit", "email message"),
SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit", "SMS message"), SMS_EXEC_COUNT(ApiFeature.SMS, "smsCount", "smsLimit", "SMS message"),
CREATED_ALARMS_COUNT(ApiFeature.ALARM, "createdAlarmsCount", "createdAlarmsLimit", "alarm"), CREATED_ALARMS_COUNT(ApiFeature.ALARM, "createdAlarmsCount", "createdAlarmsLimit", "alarm"),
@ -31,6 +32,7 @@ public enum ApiUsageRecordKey {
INACTIVE_DEVICES("inactiveDevicesCount"); INACTIVE_DEVICES("inactiveDevicesCount");
private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT}; private static final ApiUsageRecordKey[] JS_RECORD_KEYS = {JS_EXEC_COUNT};
private static final ApiUsageRecordKey[] TBEL_RECORD_KEYS = {TBEL_EXEC_COUNT};
private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT}; private static final ApiUsageRecordKey[] RE_RECORD_KEYS = {RE_EXEC_COUNT};
private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT}; private static final ApiUsageRecordKey[] DB_RECORD_KEYS = {STORAGE_DP_COUNT};
private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT}; private static final ApiUsageRecordKey[] TRANSPORT_RECORD_KEYS = {TRANSPORT_MSG_COUNT, TRANSPORT_DP_COUNT};
@ -75,6 +77,8 @@ public enum ApiUsageRecordKey {
return RE_RECORD_KEYS; return RE_RECORD_KEYS;
case JS: case JS:
return JS_RECORD_KEYS; return JS_RECORD_KEYS;
case TBEL:
return TBEL_RECORD_KEYS;
case EMAIL: case EMAIL:
return EMAIL_RECORD_KEYS; return EMAIL_RECORD_KEYS;
case SMS: case SMS:

6
common/data/src/main/java/org/thingsboard/server/common/data/ApiUsageState.java

@ -37,6 +37,7 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
private ApiUsageStateValue dbStorageState; private ApiUsageStateValue dbStorageState;
private ApiUsageStateValue reExecState; private ApiUsageStateValue reExecState;
private ApiUsageStateValue jsExecState; private ApiUsageStateValue jsExecState;
private ApiUsageStateValue tbelExecState;
private ApiUsageStateValue emailExecState; private ApiUsageStateValue emailExecState;
private ApiUsageStateValue smsExecState; private ApiUsageStateValue smsExecState;
private ApiUsageStateValue alarmExecState; private ApiUsageStateValue alarmExecState;
@ -57,6 +58,7 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
this.dbStorageState = ur.getDbStorageState(); this.dbStorageState = ur.getDbStorageState();
this.reExecState = ur.getReExecState(); this.reExecState = ur.getReExecState();
this.jsExecState = ur.getJsExecState(); this.jsExecState = ur.getJsExecState();
this.tbelExecState = ur.getTbelExecState();
this.emailExecState = ur.getEmailExecState(); this.emailExecState = ur.getEmailExecState();
this.smsExecState = ur.getSmsExecState(); this.smsExecState = ur.getSmsExecState();
this.alarmExecState = ur.getAlarmExecState(); this.alarmExecState = ur.getAlarmExecState();
@ -78,6 +80,10 @@ public class ApiUsageState extends BaseData<ApiUsageStateId> implements HasTenan
return !ApiUsageStateValue.DISABLED.equals(jsExecState); return !ApiUsageStateValue.DISABLED.equals(jsExecState);
} }
public boolean isTbelExecEnabled() {
return !ApiUsageStateValue.DISABLED.equals(tbelExecState);
}
public boolean isEmailSendEnabled(){ public boolean isEmailSendEnabled(){
return !ApiUsageStateValue.DISABLED.equals(emailExecState); return !ApiUsageStateValue.DISABLED.equals(emailExecState);
} }

2
common/data/src/main/java/org/thingsboard/server/common/data/UsageInfo.java

@ -33,7 +33,9 @@ public class UsageInfo {
private long transportMessages; private long transportMessages;
private long maxTransportMessages; private long maxTransportMessages;
private long jsExecutions; private long jsExecutions;
private long tbelExecutions;
private long maxJsExecutions; private long maxJsExecutions;
private long maxTbelExecutions;
private long emails; private long emails;
private long maxEmails; private long maxEmails;
private long sms; private long sms;

3
common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java

@ -56,6 +56,7 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
private long maxTransportDataPoints; private long maxTransportDataPoints;
private long maxREExecutions; private long maxREExecutions;
private long maxJSExecutions; private long maxJSExecutions;
private long maxTbelExecutions;
private long maxDPStorageDays; private long maxDPStorageDays;
private int maxRuleNodeExecutionsPerMessage; private int maxRuleNodeExecutionsPerMessage;
private long maxEmails; private long maxEmails;
@ -96,6 +97,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura
return maxTransportDataPoints; return maxTransportDataPoints;
case JS_EXEC_COUNT: case JS_EXEC_COUNT:
return maxJSExecutions; return maxJSExecutions;
case TBEL_EXEC_COUNT:
return maxTbelExecutions;
case RE_EXEC_COUNT: case RE_EXEC_COUNT:
return maxREExecutions; return maxREExecutions;
case STORAGE_DP_COUNT: case STORAGE_DP_COUNT:

22
common/data/src/main/java/org/thingsboard/server/common/data/widget/DeprecatedFilter.java

@ -0,0 +1,22 @@
/**
* 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.common.data.widget;
public enum DeprecatedFilter {
ALL,
ACTUAL,
DEPRECATED
}

4
common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java

@ -38,6 +38,9 @@ public class WidgetTypeDetails extends WidgetType implements HasName, HasTenantI
@Length(fieldName = "description", max = 1024) @Length(fieldName = "description", max = 1024)
@ApiModelProperty(position = 10, value = "Description of the widget") @ApiModelProperty(position = 10, value = "Description of the widget")
private String description; private String description;
@NoXss
@ApiModelProperty(position = 11, value = "Tags of the widget type")
private String[] tags;
@Getter @Getter
@Setter @Setter
@ -59,6 +62,7 @@ public class WidgetTypeDetails extends WidgetType implements HasName, HasTenantI
super(widgetTypeDetails); super(widgetTypeDetails);
this.image = widgetTypeDetails.getImage(); this.image = widgetTypeDetails.getImage();
this.description = widgetTypeDetails.getDescription(); this.description = widgetTypeDetails.getDescription();
this.tags = widgetTypeDetails.getTags();
this.externalId = widgetTypeDetails.getExternalId(); this.externalId = widgetTypeDetails.getExternalId();
} }
} }

7
common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java

@ -29,7 +29,10 @@ public class WidgetTypeInfo extends BaseWidgetType {
@ApiModelProperty(position = 9, value = "Description of the widget type", accessMode = ApiModelProperty.AccessMode.READ_ONLY) @ApiModelProperty(position = 9, value = "Description of the widget type", accessMode = ApiModelProperty.AccessMode.READ_ONLY)
private String description; private String description;
@NoXss @NoXss
@ApiModelProperty(position = 10, value = "Type of the widget (timeseries, latest, control, alarm or static)", accessMode = ApiModelProperty.AccessMode.READ_ONLY) @ApiModelProperty(position = 10, value = "Tags of the widget type", accessMode = ApiModelProperty.AccessMode.READ_ONLY)
private String[] tags;
@NoXss
@ApiModelProperty(position = 11, value = "Type of the widget (timeseries, latest, control, alarm or static)", accessMode = ApiModelProperty.AccessMode.READ_ONLY)
private String widgetType; private String widgetType;
public WidgetTypeInfo() { public WidgetTypeInfo() {
@ -48,6 +51,7 @@ public class WidgetTypeInfo extends BaseWidgetType {
super(widgetTypeInfo); super(widgetTypeInfo);
this.image = widgetTypeInfo.getImage(); this.image = widgetTypeInfo.getImage();
this.description = widgetTypeInfo.getDescription(); this.description = widgetTypeInfo.getDescription();
this.tags = widgetTypeInfo.getTags();
this.widgetType = widgetTypeInfo.getWidgetType(); this.widgetType = widgetTypeInfo.getWidgetType();
} }
@ -55,6 +59,7 @@ public class WidgetTypeInfo extends BaseWidgetType {
super(widgetTypeDetails); super(widgetTypeDetails);
this.image = widgetTypeDetails.getImage(); this.image = widgetTypeDetails.getImage();
this.description = widgetTypeDetails.getDescription(); this.description = widgetTypeDetails.getDescription();
this.tags = widgetTypeDetails.getTags();
if (widgetTypeDetails.getDescriptor() != null && widgetTypeDetails.getDescriptor().has("type")) { if (widgetTypeDetails.getDescriptor() != null && widgetTypeDetails.getDescriptor().has("type")) {
this.widgetType = widgetTypeDetails.getDescriptor().get("type").asText(); this.widgetType = widgetTypeDetails.getDescriptor().get("type").asText();
} else { } else {

2
common/edge-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

1
common/edge-api/src/main/proto/edge.proto

@ -377,6 +377,7 @@ message WidgetTypeUpdateMsg {
optional string description = 10; optional string description = 10;
optional string fqn = 11; optional string fqn = 11;
bool deprecated = 12; bool deprecated = 12;
repeated string tags = 13;
} }
message AdminSettingsUpdateMsg { message AdminSettingsUpdateMsg {

2
common/message/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>common</artifactId> <artifactId>common</artifactId>

2
common/queue/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/script/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/script/remote-js-client/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>script</artifactId> <artifactId>script</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common.script</groupId> <groupId>org.thingsboard.common.script</groupId>

2
common/script/script-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>script</artifactId> <artifactId>script</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common.script</groupId> <groupId>org.thingsboard.common.script</groupId>

20
common/script/script-api/src/main/java/org/thingsboard/script/api/AbstractScriptInvokeService.java

@ -25,11 +25,8 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.ApiUsageRecordKey;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.common.stats.TbApiUsageStateClient;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -45,9 +42,6 @@ import static java.lang.String.format;
public abstract class AbstractScriptInvokeService implements ScriptInvokeService { public abstract class AbstractScriptInvokeService implements ScriptInvokeService {
protected final Map<UUID, BlockedScriptInfo> disabledScripts = new ConcurrentHashMap<>(); protected final Map<UUID, BlockedScriptInfo> disabledScripts = new ConcurrentHashMap<>();
private final Optional<TbApiUsageStateClient> apiUsageStateClient;
private final Optional<TbApiUsageReportClient> apiUsageReportClient;
private final AtomicInteger pushedMsgs = new AtomicInteger(0); private final AtomicInteger pushedMsgs = new AtomicInteger(0);
private final AtomicInteger invokeMsgs = new AtomicInteger(0); private final AtomicInteger invokeMsgs = new AtomicInteger(0);
private final AtomicInteger evalMsgs = new AtomicInteger(0); private final AtomicInteger evalMsgs = new AtomicInteger(0);
@ -59,11 +53,6 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService
protected ScheduledExecutorService timeoutExecutorService; protected ScheduledExecutorService timeoutExecutorService;
protected AbstractScriptInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
this.apiUsageStateClient = apiUsageStateClient;
this.apiUsageReportClient = apiUsageReportClient;
}
protected long getMaxEvalRequestsTimeout() { protected long getMaxEvalRequestsTimeout() {
return getMaxInvokeRequestsTimeout(); return getMaxInvokeRequestsTimeout();
} }
@ -88,6 +77,9 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService
protected abstract boolean isScriptPresent(UUID scriptId); protected abstract boolean isScriptPresent(UUID scriptId);
protected abstract boolean isExecEnabled(TenantId tenantId);
protected abstract void reportExecution(TenantId tenantId, CustomerId customerId);
protected abstract ListenableFuture<UUID> doEvalScript(TenantId tenantId, ScriptType scriptType, String scriptBody, UUID scriptId, String[] argNames); protected abstract ListenableFuture<UUID> doEvalScript(TenantId tenantId, ScriptType scriptType, String scriptBody, UUID scriptId, String[] argNames);
protected abstract TbScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args); protected abstract TbScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args);
@ -122,7 +114,7 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService
@Override @Override
public ListenableFuture<UUID> eval(TenantId tenantId, ScriptType scriptType, String scriptBody, String... argNames) { public ListenableFuture<UUID> eval(TenantId tenantId, ScriptType scriptType, String scriptBody, String... argNames) {
if (!apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled()) { if (isExecEnabled(tenantId)) {
if (scriptBodySizeExceeded(scriptBody)) { if (scriptBodySizeExceeded(scriptBody)) {
return error(format("Script body exceeds maximum allowed size of %s symbols", getMaxScriptBodySize())); return error(format("Script body exceeds maximum allowed size of %s symbols", getMaxScriptBodySize()));
} }
@ -137,7 +129,7 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService
@Override @Override
public ListenableFuture<Object> invokeScript(TenantId tenantId, CustomerId customerId, UUID scriptId, Object... args) { public ListenableFuture<Object> invokeScript(TenantId tenantId, CustomerId customerId, UUID scriptId, Object... args) {
if (!apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled()) { if (isExecEnabled(tenantId)) {
if (!isScriptPresent(scriptId)) { if (!isScriptPresent(scriptId)) {
return error("No compiled script found for scriptId: [" + scriptId + "]!"); return error("No compiled script found for scriptId: [" + scriptId + "]!");
} }
@ -148,7 +140,7 @@ public abstract class AbstractScriptInvokeService implements ScriptInvokeService
)); ));
return Futures.immediateFailedFuture(handleScriptException(scriptId, null, t)); return Futures.immediateFailedFuture(handleScriptException(scriptId, null, t));
} }
apiUsageReportClient.ifPresent(client -> client.report(tenantId, customerId, ApiUsageRecordKey.JS_EXEC_COUNT, 1)); reportExecution(tenantId, customerId);
pushedMsgs.incrementAndGet(); pushedMsgs.incrementAndGet();
log.trace("[{}] InvokeScript uuid {} with timeout {}ms", tenantId, scriptId, getMaxInvokeRequestsTimeout()); log.trace("[{}] InvokeScript uuid {} with timeout {}ms", tenantId, scriptId, getMaxInvokeRequestsTimeout());
var task = doInvokeFunction(scriptId, args); var task = doInvokeFunction(scriptId, args);

17
common/script/script-api/src/main/java/org/thingsboard/script/api/js/AbstractJsInvokeService.java

@ -23,6 +23,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.thingsboard.script.api.AbstractScriptInvokeService; import org.thingsboard.script.api.AbstractScriptInvokeService;
import org.thingsboard.script.api.RuleNodeScriptFactory; import org.thingsboard.script.api.RuleNodeScriptFactory;
import org.thingsboard.script.api.ScriptType; import org.thingsboard.script.api.ScriptType;
import org.thingsboard.server.common.data.ApiUsageRecordKey;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.common.stats.TbApiUsageStateClient; import org.thingsboard.server.common.stats.TbApiUsageStateClient;
@ -39,6 +41,8 @@ import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractJsInvokeService extends AbstractScriptInvokeService implements JsInvokeService { public abstract class AbstractJsInvokeService extends AbstractScriptInvokeService implements JsInvokeService {
protected final Map<UUID, JsScriptInfo> scriptInfoMap = new ConcurrentHashMap<>(); protected final Map<UUID, JsScriptInfo> scriptInfoMap = new ConcurrentHashMap<>();
private final Optional<TbApiUsageStateClient> apiUsageStateClient;
private final Optional<TbApiUsageReportClient> apiUsageReportClient;
@Getter @Getter
@Value("${js.max_total_args_size:100000}") @Value("${js.max_total_args_size:100000}")
@ -51,7 +55,8 @@ public abstract class AbstractJsInvokeService extends AbstractScriptInvokeServic
private long maxScriptBodySize; private long maxScriptBodySize;
protected AbstractJsInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) { protected AbstractJsInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
super(apiUsageStateClient, apiUsageReportClient); this.apiUsageStateClient = apiUsageStateClient;
this.apiUsageReportClient = apiUsageReportClient;
} }
@Override @Override
@ -59,6 +64,16 @@ public abstract class AbstractJsInvokeService extends AbstractScriptInvokeServic
return scriptInfoMap.containsKey(scriptId); return scriptInfoMap.containsKey(scriptId);
} }
@Override
protected boolean isExecEnabled(TenantId tenantId) {
return !apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isJsExecEnabled();
}
@Override
protected void reportExecution(TenantId tenantId, CustomerId customerId) {
apiUsageReportClient.ifPresent(client -> client.report(tenantId, customerId, ApiUsageRecordKey.JS_EXEC_COUNT, 1));
}
@Override @Override
protected JsScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args) { protected JsScriptExecutionTask doInvokeFunction(UUID scriptId, Object[] args) {
return new JsScriptExecutionTask(doInvokeFunction(scriptId, scriptInfoMap.get(scriptId), args)); return new JsScriptExecutionTask(doInvokeFunction(scriptId, scriptInfoMap.get(scriptId), args));

17
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java

@ -40,6 +40,8 @@ import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.script.api.AbstractScriptInvokeService; import org.thingsboard.script.api.AbstractScriptInvokeService;
import org.thingsboard.script.api.ScriptType; import org.thingsboard.script.api.ScriptType;
import org.thingsboard.script.api.TbScriptException; import org.thingsboard.script.api.TbScriptException;
import org.thingsboard.server.common.data.ApiUsageRecordKey;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.common.stats.TbApiUsageReportClient;
import org.thingsboard.server.common.stats.TbApiUsageStateClient; import org.thingsboard.server.common.stats.TbApiUsageStateClient;
@ -69,6 +71,8 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem
protected Cache<String, Serializable> compiledScriptsCache; protected Cache<String, Serializable> compiledScriptsCache;
private SandboxedParserConfiguration parserConfig; private SandboxedParserConfiguration parserConfig;
private final Optional<TbApiUsageStateClient> apiUsageStateClient;
private final Optional<TbApiUsageReportClient> apiUsageReportClient;
@Getter @Getter
@Value("${tbel.max_total_args_size:100000}") @Value("${tbel.max_total_args_size:100000}")
@ -110,7 +114,8 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem
private final Lock lock = new ReentrantLock(); private final Lock lock = new ReentrantLock();
protected DefaultTbelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) { protected DefaultTbelInvokeService(Optional<TbApiUsageStateClient> apiUsageStateClient, Optional<TbApiUsageReportClient> apiUsageReportClient) {
super(apiUsageStateClient, apiUsageReportClient); this.apiUsageStateClient = apiUsageStateClient;
this.apiUsageReportClient = apiUsageReportClient;
} }
@Scheduled(fixedDelayString = "${tbel.stats.print_interval_ms:10000}") @Scheduled(fixedDelayString = "${tbel.stats.print_interval_ms:10000}")
@ -167,6 +172,16 @@ public class DefaultTbelInvokeService extends AbstractScriptInvokeService implem
return scriptIdToHash.containsKey(scriptId); return scriptIdToHash.containsKey(scriptId);
} }
@Override
protected boolean isExecEnabled(TenantId tenantId) {
return !apiUsageStateClient.isPresent() || apiUsageStateClient.get().getApiUsageState(tenantId).isTbelExecEnabled();
}
@Override
protected void reportExecution(TenantId tenantId, CustomerId customerId) {
apiUsageReportClient.ifPresent(client -> client.report(tenantId, customerId, ApiUsageRecordKey.TBEL_EXEC_COUNT, 1));
}
@Override @Override
protected ListenableFuture<UUID> doEvalScript(TenantId tenantId, ScriptType scriptType, String scriptBody, UUID scriptId, String[] argNames) { protected ListenableFuture<UUID> doEvalScript(TenantId tenantId, ScriptType scriptType, String scriptBody, UUID scriptId, String[] argNames) {
return executor.submit(() -> { return executor.submit(() -> {

2
common/stats/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common.transport</groupId> <groupId>org.thingsboard.common.transport</groupId>

2
common/transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common.transport</groupId> <groupId>org.thingsboard.common.transport</groupId>

2
common/transport/lwm2m/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common.transport</groupId> <groupId>org.thingsboard.common.transport</groupId>

2
common/transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common.transport</groupId> <groupId>org.thingsboard.common.transport</groupId>

2
common/transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/transport/snmp/pom.xml

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>

2
common/transport/transport-api/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common.transport</groupId> <groupId>org.thingsboard.common.transport</groupId>

2
common/util/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

2
common/version-control/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>common</artifactId> <artifactId>common</artifactId>
</parent> </parent>
<groupId>org.thingsboard.common</groupId> <groupId>org.thingsboard.common</groupId>

6
dao/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>dao</artifactId> <artifactId>dao</artifactId>
@ -230,6 +230,10 @@
<groupId>org.thingsboard.rule-engine</groupId> <groupId>org.thingsboard.rule-engine</groupId>
<artifactId>rule-engine-api</artifactId> <artifactId>rule-engine-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-55</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>

6
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -313,10 +313,15 @@ public class ModelConstants {
public static final String WIDGET_TYPE_NAME_PROPERTY = "name"; public static final String WIDGET_TYPE_NAME_PROPERTY = "name";
public static final String WIDGET_TYPE_IMAGE_PROPERTY = "image"; public static final String WIDGET_TYPE_IMAGE_PROPERTY = "image";
public static final String WIDGET_TYPE_DESCRIPTION_PROPERTY = "description"; public static final String WIDGET_TYPE_DESCRIPTION_PROPERTY = "description";
public static final String WIDGET_TYPE_TAGS_PROPERTY = "tags";
public static final String WIDGET_TYPE_DESCRIPTOR_PROPERTY = "descriptor"; public static final String WIDGET_TYPE_DESCRIPTOR_PROPERTY = "descriptor";
public static final String WIDGET_TYPE_DEPRECATED_PROPERTY = "deprecated"; public static final String WIDGET_TYPE_DEPRECATED_PROPERTY = "deprecated";
public static final String WIDGET_TYPE_WIDGET_TYPE_PROPERTY = "widget_type";
public static final String WIDGET_TYPE_INFO_VIEW_TABLE_NAME = "widget_type_info_view";
/** /**
* Widgets bundle widget constants. * Widgets bundle widget constants.
*/ */
@ -477,6 +482,7 @@ public class ModelConstants {
public static final String API_USAGE_STATE_DB_STORAGE_COLUMN = "db_storage"; public static final String API_USAGE_STATE_DB_STORAGE_COLUMN = "db_storage";
public static final String API_USAGE_STATE_RE_EXEC_COLUMN = "re_exec"; public static final String API_USAGE_STATE_RE_EXEC_COLUMN = "re_exec";
public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec"; public static final String API_USAGE_STATE_JS_EXEC_COLUMN = "js_exec";
public static final String API_USAGE_STATE_TBEL_EXEC_COLUMN = "tbel_exec";
public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec"; public static final String API_USAGE_STATE_EMAIL_EXEC_COLUMN = "email_exec";
public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec"; public static final String API_USAGE_STATE_SMS_EXEC_COLUMN = "sms_exec";
public static final String API_USAGE_STATE_ALARM_EXEC_COLUMN = "alarm_exec"; public static final String API_USAGE_STATE_ALARM_EXEC_COLUMN = "alarm_exec";

5
dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java

@ -64,6 +64,9 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
@Column(name = ModelConstants.API_USAGE_STATE_JS_EXEC_COLUMN) @Column(name = ModelConstants.API_USAGE_STATE_JS_EXEC_COLUMN)
private ApiUsageStateValue jsExecState = ApiUsageStateValue.ENABLED; private ApiUsageStateValue jsExecState = ApiUsageStateValue.ENABLED;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Column(name = ModelConstants.API_USAGE_STATE_TBEL_EXEC_COLUMN)
private ApiUsageStateValue tbelExecState = ApiUsageStateValue.ENABLED;
@Enumerated(EnumType.STRING)
@Column(name = ModelConstants.API_USAGE_STATE_EMAIL_EXEC_COLUMN) @Column(name = ModelConstants.API_USAGE_STATE_EMAIL_EXEC_COLUMN)
private ApiUsageStateValue emailExecState = ApiUsageStateValue.ENABLED; private ApiUsageStateValue emailExecState = ApiUsageStateValue.ENABLED;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@ -92,6 +95,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
this.dbStorageState = ur.getDbStorageState(); this.dbStorageState = ur.getDbStorageState();
this.reExecState = ur.getReExecState(); this.reExecState = ur.getReExecState();
this.jsExecState = ur.getJsExecState(); this.jsExecState = ur.getJsExecState();
this.tbelExecState = ur.getTbelExecState();
this.emailExecState = ur.getEmailExecState(); this.emailExecState = ur.getEmailExecState();
this.smsExecState = ur.getSmsExecState(); this.smsExecState = ur.getSmsExecState();
this.alarmExecState = ur.getAlarmExecState(); this.alarmExecState = ur.getAlarmExecState();
@ -111,6 +115,7 @@ public class ApiUsageStateEntity extends BaseSqlEntity<ApiUsageState> implements
ur.setDbStorageState(dbStorageState); ur.setDbStorageState(dbStorageState);
ur.setReExecState(reExecState); ur.setReExecState(reExecState);
ur.setJsExecState(jsExecState); ur.setJsExecState(jsExecState);
ur.setTbelExecState(tbelExecState);
ur.setEmailExecState(emailExecState); ur.setEmailExecState(emailExecState);
ur.setSmsExecState(smsExecState); ur.setSmsExecState(smsExecState);
ur.setAlarmExecState(alarmExecState); ur.setAlarmExecState(alarmExecState);

9
dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java

@ -16,12 +16,12 @@
package org.thingsboard.server.dao.model.sql; package org.thingsboard.server.dao.model.sql;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import io.hypersistence.utils.hibernate.type.array.StringArrayType;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.widget.BaseWidgetType; import org.thingsboard.server.common.data.widget.BaseWidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.ModelConstants;
@ -36,6 +36,7 @@ import java.util.UUID;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Entity @Entity
@TypeDef(name = "json", typeClass = JsonStringType.class) @TypeDef(name = "json", typeClass = JsonStringType.class)
@TypeDef(name = "string-array", typeClass = StringArrayType.class)
@Table(name = ModelConstants.WIDGET_TYPE_TABLE_NAME) @Table(name = ModelConstants.WIDGET_TYPE_TABLE_NAME)
public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity<WidgetTypeDetails> { public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity<WidgetTypeDetails> {
@ -45,6 +46,10 @@ public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity<WidgetType
@Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTION_PROPERTY) @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTION_PROPERTY)
private String description; private String description;
@Type(type="string-array")
@Column(name = ModelConstants.WIDGET_TYPE_TAGS_PROPERTY, columnDefinition = "text[]")
private String[] tags;
@Type(type="json") @Type(type="json")
@Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY) @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY)
private JsonNode descriptor; private JsonNode descriptor;
@ -60,6 +65,7 @@ public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity<WidgetType
super(widgetTypeDetails); super(widgetTypeDetails);
this.image = widgetTypeDetails.getImage(); this.image = widgetTypeDetails.getImage();
this.description = widgetTypeDetails.getDescription(); this.description = widgetTypeDetails.getDescription();
this.tags = widgetTypeDetails.getTags();
this.descriptor = widgetTypeDetails.getDescriptor(); this.descriptor = widgetTypeDetails.getDescriptor();
if (widgetTypeDetails.getExternalId() != null) { if (widgetTypeDetails.getExternalId() != null) {
this.externalId = widgetTypeDetails.getExternalId().getId(); this.externalId = widgetTypeDetails.getExternalId().getId();
@ -72,6 +78,7 @@ public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity<WidgetType
WidgetTypeDetails widgetTypeDetails = new WidgetTypeDetails(baseWidgetType); WidgetTypeDetails widgetTypeDetails = new WidgetTypeDetails(baseWidgetType);
widgetTypeDetails.setImage(image); widgetTypeDetails.setImage(image);
widgetTypeDetails.setDescription(description); widgetTypeDetails.setDescription(description);
widgetTypeDetails.setTags(tags);
widgetTypeDetails.setDescriptor(descriptor); widgetTypeDetails.setDescriptor(descriptor);
if (externalId != null) { if (externalId != null) {
widgetTypeDetails.setExternalId(new WidgetTypeId(externalId)); widgetTypeDetails.setExternalId(new WidgetTypeId(externalId));

34
dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeInfoEntity.java

@ -15,40 +15,52 @@
*/ */
package org.thingsboard.server.dao.model.sql; package org.thingsboard.server.dao.model.sql;
import io.hypersistence.utils.hibernate.type.array.StringArrayType;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.widget.BaseWidgetType; import org.thingsboard.server.common.data.widget.BaseWidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
import org.thingsboard.server.dao.model.ModelConstants;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Entity
@Immutable
@TypeDef(name = "string-array", typeClass = StringArrayType.class)
@Table(name = ModelConstants.WIDGET_TYPE_INFO_VIEW_TABLE_NAME)
public final class WidgetTypeInfoEntity extends AbstractWidgetTypeEntity<WidgetTypeInfo> { public final class WidgetTypeInfoEntity extends AbstractWidgetTypeEntity<WidgetTypeInfo> {
@Column(name = ModelConstants.WIDGET_TYPE_IMAGE_PROPERTY)
private String image; private String image;
@Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTION_PROPERTY)
private String description; private String description;
@Type(type="string-array")
@Column(name = ModelConstants.WIDGET_TYPE_TAGS_PROPERTY, columnDefinition = "text[]")
private String[] tags;
@Column(name = ModelConstants.WIDGET_TYPE_WIDGET_TYPE_PROPERTY)
private String widgetType; private String widgetType;
public WidgetTypeInfoEntity() { public WidgetTypeInfoEntity() {
super(); super();
} }
public WidgetTypeInfoEntity(WidgetTypeDetailsEntity widgetTypeDetailsEntity) {
super(widgetTypeDetailsEntity);
this.image = widgetTypeDetailsEntity.getImage();
this.description = widgetTypeDetailsEntity.getDescription();
if (widgetTypeDetailsEntity.getDescriptor() != null && widgetTypeDetailsEntity.getDescriptor().has("type")) {
this.widgetType = widgetTypeDetailsEntity.getDescriptor().get("type").asText();
} else {
this.widgetType = "";
}
}
@Override @Override
public WidgetTypeInfo toData() { public WidgetTypeInfo toData() {
BaseWidgetType baseWidgetType = super.toBaseWidgetType(); BaseWidgetType baseWidgetType = super.toBaseWidgetType();
WidgetTypeInfo widgetTypeInfo = new WidgetTypeInfo(baseWidgetType); WidgetTypeInfo widgetTypeInfo = new WidgetTypeInfo(baseWidgetType);
widgetTypeInfo.setImage(image); widgetTypeInfo.setImage(image);
widgetTypeInfo.setDescription(description); widgetTypeInfo.setDescription(description);
widgetTypeInfo.setTags(tags);
widgetTypeInfo.setWidgetType(widgetType); widgetTypeInfo.setWidgetType(widgetType);
return widgetTypeInfo; return widgetTypeInfo;
} }

55
dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
@ -35,6 +36,7 @@ import org.thingsboard.server.dao.sql.JpaAbstractDao;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import org.thingsboard.server.dao.widget.WidgetTypeDao; import org.thingsboard.server.dao.widget.WidgetTypeDao;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -54,6 +56,9 @@ public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeDetailsEntity, Wi
@Autowired @Autowired
private WidgetTypeRepository widgetTypeRepository; private WidgetTypeRepository widgetTypeRepository;
@Autowired
private WidgetTypeInfoRepository widgetTypeInfoRepository;
@Autowired @Autowired
private WidgetsBundleWidgetRepository widgetsBundleWidgetRepository; private WidgetsBundleWidgetRepository widgetsBundleWidgetRepository;
@ -78,36 +83,57 @@ public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeDetailsEntity, Wi
} }
@Override @Override
public PageData<WidgetTypeInfo> findSystemWidgetTypes(TenantId tenantId, boolean fullSearch, PageLink pageLink) { public PageData<WidgetTypeInfo> findSystemWidgetTypes(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
boolean deprecatedFilterEnabled = !DeprecatedFilter.ALL.equals(deprecatedFilter);
boolean deprecatedFilterBool = DeprecatedFilter.DEPRECATED.equals(deprecatedFilter);
boolean widgetTypesEmpty = widgetTypes == null || widgetTypes.isEmpty();
return DaoUtil.toPageData( return DaoUtil.toPageData(
widgetTypeRepository widgetTypeInfoRepository
.findSystemWidgetTypes( .findSystemWidgetTypes(
NULL_UUID, NULL_UUID,
Objects.toString(pageLink.getTextSearch(), ""), Objects.toString(pageLink.getTextSearch(), ""),
fullSearch, fullSearch,
deprecatedFilterEnabled,
deprecatedFilterBool,
widgetTypesEmpty,
widgetTypes == null ? Collections.emptyList() : widgetTypes,
DaoUtil.toPageable(pageLink))); DaoUtil.toPageable(pageLink)));
} }
@Override @Override
public PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, PageLink pageLink) { public PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
boolean deprecatedFilterEnabled = !DeprecatedFilter.ALL.equals(deprecatedFilter);
boolean deprecatedFilterBool = DeprecatedFilter.DEPRECATED.equals(deprecatedFilter);
boolean widgetTypesEmpty = widgetTypes == null || widgetTypes.isEmpty();
return DaoUtil.toPageData( return DaoUtil.toPageData(
widgetTypeRepository widgetTypeInfoRepository
.findAllTenantWidgetTypesByTenantId( .findAllTenantWidgetTypesByTenantId(
tenantId, tenantId,
NULL_UUID, NULL_UUID,
Objects.toString(pageLink.getTextSearch(), ""), Objects.toString(pageLink.getTextSearch(), ""),
fullSearch, fullSearch,
deprecatedFilterEnabled,
deprecatedFilterBool,
widgetTypesEmpty,
widgetTypes == null ? Collections.emptyList() : widgetTypes,
DaoUtil.toPageable(pageLink))); DaoUtil.toPageable(pageLink)));
} }
@Override @Override
public PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, PageLink pageLink) { public PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
boolean deprecatedFilterEnabled = !DeprecatedFilter.ALL.equals(deprecatedFilter);
boolean deprecatedFilterBool = DeprecatedFilter.DEPRECATED.equals(deprecatedFilter);
boolean widgetTypesEmpty = widgetTypes == null || widgetTypes.isEmpty();
return DaoUtil.toPageData( return DaoUtil.toPageData(
widgetTypeRepository widgetTypeInfoRepository
.findTenantWidgetTypesByTenantId( .findTenantWidgetTypesByTenantId(
tenantId, tenantId,
Objects.toString(pageLink.getTextSearch(), ""), Objects.toString(pageLink.getTextSearch(), ""),
fullSearch, fullSearch,
deprecatedFilterEnabled,
deprecatedFilterBool,
widgetTypesEmpty,
widgetTypes == null ? Collections.emptyList() : widgetTypes,
DaoUtil.toPageable(pageLink))); DaoUtil.toPageable(pageLink)));
} }
@ -122,8 +148,21 @@ public class JpaWidgetTypeDao extends JpaAbstractDao<WidgetTypeDetailsEntity, Wi
} }
@Override @Override
public List<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId) { public PageData<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
return DaoUtil.convertDataList(widgetTypeRepository.findWidgetTypesInfosByWidgetsBundleId(widgetsBundleId)); boolean deprecatedFilterEnabled = !DeprecatedFilter.ALL.equals(deprecatedFilter);
boolean deprecatedFilterBool = DeprecatedFilter.DEPRECATED.equals(deprecatedFilter);
boolean widgetTypesEmpty = widgetTypes == null || widgetTypes.isEmpty();
return DaoUtil.toPageData(
widgetTypeInfoRepository
.findWidgetTypesInfosByWidgetsBundleId(
widgetsBundleId,
Objects.toString(pageLink.getTextSearch(), ""),
fullSearch,
deprecatedFilterEnabled,
deprecatedFilterBool,
widgetTypesEmpty,
widgetTypes == null ? Collections.emptyList() : widgetTypes,
DaoUtil.toPageable(pageLink)));
} }
@Override @Override

49
dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java

@ -62,13 +62,22 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
} }
@Override @Override
public PageData<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId, PageLink pageLink) { public PageData<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId, boolean fullSearch, PageLink pageLink) {
return DaoUtil.toPageData( if (fullSearch) {
widgetsBundleRepository return DaoUtil.toPageData(
.findSystemWidgetsBundles( widgetsBundleRepository
NULL_UUID, .findSystemWidgetsBundlesFullSearch(
Objects.toString(pageLink.getTextSearch(), ""), NULL_UUID,
DaoUtil.toPageable(pageLink))); Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
} else {
return DaoUtil.toPageData(
widgetsBundleRepository
.findSystemWidgetsBundles(
NULL_UUID,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
} }
@Override @Override
@ -82,14 +91,24 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
} }
@Override @Override
public PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(UUID tenantId, PageLink pageLink) { public PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(UUID tenantId, boolean fullSearch, PageLink pageLink) {
return DaoUtil.toPageData( if (fullSearch) {
widgetsBundleRepository return DaoUtil.toPageData(
.findAllTenantWidgetsBundlesByTenantId( widgetsBundleRepository
tenantId, .findAllTenantWidgetsBundlesByTenantIdFullSearch(
NULL_UUID, tenantId,
Objects.toString(pageLink.getTextSearch(), ""), NULL_UUID,
DaoUtil.toPageable(pageLink))); Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
} else {
return DaoUtil.toPageData(
widgetsBundleRepository
.findAllTenantWidgetsBundlesByTenantId(
tenantId,
NULL_UUID,
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
} }
@Override @Override

134
dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeInfoRepository.java

@ -0,0 +1,134 @@
/**
* 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.dao.sql.widget;
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.repository.query.Param;
import org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity;
import java.util.List;
import java.util.UUID;
public interface WidgetTypeInfoRepository extends JpaRepository<WidgetTypeInfoEntity, UUID> {
@Query(nativeQuery = true,
value = "SELECT * FROM widget_type_info_view wti WHERE wti.tenant_id = :systemTenantId " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' '))))",
// "OR to_tsvector(lower(array_to_string(wti.tags, ' '))) @@ to_tsquery(lower(:searchText)))))",
countQuery = "SELECT count(*) FROM widget_type_info_view wti WHERE wti.tenant_id = :systemTenantId " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' '))))"
)
Page<WidgetTypeInfoEntity> findSystemWidgetTypes(@Param("systemTenantId") UUID systemTenantId,
@Param("searchText") String searchText,
@Param("fullSearch") boolean fullSearch,
@Param("deprecatedFilterEnabled") boolean deprecatedFilterEnabled,
@Param("deprecatedFilter") boolean deprecatedFilter,
@Param("widgetTypesEmpty") boolean widgetTypesEmpty,
@Param("widgetTypes") List<String> widgetTypes,
Pageable pageable);
@Query(nativeQuery = true,
value = "SELECT * FROM widget_type_info_view wti WHERE wti.tenant_id IN (:tenantId, :nullTenantId) " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' '))))",
countQuery = "SELECT count(*) FROM widget_type_info_view wti WHERE wti.tenant_id IN (:tenantId, :nullTenantId) " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' '))))"
)
Page<WidgetTypeInfoEntity> findAllTenantWidgetTypesByTenantId(@Param("tenantId") UUID tenantId,
@Param("nullTenantId") UUID nullTenantId,
@Param("searchText") String searchText,
@Param("fullSearch") boolean fullSearch,
@Param("deprecatedFilterEnabled") boolean deprecatedFilterEnabled,
@Param("deprecatedFilter") boolean deprecatedFilter,
@Param("widgetTypesEmpty") boolean widgetTypesEmpty,
@Param("widgetTypes") List<String> widgetTypes,
Pageable pageable);
@Query(nativeQuery = true,
value = "SELECT * FROM widget_type_info_view wti WHERE wti.tenant_id = :tenantId " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' '))))",
countQuery = "SELECT count(*) FROM widget_type_info_view wti WHERE wti.tenant_id = :tenantId " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' '))))"
)
Page<WidgetTypeInfoEntity> findTenantWidgetTypesByTenantId(@Param("tenantId") UUID tenantId,
@Param("searchText") String searchText,
@Param("fullSearch") boolean fullSearch,
@Param("deprecatedFilterEnabled") boolean deprecatedFilterEnabled,
@Param("deprecatedFilter") boolean deprecatedFilter,
@Param("widgetTypesEmpty") boolean widgetTypesEmpty,
@Param("widgetTypes") List<String> widgetTypes,
Pageable pageable);
@Query("SELECT wti FROM WidgetTypeInfoEntity wti, WidgetsBundleWidgetEntity wbw " +
"WHERE wbw.widgetsBundleId = :widgetsBundleId " +
"AND wbw.widgetTypeId = wti.id ORDER BY wbw.widgetTypeOrder")
List<WidgetTypeInfoEntity> findWidgetTypesInfosByWidgetsBundleId(@Param("widgetsBundleId") UUID widgetsBundleId);
@Query(nativeQuery = true,
value = "SELECT * FROM widget_type_info_view wti, widgets_bundle_widget wbw " +
"WHERE wbw.widgets_bundle_id = :widgetsBundleId " +
"AND wbw.widget_type_id = wti.id " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' ')))) " +
"ORDER BY wbw.widget_type_order",
countQuery = "SELECT count(*) FROM widget_type_info_view wti, widgets_bundle_widget wbw " +
"WHERE wbw.widgets_bundle_id = :widgetsBundleId " +
"AND wbw.widget_type_id = wti.id " +
"AND ((:deprecatedFilterEnabled) IS FALSE OR wti.deprecated = :deprecatedFilter) " +
"AND ((:widgetTypesEmpty) IS TRUE OR wti.widget_type IN (:widgetTypes)) " +
"AND (wti.name ILIKE CONCAT('%', :searchText, '%') " +
"OR ((:fullSearch) IS TRUE AND (wti.description ILIKE CONCAT('%', :searchText, '%') " +
"OR lower(wti.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:searchText), ' '))))"
)
Page<WidgetTypeInfoEntity> findWidgetTypesInfosByWidgetsBundleId(@Param("widgetsBundleId") UUID widgetsBundleId,
@Param("searchText") String searchText,
@Param("fullSearch") boolean fullSearch,
@Param("deprecatedFilterEnabled") boolean deprecatedFilterEnabled,
@Param("deprecatedFilter") boolean deprecatedFilter,
@Param("widgetTypesEmpty") boolean widgetTypesEmpty,
@Param("widgetTypes") List<String> widgetTypes,
Pageable pageable);
}

31
dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetTypeRepository.java

@ -24,8 +24,6 @@ import org.thingsboard.server.dao.ExportableEntityRepository;
import org.thingsboard.server.dao.model.sql.WidgetTypeDetailsEntity; import org.thingsboard.server.dao.model.sql.WidgetTypeDetailsEntity;
import org.thingsboard.server.dao.model.sql.WidgetTypeEntity; import org.thingsboard.server.dao.model.sql.WidgetTypeEntity;
import org.thingsboard.server.dao.model.sql.WidgetTypeIdFqnEntity; import org.thingsboard.server.dao.model.sql.WidgetTypeIdFqnEntity;
import org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity;
import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -37,31 +35,6 @@ public interface WidgetTypeRepository extends JpaRepository<WidgetTypeDetailsEnt
boolean existsByTenantIdAndId(UUID tenantId, UUID id); boolean existsByTenantIdAndId(UUID tenantId, UUID id);
@Query("SELECT new org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity(wtd) FROM WidgetTypeDetailsEntity wtd WHERE wtd.tenantId = :systemTenantId " +
"AND (LOWER(wtd.name) LIKE LOWER(CONCAT('%', :searchText, '%')) " +
"OR ((:fullSearch) IS TRUE AND LOWER(wtd.description) LIKE LOWER(CONCAT('%', :searchText, '%'))))")
Page<WidgetTypeInfoEntity> findSystemWidgetTypes(@Param("systemTenantId") UUID systemTenantId,
@Param("searchText") String searchText,
@Param("fullSearch") boolean fullSearch,
Pageable pageable);
@Query("SELECT new org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity(wtd) FROM WidgetTypeDetailsEntity wtd WHERE wtd.tenantId IN (:tenantId, :nullTenantId) " +
"AND (LOWER(wtd.name) LIKE LOWER(CONCAT('%', :searchText, '%')) " +
"OR ((:fullSearch) IS TRUE AND LOWER(wtd.description) LIKE LOWER(CONCAT('%', :searchText, '%'))))")
Page<WidgetTypeInfoEntity> findAllTenantWidgetTypesByTenantId(@Param("tenantId") UUID tenantId,
@Param("nullTenantId") UUID nullTenantId,
@Param("searchText") String searchText,
@Param("fullSearch") boolean fullSearch,
Pageable pageable);
@Query("SELECT new org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity(wtd) FROM WidgetTypeDetailsEntity wtd WHERE wtd.tenantId = :tenantId " +
"AND (LOWER(wtd.name) LIKE LOWER(CONCAT('%', :searchText, '%')) " +
"OR ((:fullSearch) IS TRUE AND LOWER(wtd.description) LIKE LOWER(CONCAT('%', :searchText, '%'))))")
Page<WidgetTypeInfoEntity> findTenantWidgetTypesByTenantId(@Param("tenantId") UUID tenantId,
@Param("searchText") String searchText,
@Param("fullSearch") boolean fullSearch,
Pageable pageable);
@Query("SELECT wtd FROM WidgetTypeDetailsEntity wtd WHERE wtd.tenantId = :tenantId " + @Query("SELECT wtd FROM WidgetTypeDetailsEntity wtd WHERE wtd.tenantId = :tenantId " +
"AND LOWER(wtd.name) LIKE LOWER(CONCAT('%', :textSearch, '%'))") "AND LOWER(wtd.name) LIKE LOWER(CONCAT('%', :textSearch, '%'))")
Page<WidgetTypeDetailsEntity> findTenantWidgetTypeDetailsByTenantId(@Param("tenantId") UUID tenantId, Page<WidgetTypeDetailsEntity> findTenantWidgetTypeDetailsByTenantId(@Param("tenantId") UUID tenantId,
@ -78,10 +51,6 @@ public interface WidgetTypeRepository extends JpaRepository<WidgetTypeDetailsEnt
"AND wbw.widgetTypeId = wtd.id ORDER BY wbw.widgetTypeOrder") "AND wbw.widgetTypeId = wtd.id ORDER BY wbw.widgetTypeOrder")
List<WidgetTypeDetailsEntity> findWidgetTypesDetailsByWidgetsBundleId(@Param("widgetsBundleId") UUID widgetsBundleId); List<WidgetTypeDetailsEntity> findWidgetTypesDetailsByWidgetsBundleId(@Param("widgetsBundleId") UUID widgetsBundleId);
@Query("SELECT new org.thingsboard.server.dao.model.sql.WidgetTypeInfoEntity(wtd) FROM WidgetTypeDetailsEntity wtd, WidgetsBundleWidgetEntity wbw " +
"WHERE wbw.widgetsBundleId = :widgetsBundleId " +
"AND wbw.widgetTypeId = wtd.id ORDER BY wbw.widgetTypeOrder")
List<WidgetTypeInfoEntity> findWidgetTypesInfosByWidgetsBundleId(@Param("widgetsBundleId") UUID widgetsBundleId);
@Query("SELECT wtd.fqn FROM WidgetTypeDetailsEntity wtd, WidgetsBundleWidgetEntity wbw " + @Query("SELECT wtd.fqn FROM WidgetTypeDetailsEntity wtd, WidgetsBundleWidgetEntity wbw " +
"WHERE wbw.widgetsBundleId = :widgetsBundleId " + "WHERE wbw.widgetsBundleId = :widgetsBundleId " +

49
dao/src/main/java/org/thingsboard/server/dao/sql/widget/WidgetsBundleRepository.java

@ -33,11 +33,33 @@ public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEnti
WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias); WidgetsBundleEntity findWidgetsBundleByTenantIdAndAlias(UUID tenantId, String alias);
@Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :systemTenantId " + @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :systemTenantId " +
"AND LOWER(wb.title) LIKE LOWER(CONCAT('%', :searchText, '%'))") "AND LOWER(wb.title) LIKE LOWER(CONCAT('%', :textSearch, '%'))")
Page<WidgetsBundleEntity> findSystemWidgetsBundles(@Param("systemTenantId") UUID systemTenantId, Page<WidgetsBundleEntity> findSystemWidgetsBundles(@Param("systemTenantId") UUID systemTenantId,
@Param("searchText") String searchText, @Param("textSearch") String textSearch,
Pageable pageable); Pageable pageable);
@Query(nativeQuery = true,
value = "SELECT * FROM widgets_bundle wb WHERE wb.tenant_id = :systemTenantId " +
"AND (wb.title ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.id in (SELECT wbw.widgets_bundle_id FROM widgets_bundle_widget wbw, widget_type wtd " +
"WHERE wtd.id = wbw.widget_type_id " +
"AND (wtd.name ILIKE CONCAT('%', :textSearch, '%') " +
"OR wtd.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR lower(wtd.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:textSearch), ' '))))",
countQuery = "SELECT count(*) FROM widgets_bundle wb WHERE wb.tenant_id = :systemTenantId " +
"AND (wb.title ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.id in (SELECT wbw.widgets_bundle_id FROM widgets_bundle_widget wbw, widget_type wtd " +
"WHERE wtd.id = wbw.widget_type_id " +
"AND (wtd.name ILIKE CONCAT('%', :textSearch, '%') " +
"OR wtd.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR lower(wtd.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:textSearch), ' '))))"
)
Page<WidgetsBundleEntity> findSystemWidgetsBundlesFullSearch(@Param("systemTenantId") UUID systemTenantId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :tenantId " + @Query("SELECT wb FROM WidgetsBundleEntity wb WHERE wb.tenantId = :tenantId " +
"AND LOWER(wb.title) LIKE LOWER(CONCAT('%', :textSearch, '%'))") "AND LOWER(wb.title) LIKE LOWER(CONCAT('%', :textSearch, '%'))")
Page<WidgetsBundleEntity> findTenantWidgetsBundlesByTenantId(@Param("tenantId") UUID tenantId, Page<WidgetsBundleEntity> findTenantWidgetsBundlesByTenantId(@Param("tenantId") UUID tenantId,
@ -51,6 +73,29 @@ public interface WidgetsBundleRepository extends JpaRepository<WidgetsBundleEnti
@Param("textSearch") String textSearch, @Param("textSearch") String textSearch,
Pageable pageable); Pageable pageable);
@Query(nativeQuery = true,
value = "SELECT * FROM widgets_bundle wb WHERE wb.tenant_id IN (:tenantId, :nullTenantId) " +
"AND (wb.title ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.id in (SELECT wbw.widgets_bundle_id FROM widgets_bundle_widget wbw, widget_type wtd " +
"WHERE wtd.id = wbw.widget_type_id " +
"AND (wtd.name ILIKE CONCAT('%', :textSearch, '%') " +
"OR wtd.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR lower(wtd.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:textSearch), ' '))))",
countQuery = "SELECT count(*) FROM widgets_bundle wb WHERE wb.tenant_id IN (:tenantId, :nullTenantId) " +
"AND (wb.title ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR wb.id in (SELECT wbw.widgets_bundle_id FROM widgets_bundle_widget wbw, widget_type wtd " +
"WHERE wtd.id = wbw.widget_type_id " +
"AND (wtd.name ILIKE CONCAT('%', :textSearch, '%') " +
"OR wtd.description ILIKE CONCAT('%', :textSearch, '%') " +
"OR lower(wtd.tags\\:\\:text)\\:\\:text[] && string_to_array(lower(:textSearch), ' '))))"
)
Page<WidgetsBundleEntity> findAllTenantWidgetsBundlesByTenantIdFullSearch(@Param("tenantId") UUID tenantId,
@Param("nullTenantId") UUID nullTenantId,
@Param("textSearch") String textSearch,
Pageable pageable);
WidgetsBundleEntity findFirstByTenantIdAndTitle(UUID tenantId, String title); WidgetsBundleEntity findFirstByTenantIdAndTitle(UUID tenantId, String title);
@Query("SELECT externalId FROM WidgetsBundleEntity WHERE id = :id") @Query("SELECT externalId FROM WidgetsBundleEntity WHERE id = :id")

3
dao/src/main/java/org/thingsboard/server/dao/usage/BasicUsageInfoService.java

@ -67,6 +67,7 @@ public class BasicUsageInfoService implements UsageInfoService {
usageInfo.setMaxAlarms(profileConfiguration.getMaxCreatedAlarms()); usageInfo.setMaxAlarms(profileConfiguration.getMaxCreatedAlarms());
usageInfo.setMaxTransportMessages(profileConfiguration.getMaxTransportMessages()); usageInfo.setMaxTransportMessages(profileConfiguration.getMaxTransportMessages());
usageInfo.setMaxJsExecutions(profileConfiguration.getMaxJSExecutions()); usageInfo.setMaxJsExecutions(profileConfiguration.getMaxJSExecutions());
usageInfo.setMaxTbelExecutions(profileConfiguration.getMaxTbelExecutions());
usageInfo.setMaxEmails(profileConfiguration.getMaxEmails()); usageInfo.setMaxEmails(profileConfiguration.getMaxEmails());
usageInfo.setMaxSms(profileConfiguration.getMaxSms()); usageInfo.setMaxSms(profileConfiguration.getMaxSms());
usageInfo.setSmsEnabled(profileConfiguration.getSmsEnabled()); usageInfo.setSmsEnabled(profileConfiguration.getSmsEnabled());
@ -75,6 +76,7 @@ public class BasicUsageInfoService implements UsageInfoService {
Collection<String> keys = Arrays.asList( Collection<String> keys = Arrays.asList(
ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey(), ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey(),
ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey(), ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey(),
ApiUsageRecordKey.TBEL_EXEC_COUNT.getApiCountKey(),
ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey(), ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey(),
ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey(), ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey(),
ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey()); ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey());
@ -82,6 +84,7 @@ public class BasicUsageInfoService implements UsageInfoService {
List<TsKvEntry> entries = tsService.findLatest(tenantId, apiUsageState.getId(), keys).get(); List<TsKvEntry> entries = tsService.findLatest(tenantId, apiUsageState.getId(), keys).get();
usageInfo.setTransportMessages(getLongValueFromTsEntries(entries, ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey())); usageInfo.setTransportMessages(getLongValueFromTsEntries(entries, ApiUsageRecordKey.TRANSPORT_MSG_COUNT.getApiCountKey()));
usageInfo.setJsExecutions(getLongValueFromTsEntries(entries, ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey())); usageInfo.setJsExecutions(getLongValueFromTsEntries(entries, ApiUsageRecordKey.JS_EXEC_COUNT.getApiCountKey()));
usageInfo.setTbelExecutions(getLongValueFromTsEntries(entries, ApiUsageRecordKey.TBEL_EXEC_COUNT.getApiCountKey()));
usageInfo.setEmails(getLongValueFromTsEntries(entries, ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey())); usageInfo.setEmails(getLongValueFromTsEntries(entries, ApiUsageRecordKey.EMAIL_EXEC_COUNT.getApiCountKey()));
usageInfo.setSms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey())); usageInfo.setSms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.SMS_EXEC_COUNT.getApiCountKey()));
usageInfo.setAlarms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey())); usageInfo.setAlarms(getLongValueFromTsEntries(entries, ApiUsageRecordKey.CREATED_ALARMS_COUNT.getApiCountKey()));

3
dao/src/main/java/org/thingsboard/server/dao/usagerecord/ApiUsageStateServiceImpl.java

@ -93,6 +93,7 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
apiUsageState.setTransportState(ApiUsageStateValue.ENABLED); apiUsageState.setTransportState(ApiUsageStateValue.ENABLED);
apiUsageState.setReExecState(ApiUsageStateValue.ENABLED); apiUsageState.setReExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED); apiUsageState.setJsExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setTbelExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED); apiUsageState.setDbStorageState(ApiUsageStateValue.ENABLED);
apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED); apiUsageState.setSmsExecState(ApiUsageStateValue.ENABLED);
apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED); apiUsageState.setEmailExecState(ApiUsageStateValue.ENABLED);
@ -110,6 +111,8 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
new StringDataEntry(ApiFeature.RE.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); new StringDataEntry(ApiFeature.RE.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
new StringDataEntry(ApiFeature.JS.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); new StringDataEntry(ApiFeature.JS.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
new StringDataEntry(ApiFeature.TBEL.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),
new StringDataEntry(ApiFeature.EMAIL.getApiStateKey(), ApiUsageStateValue.ENABLED.name()))); new StringDataEntry(ApiFeature.EMAIL.getApiStateKey(), ApiUsageStateValue.ENABLED.name())));
apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(), apiUsageStates.add(new BasicTsKvEntry(saved.getCreatedTime(),

16
dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeDao.java

@ -19,6 +19,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
@ -53,11 +54,11 @@ public interface WidgetTypeDao extends Dao<WidgetTypeDetails>, ExportableEntityD
boolean existsByTenantIdAndId(TenantId tenantId, UUID widgetTypeId); boolean existsByTenantIdAndId(TenantId tenantId, UUID widgetTypeId);
PageData<WidgetTypeInfo> findSystemWidgetTypes(TenantId tenantId, boolean fullSearch, PageLink pageLink); PageData<WidgetTypeInfo> findSystemWidgetTypes(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, PageLink pageLink); PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, PageLink pageLink); PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantId(UUID tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
/** /**
* Find widget types by widgetsBundleId. * Find widget types by widgetsBundleId.
@ -77,14 +78,7 @@ public interface WidgetTypeDao extends Dao<WidgetTypeDetails>, ExportableEntityD
*/ */
List<WidgetTypeDetails> findWidgetTypesDetailsByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId); List<WidgetTypeDetails> findWidgetTypesDetailsByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId);
/** PageData<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink);
* Find widget types infos by widgetsBundleId.
*
* @param tenantId the tenantId
* @param widgetsBundleId the widgets bundle id
* @return the list of widget types infos objects
*/
List<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId);
List<String> findWidgetFqnsByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId); List<String> findWidgetFqnsByWidgetsBundleId(UUID tenantId, UUID widgetsBundleId);

32
dao/src/main/java/org/thingsboard/server/dao/widget/WidgetTypeServiceImpl.java

@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
@ -110,26 +111,28 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
} }
@Override @Override
public PageData<WidgetTypeInfo> findSystemWidgetTypesByPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink) { public PageData<WidgetTypeInfo> findSystemWidgetTypesByPageLink(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
log.trace("Executing findSystemWidgetTypesByPageLink, fullSearch [{}] pageLink [{}]", fullSearch, pageLink); log.trace("Executing findSystemWidgetTypesByPageLink, fullSearch [{}], deprecatedFilter [{}], widgetTypes [{}], pageLink [{}]", fullSearch, deprecatedFilter, widgetTypes, pageLink);
Validator.validatePageLink(pageLink); Validator.validatePageLink(pageLink);
return widgetTypeDao.findSystemWidgetTypes(tenantId, fullSearch, pageLink); return widgetTypeDao.findSystemWidgetTypes(tenantId, fullSearch, deprecatedFilter, widgetTypes, pageLink);
} }
@Override @Override
public PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink) { public PageData<WidgetTypeInfo> findAllTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
log.trace("Executing findAllTenantWidgetTypesByTenantIdAndPageLink, tenantId [{}], fullSearch [{}], pageLink [{}]", tenantId, fullSearch, pageLink); log.trace("Executing findAllTenantWidgetTypesByTenantIdAndPageLink, tenantId [{}], fullSearch [{}], deprecatedFilter [{}], widgetTypes [{}], pageLink [{}]",
tenantId, fullSearch, deprecatedFilter, widgetTypes, pageLink);
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Validator.validatePageLink(pageLink); Validator.validatePageLink(pageLink);
return widgetTypeDao.findAllTenantWidgetTypesByTenantId(tenantId.getId(), fullSearch, pageLink); return widgetTypeDao.findAllTenantWidgetTypesByTenantId(tenantId.getId(), fullSearch, deprecatedFilter, widgetTypes, pageLink);
} }
@Override @Override
public PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink) { public PageData<WidgetTypeInfo> findTenantWidgetTypesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
log.trace("Executing findTenantWidgetTypesByTenantIdAndPageLink, tenantId [{}], fullSearch [{}], pageLink [{}]", tenantId, fullSearch, pageLink); log.trace("Executing findTenantWidgetTypesByTenantIdAndPageLink, tenantId [{}], fullSearch [{}], deprecatedFilter [{}], widgetTypes [{}], pageLink [{}]",
tenantId, fullSearch, deprecatedFilter, widgetTypes, pageLink);
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Validator.validatePageLink(pageLink); Validator.validatePageLink(pageLink);
return widgetTypeDao.findTenantWidgetTypesByTenantId(tenantId.getId(), fullSearch, pageLink); return widgetTypeDao.findTenantWidgetTypesByTenantId(tenantId.getId(), fullSearch, deprecatedFilter, widgetTypes, pageLink);
} }
@Override @Override
@ -150,11 +153,14 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
} }
@Override @Override
public List<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId) { public PageData<WidgetTypeInfo> findWidgetTypesInfosByWidgetsBundleId(TenantId tenantId, WidgetsBundleId widgetsBundleId, boolean fullSearch,
log.trace("Executing findWidgetTypesInfosByWidgetsBundleId, tenantId [{}], widgetsBundleId [{}]", tenantId, widgetsBundleId); DeprecatedFilter deprecatedFilter, List<String> widgetTypes, PageLink pageLink) {
log.trace("Executing findWidgetTypesInfosByWidgetsBundleId, tenantId [{}], widgetsBundleId [{}], fullSearch [{}], deprecatedFilter [{}], widgetTypes [{}], pageLink [{}]",
tenantId, widgetsBundleId, fullSearch, deprecatedFilter, widgetTypes, pageLink);
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Validator.validateId(widgetsBundleId, INCORRECT_WIDGETS_BUNDLE_ID + widgetsBundleId); Validator.validateId(widgetsBundleId, INCORRECT_WIDGETS_BUNDLE_ID + widgetsBundleId);
return widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(tenantId.getId(), widgetsBundleId.getId()); Validator.validatePageLink(pageLink);
return widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(tenantId.getId(), widgetsBundleId.getId(), fullSearch, deprecatedFilter, widgetTypes, pageLink);
} }
@Override @Override
@ -230,7 +236,7 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
@Override @Override
protected PageData<WidgetTypeInfo> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) { protected PageData<WidgetTypeInfo> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
return widgetTypeDao.findTenantWidgetTypesByTenantId(id.getId(), false, pageLink); return widgetTypeDao.findTenantWidgetTypesByTenantId(id.getId(), false, DeprecatedFilter.ALL, null, pageLink);
} }
@Override @Override

4
dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleDao.java

@ -54,7 +54,7 @@ public interface WidgetsBundleDao extends Dao<WidgetsBundle>, ExportableEntityDa
* @param pageLink the page link * @param pageLink the page link
* @return the list of widgets bundles objects * @return the list of widgets bundles objects
*/ */
PageData<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId, PageLink pageLink); PageData<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId, boolean fullSearch, PageLink pageLink);
/** /**
* Find tenant widgets bundles by tenantId and page link. * Find tenant widgets bundles by tenantId and page link.
@ -72,7 +72,7 @@ public interface WidgetsBundleDao extends Dao<WidgetsBundle>, ExportableEntityDa
* @param pageLink the page link * @param pageLink the page link
* @return the list of widgets bundles objects * @return the list of widgets bundles objects
*/ */
PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(UUID tenantId, PageLink pageLink); PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(UUID tenantId, boolean fullSearch, PageLink pageLink);
} }

16
dao/src/main/java/org/thingsboard/server/dao/widget/WidgetsBundleServiceImpl.java

@ -104,10 +104,10 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
} }
@Override @Override
public PageData<WidgetsBundle> findSystemWidgetsBundlesByPageLink(TenantId tenantId, PageLink pageLink) { public PageData<WidgetsBundle> findSystemWidgetsBundlesByPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink) {
log.trace("Executing findSystemWidgetsBundles, pageLink [{}]", pageLink); log.trace("Executing findSystemWidgetsBundles, fullSearch [{}], pageLink [{}]", fullSearch, pageLink);
Validator.validatePageLink(pageLink); Validator.validatePageLink(pageLink);
return widgetsBundleDao.findSystemWidgetsBundles(tenantId, pageLink); return widgetsBundleDao.findSystemWidgetsBundles(tenantId, fullSearch, pageLink);
} }
@Override @Override
@ -117,7 +117,7 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
PageLink pageLink = new PageLink(DEFAULT_WIDGETS_BUNDLE_LIMIT); PageLink pageLink = new PageLink(DEFAULT_WIDGETS_BUNDLE_LIMIT);
PageData<WidgetsBundle> pageData; PageData<WidgetsBundle> pageData;
do { do {
pageData = findSystemWidgetsBundlesByPageLink(tenantId, pageLink); pageData = findSystemWidgetsBundlesByPageLink(tenantId, false, pageLink);
widgetsBundles.addAll(pageData.getData()); widgetsBundles.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
@ -135,11 +135,11 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
} }
@Override @Override
public PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink) { public PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantIdAndPageLink(TenantId tenantId, boolean fullSearch, PageLink pageLink) {
log.trace("Executing findAllTenantWidgetsBundlesByTenantIdAndPageLink, tenantId [{}], pageLink [{}]", tenantId, pageLink); log.trace("Executing findAllTenantWidgetsBundlesByTenantIdAndPageLink, tenantId [{}], fullSearch [{}], pageLink [{}]", tenantId, fullSearch, pageLink);
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId); Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Validator.validatePageLink(pageLink); Validator.validatePageLink(pageLink);
return widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId.getId(), pageLink); return widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId.getId(), fullSearch, pageLink);
} }
@Override @Override
@ -150,7 +150,7 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
PageLink pageLink = new PageLink(DEFAULT_WIDGETS_BUNDLE_LIMIT); PageLink pageLink = new PageLink(DEFAULT_WIDGETS_BUNDLE_LIMIT);
PageData<WidgetsBundle> pageData; PageData<WidgetsBundle> pageData;
do { do {
pageData = findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, pageLink); pageData = findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, false, pageLink);
widgetsBundles.addAll(pageData.getData()); widgetsBundles.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();

2
dao/src/main/resources/sql/schema-entities.sql

@ -489,6 +489,7 @@ CREATE TABLE IF NOT EXISTS widget_type (
image varchar(1000000), image varchar(1000000),
deprecated boolean NOT NULL DEFAULT false, deprecated boolean NOT NULL DEFAULT false,
description varchar(1024), description varchar(1024),
tags text[],
external_id uuid, external_id uuid,
CONSTRAINT uq_widget_type_fqn UNIQUE (tenant_id, fqn), CONSTRAINT uq_widget_type_fqn UNIQUE (tenant_id, fqn),
CONSTRAINT widget_type_external_id_unq_key UNIQUE (tenant_id, external_id) CONSTRAINT widget_type_external_id_unq_key UNIQUE (tenant_id, external_id)
@ -696,6 +697,7 @@ CREATE TABLE IF NOT EXISTS api_usage_state (
db_storage varchar(32), db_storage varchar(32),
re_exec varchar(32), re_exec varchar(32),
js_exec varchar(32), js_exec varchar(32),
tbel_exec varchar(32),
email_exec varchar(32), email_exec varchar(32),
sms_exec varchar(32), sms_exec varchar(32),
alarm_exec varchar(32), alarm_exec varchar(32),

6
dao/src/main/resources/sql/schema-views-and-functions.sql

@ -285,3 +285,9 @@ BEGIN
RETURN json_build_object('success', true, 'modified', modified, 'alarm', row_to_json(result))::text; RETURN json_build_object('success', true, 'modified', modified, 'alarm', row_to_json(result))::text;
END END
$$; $$;
DROP VIEW IF EXISTS widget_type_info_view CASCADE;
CREATE OR REPLACE VIEW widget_type_info_view AS
SELECT t.*
, COALESCE((t.descriptor::json->>'type')::text, '') as widget_type
FROM widget_type t;

8
dao/src/test/java/org/thingsboard/server/dao/service/WidgetsBundleServiceTest.java

@ -174,7 +174,7 @@ public class WidgetsBundleServiceTest extends AbstractServiceTest {
PageLink pageLink = new PageLink(19); PageLink pageLink = new PageLink(19);
PageData<WidgetsBundle> pageData = null; PageData<WidgetsBundle> pageData = null;
do { do {
pageData = widgetsBundleService.findSystemWidgetsBundlesByPageLink(tenantId, pageLink); pageData = widgetsBundleService.findSystemWidgetsBundlesByPageLink(tenantId, false, pageLink);
loadedWidgetsBundles.addAll(pageData.getData()); loadedWidgetsBundles.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
@ -297,7 +297,7 @@ public class WidgetsBundleServiceTest extends AbstractServiceTest {
PageLink pageLink = new PageLink(17); PageLink pageLink = new PageLink(17);
PageData<WidgetsBundle> pageData = null; PageData<WidgetsBundle> pageData = null;
do { do {
pageData = widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, pageLink); pageData = widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, false, pageLink);
loadedWidgetsBundles.addAll(pageData.getData()); loadedWidgetsBundles.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
@ -314,7 +314,7 @@ public class WidgetsBundleServiceTest extends AbstractServiceTest {
loadedWidgetsBundles.clear(); loadedWidgetsBundles.clear();
pageLink = new PageLink(14); pageLink = new PageLink(14);
do { do {
pageData = widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, pageLink); pageData = widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, false, pageLink);
loadedWidgetsBundles.addAll(pageData.getData()); loadedWidgetsBundles.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
@ -336,7 +336,7 @@ public class WidgetsBundleServiceTest extends AbstractServiceTest {
loadedWidgetsBundles.clear(); loadedWidgetsBundles.clear();
pageLink = new PageLink(18); pageLink = new PageLink(18);
do { do {
pageData = widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, pageLink); pageData = widgetsBundleService.findAllTenantWidgetsBundlesByTenantIdAndPageLink(tenantId, false, pageLink);
loadedWidgetsBundles.addAll(pageData.getData()); loadedWidgetsBundles.addAll(pageData.getData());
if (pageData.hasNext()) { if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();

67
dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java

@ -20,10 +20,17 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.widget.BaseWidgetType;
import org.thingsboard.server.common.data.widget.DeprecatedFilter;
import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetTypeInfo;
import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.common.data.widget.WidgetsBundleWidget; import org.thingsboard.server.common.data.widget.WidgetsBundleWidget;
import org.thingsboard.server.dao.AbstractJpaDaoTest; import org.thingsboard.server.dao.AbstractJpaDaoTest;
@ -31,7 +38,10 @@ import org.thingsboard.server.dao.widget.WidgetTypeDao;
import org.thingsboard.server.dao.widget.WidgetsBundleDao; import org.thingsboard.server.dao.widget.WidgetsBundleDao;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.UUID;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@ -43,7 +53,7 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
final String BUNDLE_ALIAS = "BUNDLE_ALIAS"; final String BUNDLE_ALIAS = "BUNDLE_ALIAS";
final int WIDGET_TYPE_COUNT = 3; final int WIDGET_TYPE_COUNT = 3;
List<WidgetType> widgetTypeList; List<WidgetTypeDetails> widgetTypeList;
WidgetsBundle widgetsBundle; WidgetsBundle widgetsBundle;
@Autowired @Autowired
@ -64,17 +74,24 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
this.widgetsBundle = widgetsBundleDao.save(TenantId.SYS_TENANT_ID, widgetsBundle); this.widgetsBundle = widgetsBundleDao.save(TenantId.SYS_TENANT_ID, widgetsBundle);
for (int i = 0; i < WIDGET_TYPE_COUNT; i++) { for (int i = 0; i < WIDGET_TYPE_COUNT; i++) {
var widgetType = createAndSaveWidgetType(i); var widgetType = createAndSaveWidgetType(TenantId.SYS_TENANT_ID, i);
widgetTypeList.add(widgetType); widgetTypeList.add(widgetType);
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(this.widgetsBundle.getId(), widgetType.getId(), i)); widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(this.widgetsBundle.getId(), widgetType.getId(), i));
} }
widgetTypeList.sort(Comparator.comparing(BaseWidgetType::getName));
} }
WidgetType createAndSaveWidgetType(int number) { WidgetTypeDetails createAndSaveWidgetType(TenantId tenantId, int number) {
WidgetTypeDetails widgetType = new WidgetTypeDetails(); WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(TenantId.SYS_TENANT_ID); widgetType.setTenantId(tenantId);
widgetType.setName("WIDGET_TYPE_" + number); widgetType.setName("WIDGET_TYPE_" + number);
widgetType.setDescription("WIDGET_TYPE_DESCRIPTION" + number);
widgetType.setFqn("FQN_" + number); widgetType.setFqn("FQN_" + number);
var descriptor = JacksonUtil.newObjectNode();
descriptor.put("type", number % 2 == 0 ? "latest" : "static");
widgetType.setDescriptor(descriptor);
String[] tags = new String[]{"Tag1_"+number, "Tag2_"+number, "TEST_"+number};
widgetType.setTags(tags);
return widgetTypeDao.save(TenantId.SYS_TENANT_ID, widgetType); return widgetTypeDao.save(TenantId.SYS_TENANT_ID, widgetType);
} }
@ -92,6 +109,48 @@ public class JpaWidgetTypeDaoTest extends AbstractJpaDaoTest {
assertEquals(WIDGET_TYPE_COUNT, widgetTypes.size()); assertEquals(WIDGET_TYPE_COUNT, widgetTypes.size());
} }
@Test
public void testFindSystemWidgetTypes() {
PageData<WidgetTypeInfo> widgetTypes = widgetTypeDao.findSystemWidgetTypes(TenantId.SYS_TENANT_ID, true, DeprecatedFilter.ALL, Collections.singletonList("static"),
new PageLink(1024, 0, "TYPE_DESCRIPTION", new SortOrder("name")));
assertEquals(1, widgetTypes.getData().size());
assertEquals(new WidgetTypeInfo(widgetTypeList.get(1)), widgetTypes.getData().get(0));
widgetTypes = widgetTypeDao.findSystemWidgetTypes(TenantId.SYS_TENANT_ID, true, DeprecatedFilter.ALL, Collections.emptyList(),
new PageLink(1024, 0, "hfgfd tag2_2 ghg", new SortOrder("name")));
assertEquals(1, widgetTypes.getData().size());
assertEquals(new WidgetTypeInfo(widgetTypeList.get(2)), widgetTypes.getData().get(0));
}
@Test
public void testFindTenantWidgetTypesByTenantId() {
UUID tenantId = Uuids.timeBased();
for (int i = 0; i < WIDGET_TYPE_COUNT; i++) {
var widgetType = createAndSaveWidgetType(new TenantId(tenantId), i);
widgetTypeList.add(widgetType);
}
PageData<WidgetTypeInfo> widgetTypes = widgetTypeDao.findTenantWidgetTypesByTenantId(tenantId, true, DeprecatedFilter.ALL, null,
new PageLink(10, 0, "", new SortOrder("name")));
assertEquals(WIDGET_TYPE_COUNT, widgetTypes.getData().size());
assertEquals(new WidgetTypeInfo(widgetTypeList.get(3)), widgetTypes.getData().get(0));
assertEquals(new WidgetTypeInfo(widgetTypeList.get(4)), widgetTypes.getData().get(1));
assertEquals(new WidgetTypeInfo(widgetTypeList.get(5)), widgetTypes.getData().get(2));
}
@Test
public void testFindByWidgetTypeInfosByBundleId() {
PageData<WidgetTypeInfo> widgetTypes = widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(TenantId.SYS_TENANT_ID.getId(), widgetsBundle.getUuidId(),true, DeprecatedFilter.ALL, Collections.singletonList("latest"),
new PageLink(1024, 0, "TYPE_DESCRIPTION", new SortOrder("name")));
assertEquals(2, widgetTypes.getData().size());
assertEquals(new WidgetTypeInfo(widgetTypeList.get(0)), widgetTypes.getData().get(0));
assertEquals(new WidgetTypeInfo(widgetTypeList.get(2)), widgetTypes.getData().get(1));
widgetTypes = widgetTypeDao.findWidgetTypesInfosByWidgetsBundleId(TenantId.SYS_TENANT_ID.getId(), widgetsBundle.getUuidId(), true, DeprecatedFilter.ALL, Collections.emptyList(),
new PageLink(1024, 0, "hfgfd TEST_0 ghg", new SortOrder("name")));
assertEquals(1, widgetTypes.getData().size());
assertEquals(new WidgetTypeInfo(widgetTypeList.get(0)), widgetTypes.getData().get(0));
}
@Test @Test
public void testFindByTenantIdAndFqn() { public void testFindByTenantIdAndFqn() {
WidgetType result = widgetTypeList.get(0); WidgetType result = widgetTypeList.get(0);

137
dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java

@ -17,18 +17,27 @@ package org.thingsboard.server.dao.sql.widget;
import com.datastax.oss.driver.api.core.uuid.Uuids; import com.datastax.oss.driver.api.core.uuid.Uuids;
import org.junit.After; import org.junit.After;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.common.data.widget.WidgetsBundleWidget;
import org.thingsboard.server.dao.AbstractJpaDaoTest; import org.thingsboard.server.dao.AbstractJpaDaoTest;
import org.thingsboard.server.dao.widget.WidgetTypeDao;
import org.thingsboard.server.dao.widget.WidgetsBundleDao; import org.thingsboard.server.dao.widget.WidgetsBundleDao;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -38,15 +47,27 @@ import static org.junit.Assert.assertEquals;
public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest { public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
List<WidgetsBundle> widgetsBundles; List<WidgetsBundle> widgetsBundles;
List<WidgetType> widgetTypeList;
@Autowired @Autowired
private WidgetsBundleDao widgetsBundleDao; private WidgetsBundleDao widgetsBundleDao;
@Autowired
private WidgetTypeDao widgetTypeDao;
@Before
public void setUp() {
widgetTypeList = new ArrayList<>();
}
@After @After
public void tearDown() { public void tearDown() {
for (WidgetsBundle widgetsBundle : widgetsBundles) { for (WidgetsBundle widgetsBundle : widgetsBundles) {
widgetsBundleDao.removeById(widgetsBundle.getTenantId(), widgetsBundle.getUuidId()); widgetsBundleDao.removeById(widgetsBundle.getTenantId(), widgetsBundle.getUuidId());
} }
for (WidgetType widgetType : widgetTypeList) {
widgetTypeDao.removeById(TenantId.SYS_TENANT_ID, widgetType.getUuidId());
}
} }
@Test @Test
@ -72,14 +93,53 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
assertEquals(30, widgetsBundles.size()); assertEquals(30, widgetsBundles.size());
// Get first page // Get first page
PageLink pageLink = new PageLink(10, 0, "WB"); PageLink pageLink = new PageLink(10, 0, "WB");
PageData<WidgetsBundle> widgetsBundles1 = widgetsBundleDao.findSystemWidgetsBundles(TenantId.SYS_TENANT_ID, pageLink); PageData<WidgetsBundle> widgetsBundles1 = widgetsBundleDao.findSystemWidgetsBundles(TenantId.SYS_TENANT_ID, false, pageLink);
assertEquals(10, widgetsBundles1.getData().size()); assertEquals(10, widgetsBundles1.getData().size());
// Get next page // Get next page
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
PageData<WidgetsBundle> widgetsBundles2 = widgetsBundleDao.findSystemWidgetsBundles(TenantId.SYS_TENANT_ID, pageLink); PageData<WidgetsBundle> widgetsBundles2 = widgetsBundleDao.findSystemWidgetsBundles(TenantId.SYS_TENANT_ID, false, pageLink);
assertEquals(10, widgetsBundles2.getData().size()); assertEquals(10, widgetsBundles2.getData().size());
} }
@Test
public void testFindSystemWidgetsBundlesFullSearch() {
createSystemWidgetBundles(30, "WB_");
widgetsBundles = widgetsBundleDao.find(TenantId.SYS_TENANT_ID).stream().sorted(Comparator.comparing(WidgetsBundle::getTitle)).collect(Collectors.toList());
assertEquals(30, widgetsBundles.size());
var widgetType1 = createAndSaveWidgetType(TenantId.SYS_TENANT_ID,1, "Test widget type 1", "This is the widget type 1", new String[]{"tag1", "Tag2", "TEST_TAG"});
var widgetType2 = createAndSaveWidgetType(TenantId.SYS_TENANT_ID,2, "Test widget type 2", "This is the widget type 2", new String[]{"tag3", "Tag5", "TEST_Tag2"});
var widgetsBundle1 = widgetsBundles.get(10);
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle1.getId(), widgetType1.getId(), 0));
var widgetsBundle2 = widgetsBundles.get(15);
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle2.getId(), widgetType2.getId(), 0));
var widgetsBundle3 = widgetsBundles.get(28);
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle3.getId(), widgetType1.getId(), 0));
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle3.getId(), widgetType2.getId(), 1));
PageLink pageLink = new PageLink(10, 0, "widget type 1", new SortOrder("title"));
PageData<WidgetsBundle> widgetsBundles1 = widgetsBundleDao.findSystemWidgetsBundles(TenantId.SYS_TENANT_ID, true, pageLink);
assertEquals(2, widgetsBundles1.getData().size());
assertEquals(widgetsBundle1, widgetsBundles1.getData().get(0));
assertEquals(widgetsBundle3, widgetsBundles1.getData().get(1));
pageLink = new PageLink(10, 0, "Test widget type 2", new SortOrder("title"));
PageData<WidgetsBundle> widgetsBundles2 = widgetsBundleDao.findSystemWidgetsBundles(TenantId.SYS_TENANT_ID, true, pageLink);
assertEquals(2, widgetsBundles2.getData().size());
assertEquals(widgetsBundle2, widgetsBundles2.getData().get(0));
assertEquals(widgetsBundle3, widgetsBundles2.getData().get(1));
pageLink = new PageLink(10, 0, "ppp Fd v TAG1 tt", new SortOrder("title"));
PageData<WidgetsBundle> widgetsBundles3 = widgetsBundleDao.findSystemWidgetsBundles(TenantId.SYS_TENANT_ID, true, pageLink);
assertEquals(2, widgetsBundles3.getData().size());
assertEquals(widgetsBundle1, widgetsBundles3.getData().get(0));
assertEquals(widgetsBundle3, widgetsBundles3.getData().get(1));
}
@Test @Test
public void testFindWidgetsBundlesByTenantId() { public void testFindWidgetsBundlesByTenantId() {
UUID tenantId1 = Uuids.timeBased(); UUID tenantId1 = Uuids.timeBased();
@ -120,22 +180,71 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
assertEquals(100, widgetsBundleDao.find(TenantId.SYS_TENANT_ID).size()); assertEquals(100, widgetsBundleDao.find(TenantId.SYS_TENANT_ID).size());
PageLink pageLink = new PageLink(30, 0, "WB"); PageLink pageLink = new PageLink(30, 0, "WB");
PageData<WidgetsBundle> widgetsBundles1 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, pageLink); PageData<WidgetsBundle> widgetsBundles1 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, false, pageLink);
assertEquals(30, widgetsBundles1.getData().size()); assertEquals(30, widgetsBundles1.getData().size());
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
PageData<WidgetsBundle> widgetsBundles2 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, pageLink); PageData<WidgetsBundle> widgetsBundles2 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, false, pageLink);
assertEquals(30, widgetsBundles2.getData().size()); assertEquals(30, widgetsBundles2.getData().size());
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
PageData<WidgetsBundle> widgetsBundles3 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, pageLink); PageData<WidgetsBundle> widgetsBundles3 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, false, pageLink);
assertEquals(10, widgetsBundles3.getData().size()); assertEquals(10, widgetsBundles3.getData().size());
pageLink = pageLink.nextPageLink(); pageLink = pageLink.nextPageLink();
PageData<WidgetsBundle> widgetsBundles4 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, pageLink); PageData<WidgetsBundle> widgetsBundles4 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, false, pageLink);
assertEquals(0, widgetsBundles4.getData().size()); assertEquals(0, widgetsBundles4.getData().size());
} }
@Test
public void testFindAllWidgetsBundlesByTenantIdFullSearch() {
UUID tenantId1 = Uuids.timeBased();
UUID tenantId2 = Uuids.timeBased();
for (int i = 0; i < 10; i++) {
createWidgetBundles(5, tenantId1, "WB1_" + i + "_");
createWidgetBundles(3, tenantId2, "WB2_" + i + "_");
createSystemWidgetBundles(2, "WB_SYS_" + i + "_");
}
widgetsBundles = widgetsBundleDao.find(TenantId.SYS_TENANT_ID).stream().sorted(Comparator.comparing(WidgetsBundle::getTitle)).collect(Collectors.toList());;
assertEquals(100, widgetsBundleDao.find(TenantId.SYS_TENANT_ID).size());
var widgetType1 = createAndSaveWidgetType(new TenantId(tenantId1), 1, "Test widget type 1", "This is the widget type 1", new String[]{"tag1", "Tag2", "TEST_TAG"});
var widgetType2 = createAndSaveWidgetType(new TenantId(tenantId2), 2, "Test widget type 2", "This is the widget type 2", new String[]{"tag3", "Tag5", "TEST_Tag2"});
var widgetsBundle1 = widgetsBundles.stream().filter(widgetsBundle -> widgetsBundle.getTenantId().getId().equals(tenantId1)).collect(Collectors.toList()).get(10);
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle1.getId(), widgetType1.getId(), 0));
var widgetsBundle2 = widgetsBundles.stream().filter(widgetsBundle -> widgetsBundle.getTenantId().getId().equals(tenantId2)).collect(Collectors.toList()).get(15);
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle2.getId(), widgetType2.getId(), 0));
var widgetsBundle3 = widgetsBundles.stream().filter(widgetsBundle -> widgetsBundle.getTenantId().getId().equals(tenantId2)).collect(Collectors.toList()).get(28);
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle3.getId(), widgetType1.getId(), 0));
widgetTypeDao.saveWidgetsBundleWidget(new WidgetsBundleWidget(widgetsBundle3.getId(), widgetType2.getId(), 1));
PageLink pageLink = new PageLink(10, 0, "widget type 1", new SortOrder("title"));
PageData<WidgetsBundle> widgetsBundles1 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, true, pageLink);
assertEquals(1, widgetsBundles1.getData().size());
assertEquals(widgetsBundle1, widgetsBundles1.getData().get(0));
pageLink = new PageLink(10, 0, "Test widget type 2", new SortOrder("title"));
PageData<WidgetsBundle> widgetsBundles2 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, true, pageLink);
assertEquals(0, widgetsBundles2.getData().size());
PageData<WidgetsBundle> widgetsBundles3 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId2, true, pageLink);
assertEquals(2, widgetsBundles3.getData().size());
assertEquals(widgetsBundle2, widgetsBundles3.getData().get(0));
assertEquals(widgetsBundle3, widgetsBundles3.getData().get(1));
pageLink = new PageLink(10, 0, "ttt Tag2 ffff hhhh", new SortOrder("title"));
PageData<WidgetsBundle> widgetsBundles4 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId1, true, pageLink);
assertEquals(1, widgetsBundles4.getData().size());
assertEquals(widgetsBundle1, widgetsBundles4.getData().get(0));
PageData<WidgetsBundle> widgetsBundles5 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId2, true, pageLink);
assertEquals(1, widgetsBundles5.getData().size());
assertEquals(widgetsBundle3, widgetsBundles5.getData().get(0));
}
@Test @Test
public void testSearchTextNotFound() { public void testSearchTextNotFound() {
UUID tenantId = Uuids.timeBased(); UUID tenantId = Uuids.timeBased();
@ -144,7 +253,7 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
widgetsBundles = widgetsBundleDao.find(TenantId.SYS_TENANT_ID); widgetsBundles = widgetsBundleDao.find(TenantId.SYS_TENANT_ID);
assertEquals(10, widgetsBundleDao.find(TenantId.SYS_TENANT_ID).size()); assertEquals(10, widgetsBundleDao.find(TenantId.SYS_TENANT_ID).size());
PageLink textPageLink = new PageLink(30, 0, "TEXT_NOT_FOUND"); PageLink textPageLink = new PageLink(30, 0, "TEXT_NOT_FOUND");
PageData<WidgetsBundle> widgetsBundles4 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId, textPageLink); PageData<WidgetsBundle> widgetsBundles4 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId, false, textPageLink);
assertEquals(0, widgetsBundles4.getData().size()); assertEquals(0, widgetsBundles4.getData().size());
} }
@ -169,4 +278,16 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
widgetsBundleDao.save(TenantId.SYS_TENANT_ID, widgetsBundle); widgetsBundleDao.save(TenantId.SYS_TENANT_ID, widgetsBundle);
} }
} }
WidgetType createAndSaveWidgetType(TenantId tenantId, int number, String name, String description, String[] tags) {
WidgetTypeDetails widgetType = new WidgetTypeDetails();
widgetType.setTenantId(tenantId);
widgetType.setName(name);
widgetType.setDescription(description);
widgetType.setTags(tags);
widgetType.setFqn("FQN_" + number);
var saved = widgetTypeDao.save(TenantId.SYS_TENANT_ID, widgetType);
this.widgetTypeList.add(saved);
return saved;
}
} }

2
monitoring/pom.xml

@ -21,7 +21,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>

2
msa/black-box-tests/pom.xml

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

2
msa/js-executor/package.json

@ -1,7 +1,7 @@
{ {
"name": "thingsboard-js-executor", "name": "thingsboard-js-executor",
"private": true, "private": true,
"version": "3.6.0", "version": "3.6.1",
"description": "ThingsBoard JavaScript Executor Microservice", "description": "ThingsBoard JavaScript Executor Microservice",
"main": "server.ts", "main": "server.ts",
"bin": "server.js", "bin": "server.js",

2
msa/js-executor/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

2
msa/monitoring/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>

2
msa/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>

2
msa/tb-node/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

2
msa/tb/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

2
msa/transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa.transport</groupId> <groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa.transport</groupId> <groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/lwm2m/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa.transport</groupId> <groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/mqtt/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa.transport</groupId> <groupId>org.thingsboard.msa.transport</groupId>

2
msa/transport/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

2
msa/transport/snmp/pom.xml

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
</parent> </parent>
<groupId>org.thingsboard.msa.transport</groupId> <groupId>org.thingsboard.msa.transport</groupId>

2
msa/vc-executor-docker/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

2
msa/vc-executor/pom.xml

@ -21,7 +21,7 @@
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

2
msa/web-ui/package.json

@ -1,7 +1,7 @@
{ {
"name": "thingsboard-web-ui", "name": "thingsboard-web-ui",
"private": true, "private": true,
"version": "3.6.0", "version": "3.6.1",
"description": "ThingsBoard Web UI Microservice", "description": "ThingsBoard Web UI Microservice",
"main": "server.ts", "main": "server.ts",
"bin": "server.js", "bin": "server.js",

2
msa/web-ui/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>msa</artifactId> <artifactId>msa</artifactId>
</parent> </parent>
<groupId>org.thingsboard.msa</groupId> <groupId>org.thingsboard.msa</groupId>

4
netty-mqtt/pom.xml

@ -19,11 +19,11 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>netty-mqtt</artifactId> <artifactId>netty-mqtt</artifactId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Netty MQTT Client</name> <name>Netty MQTT Client</name>

8
pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Thingsboard</name> <name>Thingsboard</name>
@ -121,6 +121,7 @@
<wire-schema.version>3.4.0</wire-schema.version> <wire-schema.version>3.4.0</wire-schema.version>
<twilio.version>8.17.0</twilio.version> <twilio.version>8.17.0</twilio.version>
<hibernate-validator.version>6.0.20.Final</hibernate-validator.version> <hibernate-validator.version>6.0.20.Final</hibernate-validator.version>
<hypersistence-utils.version>3.5.2</hypersistence-utils.version>
<javax.el.version>3.0.0</javax.el.version> <javax.el.version>3.0.0</javax.el.version>
<javax.validation-api.version>2.0.1.Final</javax.validation-api.version> <javax.validation-api.version>2.0.1.Final</javax.validation-api.version>
<antisamy.version>1.7.2</antisamy.version> <antisamy.version>1.7.2</antisamy.version>
@ -1923,6 +1924,11 @@
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version> <version>${hibernate-validator.version}</version>
</dependency> </dependency>
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-55</artifactId>
<version>${hypersistence-utils.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.glassfish</groupId> <groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId> <artifactId>javax.el</artifactId>

2
rest-client/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>rest-client</artifactId> <artifactId>rest-client</artifactId>

2
rule-engine/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>rule-engine</artifactId> <artifactId>rule-engine</artifactId>

2
rule-engine/rule-engine-api/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>rule-engine</artifactId> <artifactId>rule-engine</artifactId>
</parent> </parent>
<groupId>org.thingsboard.rule-engine</groupId> <groupId>org.thingsboard.rule-engine</groupId>

2
rule-engine/rule-engine-components/pom.xml

@ -22,7 +22,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>rule-engine</artifactId> <artifactId>rule-engine</artifactId>
</parent> </parent>
<groupId>org.thingsboard.rule-engine</groupId> <groupId>org.thingsboard.rule-engine</groupId>

2
tools/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>thingsboard</artifactId> <artifactId>thingsboard</artifactId>
</parent> </parent>
<artifactId>tools</artifactId> <artifactId>tools</artifactId>

2
transport/coap/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.transport</groupId> <groupId>org.thingsboard.transport</groupId>

2
transport/http/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.transport</groupId> <groupId>org.thingsboard.transport</groupId>

2
transport/lwm2m/pom.xml

@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.thingsboard</groupId> <groupId>org.thingsboard</groupId>
<version>3.6.0-SNAPSHOT</version> <version>3.6.1-SNAPSHOT</version>
<artifactId>transport</artifactId> <artifactId>transport</artifactId>
</parent> </parent>
<groupId>org.thingsboard.transport</groupId> <groupId>org.thingsboard.transport</groupId>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save