From bce5d9332ead54bfbc9accc1d2ada60b22500414 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 15 May 2018 17:47:00 +0300 Subject: [PATCH] Ability to change Root rule chain. --- .../actors/ruleChain/DefaultTbContext.java | 17 +--- .../actors/shared/EntityActorsManager.java | 2 +- .../shared/rulechain/RuleChainManager.java | 2 +- .../rulechain/SystemRuleChainManager.java | 6 +- .../server/actors/tenant/TenantActor.java | 8 ++ .../server/controller/BaseController.java | 13 +-- .../controller/RuleChainController.java | 94 +++++++++---------- .../dao/nosql/CassandraAbstractDao.java | 16 +++- .../server/dao/rule/BaseRuleChainService.java | 79 +++++++++------- .../dao/rule/CassandraRuleChainDao.java | 11 --- .../server/dao/rule/RuleChainDao.java | 9 -- .../server/dao/rule/RuleChainService.java | 6 +- .../server/dao/sql/rule/JpaRuleChainDao.java | 11 --- .../dao/sql/rule/RuleChainRepository.java | 8 -- .../rule/engine/api/TbContext.java | 6 -- .../engine/action/TbAbstractAlarmNode.java | 6 +- ui/src/app/api/rule-chain.service.js | 52 +++------- ui/src/app/locale/locale.constant.js | 4 + ui/src/app/rulechain/rulechain-card.tpl.html | 2 +- .../app/rulechain/rulechain-fieldset.tpl.html | 5 +- ui/src/app/rulechain/rulechain.directive.js | 1 + ui/src/app/rulechain/rulechain.routes.js | 2 +- ui/src/app/rulechain/rulechains.controller.js | 53 ++++++++--- ui/src/app/rulechain/rulechains.tpl.html | 4 +- 24 files changed, 196 insertions(+), 221 deletions(-) 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 2e8955bf1f..0508123078 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 @@ -84,21 +84,6 @@ class DefaultTbContext implements TbContext { mainCtx.getScheduler().scheduleOnce(Duration.create(delayInMs, TimeUnit.MILLISECONDS), target, msg, mainCtx.getActorSystem().dispatcher(), nodeCtx.getSelfActor()); } - @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()) { @@ -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 d4a1f34006..295bfb94ce 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 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 ff0c52ef45..11ed5a3363 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 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 10e247bdfc..a3094ded36 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 4441fb8d6c..3fd1698229 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 81e5179838..8619f8c9f6 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 getRuleChains( @@ -150,48 +189,6 @@ public class RuleChainController extends BaseController { @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); - if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) { - return checkNotNull(ruleChainService.findSystemRuleChains(pageLink)); - } else { - TenantId tenantId = getCurrentUser().getTenantId(); - TextPageData ruleChainsData = checkNotNull(ruleChainService.findAllTenantRuleChainsByTenantIdAndPageLink(tenantId, pageLink)); - List 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 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 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); @@ -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 ba186ccebe..3b98356121 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 9ce1fbebbc..4a64890360 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)); @@ -89,6 +83,31 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC return savedRuleChain; } + @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."); @@ -266,13 +285,6 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC return relationService.findByFrom(ruleNodeId, RelationTypeGroup.RULE_NODE); } - @Override - public TextPageData findSystemRuleChains(TextPageLink pageLink) { - Validator.validatePageLink(pageLink, "Incorrect PageLink object for search system rule chain request."); - List ruleChains = ruleChainDao.findRuleChainsByTenantId(SYSTEM_TENANT.getId(), pageLink); - return new TextPageData<>(ruleChains, pageLink); - } - @Override public TextPageData findTenantRuleChains(TenantId tenantId, TextPageLink pageLink) { Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request."); @@ -281,18 +293,13 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC return new TextPageData<>(ruleChains, pageLink); } - @Override - public TextPageData 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 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 ruleChainValidator = new DataValidator() { @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 47c8e86d61..56a20db4e0 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 findAllRuleChainsByTenantId(UUID tenantId, TextPageLink pageLink) { - log.debug("Try to find all rule chains by tenantId [{}] and pageLink [{}]", tenantId, pageLink); - List 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 b9a9932ad3..4a7cfaea7c 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 { */ List 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 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 d516e54be4..4dbe6c9de4 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 getRuleNodeRelations(RuleNodeId ruleNodeId); - TextPageData findSystemRuleChains(TextPageLink pageLink); - TextPageData findTenantRuleChains(TenantId tenantId, TextPageLink pageLink); - TextPageData 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 425369fa2e..fb5d20a702 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 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 3b5e4dbcd7..58d4aac70b 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 :idOffset ORDER BY rc.id") - List 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 fcb8912f03..01386de0fa 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 b5a5982031..adb861b9f8 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 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); }); } diff --git a/ui/src/app/api/rule-chain.service.js b/ui/src/app/api/rule-chain.service.js index 821d82d778..e7436dedc6 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(); diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js index fc161e7f5e..9d1052f3eb 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-card.tpl.html b/ui/src/app/rulechain/rulechain-card.tpl.html index 48a572c8e0..a3ebfffeb9 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. --> -
rulechain.system
+
rulechain.root
diff --git a/ui/src/app/rulechain/rulechain-fieldset.tpl.html b/ui/src/app/rulechain/rulechain-fieldset.tpl.html index 2189daaeee..9f786ab3dc 100644 --- a/ui/src/app/rulechain/rulechain-fieldset.tpl.html +++ b/ui/src/app/rulechain/rulechain-fieldset.tpl.html @@ -18,8 +18,11 @@ {{ 'rulechain.export' | translate }} +{{ 'rulechain.set-root' | translate }} {{ 'rulechain.delete' | translate }}
diff --git a/ui/src/app/rulechain/rulechain.directive.js b/ui/src/app/rulechain/rulechain.directive.js index b23cd98136..8d19229d99 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 2aefd82379..f649f53e5c 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/rulechains.controller.js b/ui/src/app/rulechain/rulechains.controller.js index 7c857f23b6..3da5a51147 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 = [ { @@ -40,6 +41,15 @@ export default function RuleChainsController(ruleChainService, userService, impo details: function() { return $translate.instant('rulechain.export') }, icon: "file_download" }, + { + 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); @@ -47,7 +57,7 @@ export default function RuleChainsController(ruleChainService, userService, impo 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 cf9d256d2e..c780b46e3c 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)"> + on-delete-rule-chain="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"> +