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 3264af4..83b304f 100644
--- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java
+++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java
@@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.plugin.PluginMetaData;
+import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleMetaData;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.widget.WidgetType;
@@ -54,6 +55,7 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.plugin.PluginService;
import org.thingsboard.server.dao.relation.RelationService;
+import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.rule.RuleService;
import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.dao.widget.WidgetTypeService;
@@ -119,6 +121,9 @@ public abstract class BaseController {
protected PluginService pluginService;
@Autowired
+ protected RuleChainService ruleChainService;
+
+ @Autowired
protected ActorService actorService;
@Autowired
@@ -295,6 +300,9 @@ public abstract class BaseController {
case RULE:
checkRule(new RuleId(entityId.getId()));
return;
+ case RULE_CHAIN:
+ checkRuleChain(new RuleChainId(entityId.getId()));
+ return;
case ASSET:
checkAsset(assetService.findAssetById(new AssetId(entityId.getId())));
return;
@@ -526,6 +534,28 @@ public abstract class BaseController {
return rule;
}
+ protected RuleChain checkRuleChain(RuleChainId ruleChainId) throws ThingsboardException {
+ checkNotNull(ruleChainId);
+ return checkRuleChain(ruleChainService.findRuleChainById(ruleChainId));
+ }
+
+ protected RuleChain checkRuleChain(RuleChain ruleChain) throws ThingsboardException {
+ checkNotNull(ruleChain);
+ 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);
+
+ }
+ }
+ return ruleChain;
+ }
+
+
protected String constructBaseUrl(HttpServletRequest request) {
String scheme = request.getScheme();
if (request.getHeader("x-forwarded-proto") != null) {
diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
new file mode 100644
index 0000000..012e077
--- /dev/null
+++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
@@ -0,0 +1,161 @@
+/**
+ * Copyright © 2016-2018 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.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import org.thingsboard.server.common.data.EntityType;
+import org.thingsboard.server.common.data.audit.ActionType;
+import org.thingsboard.server.common.data.id.PluginId;
+import org.thingsboard.server.common.data.id.RuleChainId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TextPageData;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
+import org.thingsboard.server.common.data.plugin.PluginMetaData;
+import org.thingsboard.server.common.data.rule.RuleChain;
+import org.thingsboard.server.common.data.security.Authority;
+import org.thingsboard.server.dao.model.ModelConstants;
+import org.thingsboard.server.exception.ThingsboardException;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api")
+public class RuleChainController extends BaseController {
+
+ public static final String RULE_CHAIN_ID = "ruleChainId";
+
+ @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET)
+ @ResponseBody
+ public RuleChain getRuleChainById(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
+ checkParameter(RULE_CHAIN_ID, strRuleChainId);
+ try {
+ RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
+ return checkRuleChain(ruleChainId);
+ } catch (Exception e) {
+ throw handleException(e);
+ }
+ }
+
+ @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @RequestMapping(value = "/ruleChain", method = RequestMethod.POST)
+ @ResponseBody
+ public RuleChain saveRuleChain(@RequestBody RuleChain ruleChain) throws ThingsboardException {
+ try {
+ boolean created = ruleChain.getId() == null;
+ ruleChain.setTenantId(getCurrentUser().getTenantId());
+ RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain));
+
+ logEntityAction(savedRuleChain.getId(), savedRuleChain,
+ null,
+ created ? ActionType.ADDED : ActionType.UPDATED, null);
+
+ return savedRuleChain;
+ } catch (Exception e) {
+
+ logEntityAction(emptyId(EntityType.RULE_CHAIN), ruleChain,
+ null, ruleChain.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
+
+ throw handleException(e);
+ }
+ }
+
+ @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @RequestMapping(value = "/ruleChains", params = {"limit"}, method = RequestMethod.GET)
+ @ResponseBody
+ public TextPageData<RuleChain> getRuleChains(
+ @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);
+ 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));
+ } catch (Exception e) {
+ throw handleException(e);
+ }
+ }
+
+ @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
+ @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.DELETE)
+ @ResponseStatus(value = HttpStatus.OK)
+ public void deleteRuleChain(@PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException {
+ checkParameter(RULE_CHAIN_ID, strRuleChainId);
+ try {
+ RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
+ RuleChain ruleChain = checkRuleChain(ruleChainId);
+ ruleChainService.deleteRuleChainById(ruleChainId);
+
+ logEntityAction(ruleChainId, ruleChain,
+ null,
+ ActionType.DELETED, null, strRuleChainId);
+
+ } catch (Exception e) {
+ logEntityAction(emptyId(EntityType.RULE_CHAIN),
+ null,
+ null,
+ ActionType.DELETED, e, strRuleChainId);
+ throw handleException(e);
+ }
+ }
+
+}