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 09b23b0429..78acd0b43b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -50,6 +50,7 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetInfo; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; +import org.thingsboard.server.common.data.edge.EdgeInfo; import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; @@ -643,6 +644,18 @@ public abstract class BaseController { } } + EdgeInfo checkEdgeInfoId(EdgeId edgeId, Operation operation) throws ThingsboardException { + try { + validateId(edgeId, "Incorrect edgeId " + edgeId); + EdgeInfo edge = edgeService.findEdgeInfoById(getCurrentUser().getTenantId(), edgeId); + checkNotNull(edge); + accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, operation, edgeId, edge); + return edge; + } catch (Exception e) { + throw handleException(e, false); + } + } + DashboardInfo checkDashboardInfoId(DashboardId dashboardId, Operation operation) throws ThingsboardException { try { validateId(dashboardId, "Incorrect dashboardId " + dashboardId); diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 7e60b840b4..6b4899f378 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -84,6 +84,19 @@ public class EdgeController extends BaseController { } } + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") + @RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET) + @ResponseBody + public EdgeInfo getEdgeInfoById(@PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { + checkParameter(EDGE_ID, strEdgeId); + try { + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); + return checkEdgeInfoId(edgeId, Operation.READ); + } catch (Exception e) { + throw handleException(e); + } + } + @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge", method = RequestMethod.POST) @ResponseBody diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java index f112690950..fd72abc2e2 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/edge/EdgeService.java @@ -36,6 +36,8 @@ public interface EdgeService { Edge findEdgeById(TenantId tenantId, EdgeId edgeId); + EdgeInfo findEdgeInfoById(TenantId tenantId, EdgeId edgeId); + ListenableFuture findEdgeByIdAsync(TenantId tenantId, EdgeId edgeId); Edge findEdgeByTenantIdAndName(TenantId tenantId, String name); diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeDao.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeDao.java index ecd13d9e80..fdaa6bf930 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeDao.java @@ -42,6 +42,15 @@ public interface EdgeDao extends Dao { */ Edge save(TenantId tenantId, Edge edge); + /** + * Find edge info by id. + * + * @param tenantId the tenant id + * @param edgeId the edge id + * @return the edge info object + */ + EdgeInfo findEdgeInfoById(TenantId tenantId, UUID edgeId); + /** * Find edges by tenantId and page link. * diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 7dc6a57316..5f4881f0aa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -143,6 +143,13 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic return edgeDao.findById(tenantId, edgeId.getId()); } + @Override + public EdgeInfo findEdgeInfoById(TenantId tenantId, EdgeId edgeId) { + log.trace("Executing findEdgeInfoById [{}]", edgeId); + validateId(edgeId, INCORRECT_EDGE_ID + edgeId); + return edgeDao.findEdgeInfoById(tenantId, edgeId.getId()); + } + @Override public ListenableFuture findEdgeByIdAsync(TenantId tenantId, EdgeId edgeId) { log.trace("Executing findEdgeById [{}]", edgeId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeRepository.java index f194156d8f..c3a48bc304 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/EdgeRepository.java @@ -36,6 +36,12 @@ public interface EdgeRepository extends PagingAndSortingRepository findByTenantId(@Param("tenantId") UUID tenantId, diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java index 5bc076c7af..3633c97ccb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaEdgeDao.java @@ -67,6 +67,11 @@ public class JpaEdgeDao extends JpaAbstractSearchTextDao imple return edgeRepository; } + @Override + public EdgeInfo findEdgeInfoById(TenantId tenantId, UUID edgeId) { + return DaoUtil.getData(edgeRepository.findEdgeInfoById(edgeId)); + } + @Override public PageData findEdgesByTenantId(UUID tenantId, PageLink pageLink) { return DaoUtil.toPageData( diff --git a/ui-ngx/src/app/core/http/edge.service.ts b/ui-ngx/src/app/core/http/edge.service.ts index 775bdd83e9..f02d09147b 100644 --- a/ui-ngx/src/app/core/http/edge.service.ts +++ b/ui-ngx/src/app/core/http/edge.service.ts @@ -38,8 +38,12 @@ export class EdgeService { defaultHttpOptionsFromConfig(config)); } - public getEdge(edgeId: string, config?: RequestConfig): Observable { - return this.http.get(`/api/edge/${edgeId}`, defaultHttpOptionsFromConfig(config)); + public getEdge(edgeId: string, config?: RequestConfig): Observable { + return this.http.get(`/api/edge/${edgeId}`, defaultHttpOptionsFromConfig(config)); + } + + public getEdgeInfo(edgeId: string, config?: RequestConfig): Observable { + return this.http.get(`/api/edge/info/${edgeId}`, defaultHttpOptionsFromConfig(config)); } public saveEdge(edge: Edge, config?: RequestConfig): Observable { @@ -72,7 +76,7 @@ export class EdgeService { } public makeEdgePublic(edgeId: string, config?: RequestConfig): Observable { - return this.http.post(`/api/customer/public/edge/${edgeId}`, + return this.http.post(`/api/customer/public/edge/${edgeId}`, null, defaultHttpOptionsFromConfig(config)); } diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index 5c01902896..e4e5015577 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -324,9 +324,8 @@ export class RuleChainService { return this.http.get>(`/api/ruleChain/defaultEdgeRuleChains`, defaultHttpOptionsFromConfig(config)); } - public setEdgeRootRuleChain(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable { //TODO deaflynx EdgeInfo vs. Edge check usage - return this.http.post(`/api/edge/${edgeId}/${ruleChainId}/root`, - defaultHttpOptionsFromConfig(config)); + public setEdgeRootRuleChain(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable { + return this.http.post(`/api/edge/${edgeId}/${ruleChainId}/root`, defaultHttpOptionsFromConfig(config)); } } diff --git a/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts b/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts index 53c70ce0ee..e8a94a52a7 100644 --- a/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts +++ b/ui-ngx/src/app/modules/home/components/import-export/import-export.service.ts @@ -52,7 +52,13 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; import { ImportEntitiesResultInfo, ImportEntityData } from '@shared/models/entity.models'; import { RequestConfig } from '@core/http/http-utils'; -import { RuleChain, RuleChainImport, RuleChainMetaData } from '@shared/models/rule-chain.models'; +import { + RuleChain, + RuleChainImport, + RuleChainMetaData, + RuleChainType, + ruleChainType +} from '@shared/models/rule-chain.models'; import { RuleChainService } from '@core/http/rule-chain.service'; import * as JSZip from 'jszip'; import { FiltersInfo } from '@shared/models/query/query.models'; @@ -397,7 +403,7 @@ export class ImportExportService { ); } - public importRuleChain(): Observable { + public importRuleChain(expectedRuleChainType: RuleChainType): Observable { return this.openImportDialog('rulechain.import', 'rulechain.rulechain-file').pipe( mergeMap((ruleChainImport: RuleChainImport) => { if (!this.validateImportedRuleChain(ruleChainImport)) { @@ -405,6 +411,11 @@ export class ImportExportService { {message: this.translate.instant('rulechain.invalid-rulechain-file-error'), type: 'error'})); throw new Error('Invalid rule chain file'); + } else if (ruleChainImport.ruleChain.type !== expectedRuleChainType) { + this.store.dispatch(new ActionNotificationShow( + {message: this.translate.instant('rulechain.invalid-rulechain-type-error', { expectedRuleChainType: expectedRuleChainType }), + type: 'error'})); + throw new Error('Invalid rule chain type'); } else { return this.ruleChainService.resolveRuleChainMetadata(ruleChainImport.metadata).pipe( map((resolvedMetadata) => { @@ -458,6 +469,9 @@ export class ImportExportService { || isUndefined(ruleChainImport.ruleChain.name)) { return false; } + if (isUndefined(ruleChainImport.ruleChain.type)) { + ruleChainImport.ruleChain.type = ruleChainType.core; + } return true; } diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts index adca2e34b1..53ba2902d8 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts @@ -27,9 +27,9 @@ import { RuleChainsTableConfigResolver } from "@home/pages/rulechain/rulechains- import { DashboardPageComponent } from "@home/pages/dashboard/dashboard-page.component"; import { dashboardBreadcumbLabelFunction, DashboardResolver } from "@home/pages/dashboard/dashboard-routing.module"; import { BreadCrumbConfig } from "@shared/components/breadcrumb"; -import {RuleChainPageComponent} from "@home/pages/rulechain/rulechain-page.component"; -import {ConfirmOnExitGuard} from "@core/guards/confirm-on-exit.guard"; -import {ruleChainType} from "@shared/models/rule-chain.models"; +import { RuleChainPageComponent } from "@home/pages/rulechain/rulechain-page.component"; +import { ConfirmOnExitGuard } from "@core/guards/confirm-on-exit.guard"; +import { ruleChainType } from "@shared/models/rule-chain.models"; import { importRuleChainBreadcumbLabelFunction, ResolvedRuleChainMetaDataResolver, diff --git a/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts index ba2a69ac6f..9fe8c9b77e 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edges-table-config.resolver.ts @@ -86,13 +86,13 @@ export class EdgesTableConfigResolver implements Resolve this.translate.instant('edge.delete-edges-title', {count}); this.config.deleteEntitiesContent = () => this.translate.instant('edge.delete-edges-text'); - this.config.loadEntity = id => this.edgeService.getEdge(id.id); + this.config.loadEntity = id => this.edgeService.getEdgeInfo(id.id); this.config.saveEntity = edge => { return this.edgeService.saveEdge(edge).pipe( tap(() => { this.broadcast.broadcast('edgeSaved'); }), - mergeMap((savedEdge) => this.edgeService.getEdge(savedEdge.id.id) + mergeMap((savedEdge) => this.edgeService.getEdgeInfo(savedEdge.id.id) )); }; this.config.onEntityAction = action => this.onEdgeAction(action); diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts index fb15089e02..c37659fbc4 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts @@ -14,39 +14,40 @@ /// limitations under the License. /// -import { Injectable } from '@angular/core'; +import {Injectable} from '@angular/core'; -import {ActivatedRouteSnapshot, Resolve, Route, Router} from '@angular/router'; +import {ActivatedRouteSnapshot, Resolve, Router} from '@angular/router'; import { CellActionDescriptor, checkBoxCell, - DateEntityTableColumn, EntityColumn, + DateEntityTableColumn, + EntityColumn, EntityTableColumn, EntityTableConfig, - GroupActionDescriptor, HeaderActionDescriptor + GroupActionDescriptor, + HeaderActionDescriptor } from '@home/models/entity/entities-table-config.models'; -import { TranslateService } from '@ngx-translate/core'; -import { DatePipe } from '@angular/common'; -import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; -import { EntityAction } from '@home/models/entity/entity-component.models'; -import { RuleChain, ruleChainType } from '@shared/models/rule-chain.models'; -import { RuleChainService } from '@core/http/rule-chain.service'; -import { RuleChainComponent } from '@modules/home/pages/rulechain/rulechain.component'; -import { DialogService } from '@core/services/dialog.service'; -import { RuleChainTabsComponent } from '@home/pages/rulechain/rulechain-tabs.component'; -import { ImportExportService } from '@home/components/import-export/import-export.service'; -import { ItemBufferService } from '@core/services/item-buffer.service'; -import { EdgeService } from "@core/http/edge.service"; -import {map, mergeMap} from "rxjs/operators"; -import { forkJoin, Observable } from "rxjs"; +import {TranslateService} from '@ngx-translate/core'; +import {DatePipe} from '@angular/common'; +import {EntityType, entityTypeResources, entityTypeTranslations} from '@shared/models/entity-type.models'; +import {EntityAction} from '@home/models/entity/entity-component.models'; +import {RuleChain, ruleChainType} from '@shared/models/rule-chain.models'; +import {RuleChainService} from '@core/http/rule-chain.service'; +import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component'; +import {DialogService} from '@core/services/dialog.service'; +import {RuleChainTabsComponent} from '@home/pages/rulechain/rulechain-tabs.component'; +import {ImportExportService} from '@home/components/import-export/import-export.service'; +import {ItemBufferService} from '@core/services/item-buffer.service'; +import {EdgeService} from "@core/http/edge.service"; +import {forkJoin, Observable} from "rxjs"; import { AddEntitiesToEdgeDialogComponent, AddEntitiesToEdgeDialogData } from "@home/dialogs/add-entities-to-edge-dialog.component"; -import { MatDialog } from "@angular/material/dialog"; -import { isDefined, isUndefined } from "@core/utils"; -import { PageLink } from "@shared/models/page/page-link"; -import { Edge } from "@shared/models/edge.models"; +import {MatDialog} from "@angular/material/dialog"; +import {isUndefined} from "@core/utils"; +import {PageLink} from "@shared/models/page/page-link"; +import {Edge} from "@shared/models/edge.models"; @Injectable() export class RuleChainsTableConfigResolver implements Resolve> { @@ -267,7 +268,8 @@ export class RuleChainsTableConfigResolver implements Resolve { + const expectedRuleChainType = this.config.componentsData.ruleChainScope === 'tenant' ? ruleChainType.core : ruleChainType.edge; + this.importExport.importRuleChain(expectedRuleChainType).subscribe((ruleChainImport) => { if (ruleChainImport) { this.itembuffer.storeRuleChainImport(ruleChainImport); this.router.navigateByUrl(`${this.router.routerState.snapshot.url}/ruleChain/import`); @@ -488,17 +490,17 @@ export class RuleChainsTableConfigResolver implements Resolve