thingsboard-aplcache
Changes
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java 2(+1 -1)
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java 6(+5 -1)
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractAlarmNode.java 6(+3 -3)
ui/src/app/api/rule-chain.service.js 52(+11 -41)
ui/src/app/locale/locale.constant.js 4(+4 -0)
ui/src/app/rulechain/rulechains.controller.js 53(+40 -13)
Details
diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java
index 2e8955b..0508123 100644
--- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java
+++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java
@@ -85,21 +85,6 @@ class DefaultTbContext implements TbContext {
}
@Override
- public void tellOthers(TbMsg msg) {
- throw new RuntimeException("Not Implemented!");
- }
-
- @Override
- public void tellSibling(TbMsg msg, ServerAddress address) {
- throw new RuntimeException("Not Implemented!");
- }
-
- @Override
- public void ack(TbMsg msg) {
-
- }
-
- @Override
public void tellError(TbMsg msg, Throwable th) {
if (nodeCtx.getSelf().isDebugMode()) {
mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), msg, "", th);
@@ -119,7 +104,7 @@ class DefaultTbContext implements TbContext {
@Override
public TbMsg transformMsg(TbMsg origMsg, String type, EntityId originator, TbMsgMetaData metaData, String data) {
- return new TbMsg(origMsg.getId(), type, originator, metaData.copy(), data, nodeCtx.getSelf().getRuleChainId(), nodeCtx.getSelf().getId(), 0L);
+ return new TbMsg(origMsg.getId(), type, originator, metaData.copy(), data, origMsg.getRuleChainId(), origMsg.getRuleNodeId(), 0L);
}
@Override
diff --git a/application/src/main/java/org/thingsboard/server/actors/shared/EntityActorsManager.java b/application/src/main/java/org/thingsboard/server/actors/shared/EntityActorsManager.java
index d4a1f34..295bfb9 100644
--- a/application/src/main/java/org/thingsboard/server/actors/shared/EntityActorsManager.java
+++ b/application/src/main/java/org/thingsboard/server/actors/shared/EntityActorsManager.java
@@ -67,7 +67,7 @@ public abstract class EntityActorsManager<T extends EntityId, A extends UntypedA
}
}
- protected void visit(M entity, ActorRef actorRef) {}
+ public void visit(M entity, ActorRef actorRef) {}
public ActorRef getOrCreateActor(ActorContext context, T entityId) {
return actors.computeIfAbsent(entityId, eId ->
diff --git a/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java b/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java
index ff0c52e..11ed5a3 100644
--- a/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java
+++ b/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/RuleChainManager.java
@@ -49,7 +49,7 @@ public abstract class RuleChainManager extends EntityActorsManager<RuleChainId,
}
@Override
- protected void visit(RuleChain entity, ActorRef actorRef) {
+ public void visit(RuleChain entity, ActorRef actorRef) {
if (entity.isRoot()) {
rootChain = entity;
rootChainActor = actorRef;
diff --git a/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java b/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java
index a8bb069..87f1b16 100644
--- a/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java
+++ b/application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java
@@ -20,10 +20,14 @@ import org.thingsboard.server.actors.service.DefaultActorService;
import org.thingsboard.server.actors.shared.plugin.PluginManager;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction;
+import org.thingsboard.server.common.data.page.TextPageData;
+import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.plugin.PluginMetaData;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.dao.plugin.BasePluginService;
+import java.util.Collections;
+
public class SystemRuleChainManager extends RuleChainManager {
public SystemRuleChainManager(ActorSystemContext systemContext) {
@@ -32,7 +36,7 @@ public class SystemRuleChainManager extends RuleChainManager {
@Override
protected FetchFunction<RuleChain> getFetchEntitiesFunction() {
- return service::findSystemRuleChains;
+ return link -> new TextPageData<>(Collections.emptyList(), link);
}
@Override
diff --git a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
index 10e247b..a3094de 100644
--- a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
+++ b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
@@ -30,8 +30,11 @@ import org.thingsboard.server.actors.service.ContextBasedCreator;
import org.thingsboard.server.actors.service.DefaultActorService;
import org.thingsboard.server.actors.shared.plugin.TenantPluginManager;
import org.thingsboard.server.actors.shared.rulechain.TenantRuleChainManager;
+import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.msg.TbActorMsg;
import org.thingsboard.server.common.msg.aware.DeviceAwareMsg;
import org.thingsboard.server.common.msg.device.DeviceToDeviceActorMsg;
@@ -130,6 +133,11 @@ public class TenantActor extends RuleChainManagerActor {
private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) {
ActorRef target = getEntityActorRef(msg.getEntityId());
if (target != null) {
+ if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) {
+ RuleChain ruleChain = systemContext.getRuleChainService().
+ findRuleChainById(new RuleChainId(msg.getEntityId().getId()));
+ ruleChainManager.visit(ruleChain, target);
+ }
target.tell(msg, ActorRef.noSender());
} else {
logger.debug("Invalid component lifecycle msg: {}", msg);
diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java
index 4441fb8..3fd1698 100644
--- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java
@@ -558,15 +558,10 @@ public abstract class BaseController {
SecurityUser authUser = getCurrentUser();
TenantId tenantId = ruleChain.getTenantId();
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
- if (authUser.getAuthority() != Authority.SYS_ADMIN) {
- if (authUser.getTenantId() == null ||
- !tenantId.getId().equals(ModelConstants.NULL_UUID) && !authUser.getTenantId().equals(tenantId)) {
- throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
- ThingsboardErrorCode.PERMISSION_DENIED);
-
- } else if (tenantId.getId().equals(ModelConstants.NULL_UUID)) {
- ruleChain.setConfiguration(null);
- }
+ if (authUser.getAuthority() != Authority.TENANT_ADMIN ||
+ !authUser.getTenantId().equals(tenantId)) {
+ throw new ThingsboardException(YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION,
+ ThingsboardErrorCode.PERMISSION_DENIED);
}
return ruleChain;
}
diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
index 81e5179..8619f8c 100644
--- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
@@ -64,7 +64,7 @@ public class RuleChainController extends BaseController {
@Autowired
private EventService eventService;
- @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET)
@ResponseBody
public RuleChain getRuleChainById(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
@@ -77,7 +77,7 @@ public class RuleChainController extends BaseController {
}
}
- @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChain/{ruleChainId}/metadata", method = RequestMethod.GET)
@ResponseBody
public RuleChainMetaData getRuleChainMetaData(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
@@ -92,7 +92,7 @@ public class RuleChainController extends BaseController {
}
- @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChain", method = RequestMethod.POST)
@ResponseBody
public RuleChain saveRuleChain(@RequestBody RuleChain ruleChain) throws ThingsboardException {
@@ -118,7 +118,46 @@ public class RuleChainController extends BaseController {
}
}
- @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
+ @RequestMapping(value = "/ruleChain/{ruleChainId}/root", method = RequestMethod.POST)
+ @ResponseBody
+ public RuleChain setRootRuleChain(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
+ checkParameter(RULE_CHAIN_ID, strRuleChainId);
+ try {
+ RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
+ RuleChain ruleChain = checkRuleChain(ruleChainId);
+ TenantId tenantId = getCurrentUser().getTenantId();
+ RuleChain previousRootRuleChain = ruleChainService.getRootTenantRuleChain(tenantId);
+ if (ruleChainService.setRootRuleChain(ruleChainId)) {
+
+ previousRootRuleChain = ruleChainService.findRuleChainById(previousRootRuleChain.getId());
+
+ actorService.onEntityStateChange(previousRootRuleChain.getTenantId(), previousRootRuleChain.getId(),
+ ComponentLifecycleEvent.UPDATED);
+
+ logEntityAction(previousRootRuleChain.getId(), previousRootRuleChain,
+ null, ActionType.UPDATED, null);
+
+ ruleChain = ruleChainService.findRuleChainById(ruleChainId);
+
+ actorService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(),
+ ComponentLifecycleEvent.UPDATED);
+
+ logEntityAction(ruleChain.getId(), ruleChain,
+ null, ActionType.UPDATED, null);
+
+ }
+ return ruleChain;
+ } catch (Exception e) {
+ logEntityAction(emptyId(EntityType.RULE_CHAIN),
+ null,
+ null,
+ ActionType.UPDATED, e, strRuleChainId);
+ throw handleException(e);
+ }
+ }
+
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChain/metadata", method = RequestMethod.POST)
@ResponseBody
public RuleChainMetaData saveRuleChainMetaData(@RequestBody RuleChainMetaData ruleChainMetaData) throws ThingsboardException {
@@ -142,7 +181,7 @@ public class RuleChainController extends BaseController {
}
}
- @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChains", params = {"limit"}, method = RequestMethod.GET)
@ResponseBody
public TextPageData<RuleChain> getRuleChains(
@@ -151,48 +190,6 @@ public class RuleChainController extends BaseController {
@RequestParam(required = false) String idOffset,
@RequestParam(required = false) String textOffset) throws ThingsboardException {
try {
- TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
- if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) {
- return checkNotNull(ruleChainService.findSystemRuleChains(pageLink));
- } else {
- TenantId tenantId = getCurrentUser().getTenantId();
- TextPageData<RuleChain> ruleChainsData = checkNotNull(ruleChainService.findAllTenantRuleChainsByTenantIdAndPageLink(tenantId, pageLink));
- List<RuleChain> ruleChains = ruleChainsData.getData();
- ruleChains.stream()
- .filter(ruleChain -> ruleChain.getTenantId().getId().equals(ModelConstants.NULL_UUID))
- .forEach(ruleChain -> ruleChain.setConfiguration(null));
- return ruleChainsData;
- }
- } catch (Exception e) {
- throw handleException(e);
- }
- }
-
- @PreAuthorize("hasAuthority('SYS_ADMIN')")
- @RequestMapping(value = "/system/ruleChains", params = {"limit"}, method = RequestMethod.GET)
- @ResponseBody
- public TextPageData<RuleChain> getSystemRuleChains(
- @RequestParam int limit,
- @RequestParam(required = false) String textSearch,
- @RequestParam(required = false) String idOffset,
- @RequestParam(required = false) String textOffset) throws ThingsboardException {
- try {
- TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
- return checkNotNull(ruleChainService.findSystemRuleChains(pageLink));
- } catch (Exception e) {
- throw handleException(e);
- }
- }
-
- @PreAuthorize("hasAuthority('TENANT_ADMIN')")
- @RequestMapping(value = "/tenant/ruleChains", params = {"limit"}, method = RequestMethod.GET)
- @ResponseBody
- public TextPageData<RuleChain> getTenantRuleChains(
- @RequestParam int limit,
- @RequestParam(required = false) String textSearch,
- @RequestParam(required = false) String idOffset,
- @RequestParam(required = false) String textOffset) throws ThingsboardException {
- try {
TenantId tenantId = getCurrentUser().getTenantId();
TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset);
return checkNotNull(ruleChainService.findTenantRuleChains(tenantId, pageLink));
@@ -201,7 +198,7 @@ public class RuleChainController extends BaseController {
}
}
- @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public void deleteRuleChain(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
@@ -209,6 +206,7 @@ public class RuleChainController extends BaseController {
try {
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChain ruleChain = checkRuleChain(ruleChainId);
+
ruleChainService.deleteRuleChainById(ruleChainId);
actorService.onEntityStateChange(ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.DELETED);
diff --git a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java
index ba186cc..3b98356 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractDao.java
@@ -88,15 +88,27 @@ public abstract class CassandraAbstractDao {
}
private ResultSet execute(Statement statement, ConsistencyLevel level) {
- log.debug("Execute cassandra statement {}", statement);
+ if (log.isDebugEnabled()) {
+ log.debug("Execute cassandra statement {}", statementToString(statement));
+ }
return executeAsync(statement, level).getUninterruptibly();
}
private ResultSetFuture executeAsync(Statement statement, ConsistencyLevel level) {
- log.debug("Execute cassandra async statement {}", statement);
+ if (log.isDebugEnabled()) {
+ log.debug("Execute cassandra async statement {}", statementToString(statement));
+ }
if (statement.getConsistencyLevel() == null) {
statement.setConsistencyLevel(level);
}
return new RateLimitedResultSetFuture(getSession(), rateLimiter, statement);
}
+
+ private static String statementToString(Statement statement) {
+ if (statement instanceof BoundStatement) {
+ return ((BoundStatement)statement).preparedStatement().getQueryString();
+ } else {
+ return statement.toString();
+ }
+ }
}
\ No newline at end of file
diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java
index 9ce1fbe..4a64890 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java
@@ -57,8 +57,6 @@ import java.util.stream.Collectors;
@Slf4j
public class BaseRuleChainService extends AbstractEntityService implements RuleChainService {
- public static final TenantId SYSTEM_TENANT = new TenantId(ModelConstants.NULL_UUID);
-
@Autowired
private RuleChainDao ruleChainDao;
@@ -71,12 +69,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
@Override
public RuleChain saveRuleChain(RuleChain ruleChain) {
ruleChainValidator.validate(ruleChain);
- if (ruleChain.getTenantId() == null) {
- log.trace("Save system rule chain with predefined id {}", SYSTEM_TENANT);
- ruleChain.setTenantId(SYSTEM_TENANT);
- }
RuleChain savedRuleChain = ruleChainDao.save(ruleChain);
- if (ruleChain.isRoot() && ruleChain.getTenantId() != null && ruleChain.getId() == null) {
+ if (ruleChain.isRoot() && ruleChain.getId() == null) {
try {
createRelation(new EntityRelation(savedRuleChain.getTenantId(), savedRuleChain.getId(),
EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
@@ -90,6 +84,31 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
}
@Override
+ public boolean setRootRuleChain(RuleChainId ruleChainId) {
+ RuleChain ruleChain = ruleChainDao.findById(ruleChainId.getId());
+ if (!ruleChain.isRoot()) {
+ RuleChain previousRootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
+ if (!previousRootRuleChain.getId().equals(ruleChain.getId())) {
+ try {
+ deleteRelation(new EntityRelation(previousRootRuleChain.getTenantId(), previousRootRuleChain.getId(),
+ EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
+ previousRootRuleChain.setRoot(false);
+ ruleChainDao.save(previousRootRuleChain);
+ createRelation(new EntityRelation(ruleChain.getTenantId(), ruleChain.getId(),
+ EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
+ ruleChain.setRoot(true);
+ ruleChainDao.save(ruleChain);
+ return true;
+ } catch (ExecutionException | InterruptedException e) {
+ log.warn("[{}] Failed to set root rule chain, ruleChainId: [{}]", ruleChainId);
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
public RuleChainMetaData saveRuleChainMetaData(RuleChainMetaData ruleChainMetaData) {
Validator.validateId(ruleChainMetaData.getRuleChainId(), "Incorrect rule chain id.");
RuleChain ruleChain = findRuleChainById(ruleChainMetaData.getRuleChainId());
@@ -267,13 +286,6 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
}
@Override
- public TextPageData<RuleChain> findSystemRuleChains(TextPageLink pageLink) {
- Validator.validatePageLink(pageLink, "Incorrect PageLink object for search system rule chain request.");
- List<RuleChain> ruleChains = ruleChainDao.findRuleChainsByTenantId(SYSTEM_TENANT.getId(), pageLink);
- return new TextPageData<>(ruleChains, pageLink);
- }
-
- @Override
public TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink) {
Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request.");
Validator.validatePageLink(pageLink, "Incorrect PageLink object for search rule chain request.");
@@ -282,17 +294,12 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
}
@Override
- public TextPageData<RuleChain> findAllTenantRuleChainsByTenantIdAndPageLink(TenantId tenantId, TextPageLink pageLink) {
- log.trace("Executing findAllTenantRuleChainsByTenantIdAndPageLink, tenantId [{}], pageLink [{}]", tenantId, pageLink);
- Validator.validateId(tenantId, "Incorrect tenantId " + tenantId);
- Validator.validatePageLink(pageLink, "Incorrect page link " + pageLink);
- List<RuleChain> ruleChains = ruleChainDao.findAllRuleChainsByTenantId(tenantId.getId(), pageLink);
- return new TextPageData<>(ruleChains, pageLink);
- }
-
- @Override
public void deleteRuleChainById(RuleChainId ruleChainId) {
Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request.");
+ RuleChain ruleChain = ruleChainDao.findById(ruleChainId.getId());
+ if (ruleChain != null && ruleChain.isRoot()) {
+ throw new DataValidationException("Deletion of Root Tenant Rule Chain is prohibited!");
+ }
checkRuleNodesAndDelete(ruleChainId);
}
@@ -325,6 +332,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
relationService.saveRelation(relation);
}
+ private void deleteRelation(EntityRelation relation) throws ExecutionException, InterruptedException {
+ log.debug("Deleting relation: {}", relation);
+ relationService.deleteRelation(relation);
+ }
+
private DataValidator<RuleChain> ruleChainValidator =
new DataValidator<RuleChain>() {
@Override
@@ -332,16 +344,17 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
if (StringUtils.isEmpty(ruleChain.getName())) {
throw new DataValidationException("Rule chain name should be specified!.");
}
- if (ruleChain.getTenantId() != null && !ruleChain.getTenantId().isNullUid()) {
- Tenant tenant = tenantDao.findById(ruleChain.getTenantId().getId());
- if (tenant == null) {
- throw new DataValidationException("Rule chain is referencing to non-existent tenant!");
- }
- if (ruleChain.isRoot()) {
- RuleChain rootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
- if (rootRuleChain != null && !rootRuleChain.getId().equals(ruleChain.getId())) {
- throw new DataValidationException("Another root rule chain is present in scope of current tenant!");
- }
+ if (ruleChain.getTenantId() == null || ruleChain.getTenantId().isNullUid()) {
+ throw new DataValidationException("Rule chain should be assigned to tenant!");
+ }
+ Tenant tenant = tenantDao.findById(ruleChain.getTenantId().getId());
+ if (tenant == null) {
+ throw new DataValidationException("Rule chain is referencing to non-existent tenant!");
+ }
+ if (ruleChain.isRoot()) {
+ RuleChain rootRuleChain = getRootTenantRuleChain(ruleChain.getTenantId());
+ if (rootRuleChain != null && !rootRuleChain.getId().equals(ruleChain.getId())) {
+ throw new DataValidationException("Another root rule chain is present in scope of current tenant!");
}
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java
index 47c8e86..56a20db 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/rule/CassandraRuleChainDao.java
@@ -60,15 +60,4 @@ public class CassandraRuleChainDao extends CassandraAbstractSearchTextDao<RuleCh
return DaoUtil.convertDataList(ruleChainEntities);
}
- @Override
- public List<RuleChain> findAllRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) {
- log.debug("Try to find all rule chains by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
- List<RuleChainEntity> ruleChainEntities = findPageWithTextSearch(RULE_CHAIN_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
- Arrays.asList(in(ModelConstants.RULE_CHAIN_TENANT_ID_PROPERTY, Arrays.asList(NULL_UUID, tenantId))),
- pageLink);
-
- log.trace("Found rule chains [{}] by tenantId [{}] and pageLink [{}]", ruleChainEntities, tenantId, pageLink);
- return DaoUtil.convertDataList(ruleChainEntities);
- }
-
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java
index b9a9932..4a7cfae 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainDao.java
@@ -37,13 +37,4 @@ public interface RuleChainDao extends Dao<RuleChain> {
*/
List<RuleChain> findRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink);
- /**
- * Find all rule chains by tenantId and page link.
- *
- * @param tenantId the tenantId
- * @param pageLink the page link
- * @return the list of rule chain objects
- */
- List<RuleChain> findAllRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink);
-
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java
index d516e54..4dbe6c9 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/rule/RuleChainService.java
@@ -36,6 +36,8 @@ public interface RuleChainService {
RuleChain saveRuleChain(RuleChain ruleChain);
+ boolean setRootRuleChain(RuleChainId ruleChainId);
+
RuleChainMetaData saveRuleChainMetaData(RuleChainMetaData ruleChainMetaData);
RuleChainMetaData loadRuleChainMetaData(RuleChainId ruleChainId);
@@ -54,12 +56,8 @@ public interface RuleChainService {
List<EntityRelation> getRuleNodeRelations(RuleNodeId ruleNodeId);
- TextPageData<RuleChain> findSystemRuleChains(TextPageLink pageLink);
-
TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink);
- TextPageData<RuleChain> findAllTenantRuleChainsByTenantIdAndPageLink(TenantId tenantId, TextPageLink pageLink);
-
void deleteRuleChainById(RuleChainId ruleChainId);
void deleteRuleChainsByTenantId(TenantId tenantId);
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java
index 425369f..fb5d20a 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaRuleChainDao.java
@@ -63,15 +63,4 @@ public class JpaRuleChainDao extends JpaAbstractSearchTextDao<RuleChainEntity, R
new PageRequest(0, pageLink.getLimit())));
}
- @Override
- public List<RuleChain> findAllRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) {
- return DaoUtil.convertDataList(ruleChainRepository
- .findAllTenantRuleChainsByTenantId(
- UUIDConverter.fromTimeUUID(tenantId),
- NULL_UUID_STR,
- Objects.toString(pageLink.getTextSearch(), ""),
- pageLink.getIdOffset() == null ? NULL_UUID_STR : UUIDConverter.fromTimeUUID(pageLink.getIdOffset()),
- new PageRequest(0, pageLink.getLimit())));
- }
-
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java
index 3b5e4db..58d4aac 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/RuleChainRepository.java
@@ -35,12 +35,4 @@ public interface RuleChainRepository extends CrudRepository<RuleChainEntity, Str
@Param("idOffset") String idOffset,
Pageable pageable);
- @Query("SELECT rc FROM RuleChainEntity rc WHERE rc.tenantId IN (:tenantId, :nullTenantId) " +
- "AND LOWER(rc.searchText) LIKE LOWER(CONCAT(:searchText, '%')) " +
- "AND rc.id > :idOffset ORDER BY rc.id")
- List<RuleChainEntity> findAllTenantRuleChainsByTenantId(@Param("tenantId") String tenantId,
- @Param("nullTenantId") String nullTenantId,
- @Param("searchText") String searchText,
- @Param("idOffset") String idOffset,
- Pageable pageable);
}
diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java
index fcb8912..01386de 100644
--- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java
+++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java
@@ -48,12 +48,6 @@ public interface TbContext {
void tellSelf(TbMsg msg, long delayMs);
- void tellOthers(TbMsg msg);
-
- void tellSibling(TbMsg msg, ServerAddress address);
-
- void ack(TbMsg msg);
-
void tellError(TbMsg msg, Throwable th);
void updateSelf(RuleNode self);
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractAlarmNode.java
index b5a5982..adb861b 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractAlarmNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractAlarmNode.java
@@ -69,13 +69,13 @@ public abstract class TbAbstractAlarmNode<C extends TbAbstractAlarmNodeConfigura
protected ListenableFuture<JsonNode> buildAlarmDetails(TbContext ctx, TbMsg msg, JsonNode previousDetails) {
return ctx.getJsExecutor().executeAsync(() -> {
- TbMsg theMsg = msg;
+ TbMsg dummyMsg = msg;
if (previousDetails != null) {
TbMsgMetaData metaData = msg.getMetaData().copy();
metaData.putValue(PREV_ALARM_DETAILS, mapper.writeValueAsString(previousDetails));
- theMsg = ctx.newMsg(msg.getType(), msg.getOriginator(), metaData, msg.getData());
+ dummyMsg = ctx.transformMsg(msg, msg.getType(), msg.getOriginator(), metaData, msg.getData());
}
- return buildDetailsJsEngine.executeJson(theMsg);
+ return buildDetailsJsEngine.executeJson(dummyMsg);
});
}
ui/src/app/api/rule-chain.service.js 52(+11 -41)
diff --git a/ui/src/app/api/rule-chain.service.js b/ui/src/app/api/rule-chain.service.js
index 821d82d..e7436de 100644
--- a/ui/src/app/api/rule-chain.service.js
+++ b/ui/src/app/api/rule-chain.service.js
@@ -22,11 +22,10 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
var ruleNodeComponents = null;
var service = {
- getSystemRuleChains: getSystemRuleChains,
- getTenantRuleChains: getTenantRuleChains,
getRuleChains: getRuleChains,
getRuleChain: getRuleChain,
saveRuleChain: saveRuleChain,
+ setRootRuleChain: setRootRuleChain,
deleteRuleChain: deleteRuleChain,
getRuleChainMetaData: getRuleChainMetaData,
saveRuleChainMetaData: saveRuleChainMetaData,
@@ -40,29 +39,9 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
return service;
- function getSystemRuleChains (pageLink, config) {
- var deferred = $q.defer();
- var url = '/api/system/ruleChains?limit=' + pageLink.limit;
- if (angular.isDefined(pageLink.textSearch)) {
- url += '&textSearch=' + pageLink.textSearch;
- }
- if (angular.isDefined(pageLink.idOffset)) {
- url += '&idOffset=' + pageLink.idOffset;
- }
- if (angular.isDefined(pageLink.textOffset)) {
- url += '&textOffset=' + pageLink.textOffset;
- }
- $http.get(url, config).then(function success(response) {
- deferred.resolve(response.data);
- }, function fail() {
- deferred.reject();
- });
- return deferred.promise;
- }
-
- function getTenantRuleChains (pageLink, config) {
+ function getRuleChains (pageLink, config) {
var deferred = $q.defer();
- var url = '/api/tenant/ruleChains?limit=' + pageLink.limit;
+ var url = '/api/ruleChains?limit=' + pageLink.limit;
if (angular.isDefined(pageLink.textSearch)) {
url += '&textSearch=' + pageLink.textSearch;
}
@@ -80,18 +59,9 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
return deferred.promise;
}
- function getRuleChains (pageLink, config) {
+ function getRuleChain(ruleChainId, config) {
var deferred = $q.defer();
- var url = '/api/ruleChains?limit=' + pageLink.limit;
- if (angular.isDefined(pageLink.textSearch)) {
- url += '&textSearch=' + pageLink.textSearch;
- }
- if (angular.isDefined(pageLink.idOffset)) {
- url += '&idOffset=' + pageLink.idOffset;
- }
- if (angular.isDefined(pageLink.textOffset)) {
- url += '&textOffset=' + pageLink.textOffset;
- }
+ var url = '/api/ruleChain/' + ruleChainId;
$http.get(url, config).then(function success(response) {
deferred.resolve(response.data);
}, function fail() {
@@ -100,10 +70,10 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
return deferred.promise;
}
- function getRuleChain(ruleChainId, config) {
+ function saveRuleChain(ruleChain) {
var deferred = $q.defer();
- var url = '/api/ruleChain/' + ruleChainId;
- $http.get(url, config).then(function success(response) {
+ var url = '/api/ruleChain';
+ $http.post(url, ruleChain).then(function success(response) {
deferred.resolve(response.data);
}, function fail() {
deferred.reject();
@@ -111,10 +81,10 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
return deferred.promise;
}
- function saveRuleChain(ruleChain) {
+ function setRootRuleChain(ruleChainId) {
var deferred = $q.defer();
- var url = '/api/ruleChain';
- $http.post(url, ruleChain).then(function success(response) {
+ var url = '/api/ruleChain/' + ruleChainId + '/root';
+ $http.post(url).then(function success(response) {
deferred.resolve(response.data);
}, function fail() {
deferred.reject();
ui/src/app/locale/locale.constant.js 4(+4 -0)
diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js
index fc161e7..9d1052f 100644
--- a/ui/src/app/locale/locale.constant.js
+++ b/ui/src/app/locale/locale.constant.js
@@ -1163,11 +1163,15 @@ export default angular.module('thingsboard.locale', [])
"rulechain": {
"rulechain": "Rule chain",
"rulechains": "Rule chains",
+ "root": "Root",
"delete": "Delete rule chain",
"name": "Name",
"name-required": "Name is required.",
"description": "Description",
"add": "Add Rule Chain",
+ "set-root": "Make rule chain root",
+ "set-root-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' root?",
+ "set-root-rulechain-text": "After the confirmation the rule chain will become root and will handle all incoming transport messages.",
"delete-rulechain-title": "Are you sure you want to delete the rule chain '{{ruleChainName}}'?",
"delete-rulechain-text": "Be careful, after the confirmation the rule chain and all related data will become unrecoverable.",
"delete-rulechains-title": "Are you sure you want to delete { count, select, 1 {1 rule chain} other {# rule chains} }?",
diff --git a/ui/src/app/rulechain/rulechain.directive.js b/ui/src/app/rulechain/rulechain.directive.js
index b23cd98..8d19229 100644
--- a/ui/src/app/rulechain/rulechain.directive.js
+++ b/ui/src/app/rulechain/rulechain.directive.js
@@ -40,6 +40,7 @@ export default function RuleChainDirective($compile, $templateCache, $mdDialog,
isEdit: '=',
isReadOnly: '=',
theForm: '=',
+ onSetRootRuleChain: '&',
onExportRuleChain: '&',
onDeleteRuleChain: '&'
}
diff --git a/ui/src/app/rulechain/rulechain.routes.js b/ui/src/app/rulechain/rulechain.routes.js
index 2aefd82..f649f53 100644
--- a/ui/src/app/rulechain/rulechain.routes.js
+++ b/ui/src/app/rulechain/rulechain.routes.js
@@ -81,7 +81,7 @@ export default function RuleChainRoutes($stateProvider, NodeTemplatePathProvider
pageTitle: 'rulechain.rulechain'
},
ncyBreadcrumb: {
- label: '{"icon": "settings_ethernet", "label": "{{ vm.ruleChain.name }}", "translate": "false"}'
+ label: '{"icon": "settings_ethernet", "label": "{{ vm.ruleChain.name + (vm.ruleChain.root ? (\' (\' + (\'rulechain.root\' | translate) + \')\') : \'\') }}", "translate": "false"}'
}
}).state('home.ruleChains.importRuleChain', {
url: '/ruleChain/import',
diff --git a/ui/src/app/rulechain/rulechain-card.tpl.html b/ui/src/app/rulechain/rulechain-card.tpl.html
index 48a572c..a3ebfff 100644
--- a/ui/src/app/rulechain/rulechain-card.tpl.html
+++ b/ui/src/app/rulechain/rulechain-card.tpl.html
@@ -15,4 +15,4 @@
limitations under the License.
-->
-<div class="tb-uppercase" ng-if="item && parentCtl.types.id.nullUid === item.tenantId.id" translate>rulechain.system</div>
+<div ng-if="item && item.root" translate>rulechain.root</div>
diff --git a/ui/src/app/rulechain/rulechain-fieldset.tpl.html b/ui/src/app/rulechain/rulechain-fieldset.tpl.html
index 2189daa..9f786ab 100644
--- a/ui/src/app/rulechain/rulechain-fieldset.tpl.html
+++ b/ui/src/app/rulechain/rulechain-fieldset.tpl.html
@@ -18,8 +18,11 @@
<md-button ng-click="onExportRuleChain({event: $event})"
ng-show="!isEdit"
class="md-raised md-primary">{{ 'rulechain.export' | translate }}</md-button>
+<md-button ng-click="onSetRootRuleChain({event: $event})"
+ ng-show="!isEdit && !ruleChain.root"
+ class="md-raised md-primary">{{ 'rulechain.set-root' | translate }}</md-button>
<md-button ng-click="onDeleteRuleChain({event: $event})"
- ng-show="!isEdit && !isReadOnly"
+ ng-show="!isEdit && !ruleChain.root"
class="md-raised md-primary">{{ 'rulechain.delete' | translate }}</md-button>
<div layout="row">
ui/src/app/rulechain/rulechains.controller.js 53(+40 -13)
diff --git a/ui/src/app/rulechain/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js
index 7c857f2..3da5a51 100644
--- a/ui/src/app/rulechain/rulechains.controller.js
+++ b/ui/src/app/rulechain/rulechains.controller.js
@@ -21,7 +21,8 @@ import ruleChainCard from './rulechain-card.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
-export default function RuleChainsController(ruleChainService, userService, importExport, $state, $stateParams, $filter, $translate, types) {
+export default function RuleChainsController(ruleChainService, userService, importExport, $state,
+ $stateParams, $filter, $translate, $mdDialog, types) {
var ruleChainActionsList = [
{
@@ -42,12 +43,21 @@ export default function RuleChainsController(ruleChainService, userService, impo
},
{
onAction: function ($event, item) {
+ setRootRuleChain($event, item);
+ },
+ name: function() { return $translate.instant('rulechain.set-root') },
+ details: function() { return $translate.instant('rulechain.set-root') },
+ icon: "flag",
+ isEnabled: isNonRootRuleChain
+ },
+ {
+ onAction: function ($event, item) {
vm.grid.deleteItem($event, item);
},
name: function() { return $translate.instant('action.delete') },
details: function() { return $translate.instant('rulechain.delete') },
icon: "delete",
- isEnabled: isRuleChainEditable
+ isEnabled: isNonRootRuleChain
}
];
@@ -107,10 +117,7 @@ export default function RuleChainsController(ruleChainService, userService, impo
addItemText: function() { return $translate.instant('rulechain.add-rulechain-text') },
noItemsText: function() { return $translate.instant('rulechain.no-rulechains-text') },
itemDetailsText: function() { return $translate.instant('rulechain.rulechain-details') },
- isSelectionEnabled: isRuleChainEditable,
- isDetailsReadOnly: function(ruleChain) {
- return !isRuleChainEditable(ruleChain);
- }
+ isSelectionEnabled: isNonRootRuleChain
};
if (angular.isDefined($stateParams.items) && $stateParams.items !== null) {
@@ -121,9 +128,11 @@ export default function RuleChainsController(ruleChainService, userService, impo
vm.ruleChainGridConfig.topIndex = $stateParams.topIndex;
}
- vm.isRuleChainEditable = isRuleChainEditable;
+ vm.isRootRuleChain = isRootRuleChain;
+ vm.isNonRootRuleChain = isNonRootRuleChain;
vm.exportRuleChain = exportRuleChain;
+ vm.setRootRuleChain = setRootRuleChain;
function deleteRuleChainTitle(ruleChain) {
return $translate.instant('rulechain.delete-rulechain-title', {ruleChainName: ruleChain.name});
@@ -172,12 +181,12 @@ export default function RuleChainsController(ruleChainService, userService, impo
return ruleChain ? ruleChain.name : '';
}
- function isRuleChainEditable(ruleChain) {
- if (userService.getAuthority() === 'TENANT_ADMIN') {
- return ruleChain && ruleChain.tenantId.id != types.id.nullUid;
- } else {
- return userService.getAuthority() === 'SYS_ADMIN';
- }
+ function isRootRuleChain(ruleChain) {
+ return ruleChain && ruleChain.root;
+ }
+
+ function isNonRootRuleChain(ruleChain) {
+ return ruleChain && !ruleChain.root;
}
function exportRuleChain($event, ruleChain) {
@@ -185,4 +194,22 @@ export default function RuleChainsController(ruleChainService, userService, impo
importExport.exportRuleChain(ruleChain.id.id);
}
+ function setRootRuleChain($event, ruleChain) {
+ $event.stopPropagation();
+ var confirm = $mdDialog.confirm()
+ .targetEvent($event)
+ .title($translate.instant('rulechain.set-root-rulechain-title', {ruleChainName: ruleChain.name}))
+ .htmlContent($translate.instant('rulechain.set-root-rulechain-text'))
+ .ariaLabel($translate.instant('rulechain.set-root'))
+ .cancel($translate.instant('action.no'))
+ .ok($translate.instant('action.yes'));
+ $mdDialog.show(confirm).then(function () {
+ ruleChainService.setRootRuleChain(ruleChain.id.id).then(
+ () => {
+ vm.grid.refreshList();
+ }
+ );
+ });
+
+ }
}
diff --git a/ui/src/app/rulechain/rulechains.tpl.html b/ui/src/app/rulechain/rulechains.tpl.html
index cf9d256..c780b46 100644
--- a/ui/src/app/rulechain/rulechains.tpl.html
+++ b/ui/src/app/rulechain/rulechains.tpl.html
@@ -26,8 +26,10 @@
is-edit="vm.grid.detailsConfig.isDetailsEditMode"
is-read-only="vm.grid.isDetailsReadOnly(vm.grid.operatingItem())"
the-form="vm.grid.detailsForm"
+ on-set-root-rule-chain="vm.setRootRuleChain(event, vm.grid.detailsConfig.currentItem)"
on-export-rule-chain="vm.exportRuleChain(event, vm.grid.detailsConfig.currentItem)"
- on-delete-rule-chain="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-rule-chain>
+ on-delete-rule-chain="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)">
+ </tb-rule-chain>
</md-tab>
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleChainEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}">
<tb-attribute-table flex