Commit 77ad519a1007f161d79454b49d52f0aad563c3c9
Committed by
GitHub
Merge pull request #67 from deaflynx/develop/3.3-edge
Develop/3.3 edge Fix rule chain type, customerIsPublic for edges. Added EdgeInfo
Showing
13 changed files
with
114 additions
and
40 deletions
... | ... | @@ -50,6 +50,7 @@ import org.thingsboard.server.common.data.asset.Asset; |
50 | 50 | import org.thingsboard.server.common.data.asset.AssetInfo; |
51 | 51 | import org.thingsboard.server.common.data.audit.ActionType; |
52 | 52 | import org.thingsboard.server.common.data.edge.Edge; |
53 | +import org.thingsboard.server.common.data.edge.EdgeInfo; | |
53 | 54 | import org.thingsboard.server.common.data.edge.EdgeEventActionType; |
54 | 55 | import org.thingsboard.server.common.data.edge.EdgeEventType; |
55 | 56 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
... | ... | @@ -643,6 +644,18 @@ public abstract class BaseController { |
643 | 644 | } |
644 | 645 | } |
645 | 646 | |
647 | + EdgeInfo checkEdgeInfoId(EdgeId edgeId, Operation operation) throws ThingsboardException { | |
648 | + try { | |
649 | + validateId(edgeId, "Incorrect edgeId " + edgeId); | |
650 | + EdgeInfo edge = edgeService.findEdgeInfoById(getCurrentUser().getTenantId(), edgeId); | |
651 | + checkNotNull(edge); | |
652 | + accessControlService.checkPermission(getCurrentUser(), Resource.EDGE, operation, edgeId, edge); | |
653 | + return edge; | |
654 | + } catch (Exception e) { | |
655 | + throw handleException(e, false); | |
656 | + } | |
657 | + } | |
658 | + | |
646 | 659 | DashboardInfo checkDashboardInfoId(DashboardId dashboardId, Operation operation) throws ThingsboardException { |
647 | 660 | try { |
648 | 661 | validateId(dashboardId, "Incorrect dashboardId " + dashboardId); | ... | ... |
... | ... | @@ -84,6 +84,19 @@ public class EdgeController extends BaseController { |
84 | 84 | } |
85 | 85 | } |
86 | 86 | |
87 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | |
88 | + @RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET) | |
89 | + @ResponseBody | |
90 | + public EdgeInfo getEdgeInfoById(@PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { | |
91 | + checkParameter(EDGE_ID, strEdgeId); | |
92 | + try { | |
93 | + EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); | |
94 | + return checkEdgeInfoId(edgeId, Operation.READ); | |
95 | + } catch (Exception e) { | |
96 | + throw handleException(e); | |
97 | + } | |
98 | + } | |
99 | + | |
87 | 100 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
88 | 101 | @RequestMapping(value = "/edge", method = RequestMethod.POST) |
89 | 102 | @ResponseBody | ... | ... |
... | ... | @@ -36,6 +36,8 @@ public interface EdgeService { |
36 | 36 | |
37 | 37 | Edge findEdgeById(TenantId tenantId, EdgeId edgeId); |
38 | 38 | |
39 | + EdgeInfo findEdgeInfoById(TenantId tenantId, EdgeId edgeId); | |
40 | + | |
39 | 41 | ListenableFuture<Edge> findEdgeByIdAsync(TenantId tenantId, EdgeId edgeId); |
40 | 42 | |
41 | 43 | Edge findEdgeByTenantIdAndName(TenantId tenantId, String name); | ... | ... |
... | ... | @@ -43,6 +43,15 @@ public interface EdgeDao extends Dao<Edge> { |
43 | 43 | Edge save(TenantId tenantId, Edge edge); |
44 | 44 | |
45 | 45 | /** |
46 | + * Find edge info by id. | |
47 | + * | |
48 | + * @param tenantId the tenant id | |
49 | + * @param edgeId the edge id | |
50 | + * @return the edge info object | |
51 | + */ | |
52 | + EdgeInfo findEdgeInfoById(TenantId tenantId, UUID edgeId); | |
53 | + | |
54 | + /** | |
46 | 55 | * Find edges by tenantId and page link. |
47 | 56 | * |
48 | 57 | * @param tenantId the tenantId | ... | ... |
... | ... | @@ -144,6 +144,13 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic |
144 | 144 | } |
145 | 145 | |
146 | 146 | @Override |
147 | + public EdgeInfo findEdgeInfoById(TenantId tenantId, EdgeId edgeId) { | |
148 | + log.trace("Executing findEdgeInfoById [{}]", edgeId); | |
149 | + validateId(edgeId, INCORRECT_EDGE_ID + edgeId); | |
150 | + return edgeDao.findEdgeInfoById(tenantId, edgeId.getId()); | |
151 | + } | |
152 | + | |
153 | + @Override | |
147 | 154 | public ListenableFuture<Edge> findEdgeByIdAsync(TenantId tenantId, EdgeId edgeId) { |
148 | 155 | log.trace("Executing findEdgeById [{}]", edgeId); |
149 | 156 | validateId(edgeId, INCORRECT_EDGE_ID + edgeId); | ... | ... |
... | ... | @@ -36,6 +36,12 @@ public interface EdgeRepository extends PagingAndSortingRepository<EdgeEntity, U |
36 | 36 | @Param("textSearch") String textSearch, |
37 | 37 | Pageable pageable); |
38 | 38 | |
39 | + @Query("SELECT new org.thingsboard.server.dao.model.sql.EdgeInfoEntity(d, c.title, c.additionalInfo) " + | |
40 | + "FROM EdgeEntity d " + | |
41 | + "LEFT JOIN CustomerEntity c on c.id = d.customerId " + | |
42 | + "WHERE d.id = :edgeId") | |
43 | + EdgeInfoEntity findEdgeInfoById(@Param("edgeId") UUID edgeId); | |
44 | + | |
39 | 45 | @Query("SELECT d FROM EdgeEntity d WHERE d.tenantId = :tenantId " + |
40 | 46 | "AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))") |
41 | 47 | Page<EdgeEntity> findByTenantId(@Param("tenantId") UUID tenantId, | ... | ... |
... | ... | @@ -68,6 +68,11 @@ public class JpaEdgeDao extends JpaAbstractSearchTextDao<EdgeEntity, Edge> imple |
68 | 68 | } |
69 | 69 | |
70 | 70 | @Override |
71 | + public EdgeInfo findEdgeInfoById(TenantId tenantId, UUID edgeId) { | |
72 | + return DaoUtil.getData(edgeRepository.findEdgeInfoById(edgeId)); | |
73 | + } | |
74 | + | |
75 | + @Override | |
71 | 76 | public PageData<Edge> findEdgesByTenantId(UUID tenantId, PageLink pageLink) { |
72 | 77 | return DaoUtil.toPageData( |
73 | 78 | edgeRepository.findByTenantId( | ... | ... |
... | ... | @@ -38,8 +38,12 @@ export class EdgeService { |
38 | 38 | defaultHttpOptionsFromConfig(config)); |
39 | 39 | } |
40 | 40 | |
41 | - public getEdge(edgeId: string, config?: RequestConfig): Observable<EdgeInfo> { | |
42 | - return this.http.get<EdgeInfo>(`/api/edge/${edgeId}`, defaultHttpOptionsFromConfig(config)); | |
41 | + public getEdge(edgeId: string, config?: RequestConfig): Observable<Edge> { | |
42 | + return this.http.get<Edge>(`/api/edge/${edgeId}`, defaultHttpOptionsFromConfig(config)); | |
43 | + } | |
44 | + | |
45 | + public getEdgeInfo(edgeId: string, config?: RequestConfig): Observable<EdgeInfo> { | |
46 | + return this.http.get<EdgeInfo>(`/api/edge/info/${edgeId}`, defaultHttpOptionsFromConfig(config)); | |
43 | 47 | } |
44 | 48 | |
45 | 49 | public saveEdge(edge: Edge, config?: RequestConfig): Observable<Edge> { |
... | ... | @@ -72,7 +76,7 @@ export class EdgeService { |
72 | 76 | } |
73 | 77 | |
74 | 78 | public makeEdgePublic(edgeId: string, config?: RequestConfig): Observable<Edge> { |
75 | - return this.http.post<Edge>(`/api/customer/public/edge/${edgeId}`, | |
79 | + return this.http.post<Edge>(`/api/customer/public/edge/${edgeId}`, null, | |
76 | 80 | defaultHttpOptionsFromConfig(config)); |
77 | 81 | } |
78 | 82 | ... | ... |
... | ... | @@ -324,9 +324,8 @@ export class RuleChainService { |
324 | 324 | return this.http.get<Array<RuleChain>>(`/api/ruleChain/defaultEdgeRuleChains`, defaultHttpOptionsFromConfig(config)); |
325 | 325 | } |
326 | 326 | |
327 | - public setEdgeRootRuleChain(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable<Edge> { //TODO deaflynx EdgeInfo vs. Edge check usage | |
328 | - return this.http.post<Edge>(`/api/edge/${edgeId}/${ruleChainId}/root`, | |
329 | - defaultHttpOptionsFromConfig(config)); | |
327 | + public setEdgeRootRuleChain(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable<Edge> { | |
328 | + return this.http.post<Edge>(`/api/edge/${edgeId}/${ruleChainId}/root`, defaultHttpOptionsFromConfig(config)); | |
330 | 329 | } |
331 | 330 | |
332 | 331 | } | ... | ... |
... | ... | @@ -52,7 +52,13 @@ import { NULL_UUID } from '@shared/models/id/has-uuid'; |
52 | 52 | import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; |
53 | 53 | import { ImportEntitiesResultInfo, ImportEntityData } from '@shared/models/entity.models'; |
54 | 54 | import { RequestConfig } from '@core/http/http-utils'; |
55 | -import { RuleChain, RuleChainImport, RuleChainMetaData } from '@shared/models/rule-chain.models'; | |
55 | +import { | |
56 | + RuleChain, | |
57 | + RuleChainImport, | |
58 | + RuleChainMetaData, | |
59 | + RuleChainType, | |
60 | + ruleChainType | |
61 | +} from '@shared/models/rule-chain.models'; | |
56 | 62 | import { RuleChainService } from '@core/http/rule-chain.service'; |
57 | 63 | import * as JSZip from 'jszip'; |
58 | 64 | import { FiltersInfo } from '@shared/models/query/query.models'; |
... | ... | @@ -397,7 +403,7 @@ export class ImportExportService { |
397 | 403 | ); |
398 | 404 | } |
399 | 405 | |
400 | - public importRuleChain(): Observable<RuleChainImport> { | |
406 | + public importRuleChain(expectedRuleChainType: RuleChainType): Observable<RuleChainImport> { | |
401 | 407 | return this.openImportDialog('rulechain.import', 'rulechain.rulechain-file').pipe( |
402 | 408 | mergeMap((ruleChainImport: RuleChainImport) => { |
403 | 409 | if (!this.validateImportedRuleChain(ruleChainImport)) { |
... | ... | @@ -405,6 +411,11 @@ export class ImportExportService { |
405 | 411 | {message: this.translate.instant('rulechain.invalid-rulechain-file-error'), |
406 | 412 | type: 'error'})); |
407 | 413 | throw new Error('Invalid rule chain file'); |
414 | + } else if (ruleChainImport.ruleChain.type !== expectedRuleChainType) { | |
415 | + this.store.dispatch(new ActionNotificationShow( | |
416 | + {message: this.translate.instant('rulechain.invalid-rulechain-type-error', { expectedRuleChainType: expectedRuleChainType }), | |
417 | + type: 'error'})); | |
418 | + throw new Error('Invalid rule chain type'); | |
408 | 419 | } else { |
409 | 420 | return this.ruleChainService.resolveRuleChainMetadata(ruleChainImport.metadata).pipe( |
410 | 421 | map((resolvedMetadata) => { |
... | ... | @@ -458,6 +469,9 @@ export class ImportExportService { |
458 | 469 | || isUndefined(ruleChainImport.ruleChain.name)) { |
459 | 470 | return false; |
460 | 471 | } |
472 | + if (isUndefined(ruleChainImport.ruleChain.type)) { | |
473 | + ruleChainImport.ruleChain.type = ruleChainType.core; | |
474 | + } | |
461 | 475 | return true; |
462 | 476 | } |
463 | 477 | ... | ... |
... | ... | @@ -27,9 +27,9 @@ import { RuleChainsTableConfigResolver } from "@home/pages/rulechain/rulechains- |
27 | 27 | import { DashboardPageComponent } from "@home/pages/dashboard/dashboard-page.component"; |
28 | 28 | import { dashboardBreadcumbLabelFunction, DashboardResolver } from "@home/pages/dashboard/dashboard-routing.module"; |
29 | 29 | import { BreadCrumbConfig } from "@shared/components/breadcrumb"; |
30 | -import {RuleChainPageComponent} from "@home/pages/rulechain/rulechain-page.component"; | |
31 | -import {ConfirmOnExitGuard} from "@core/guards/confirm-on-exit.guard"; | |
32 | -import {ruleChainType} from "@shared/models/rule-chain.models"; | |
30 | +import { RuleChainPageComponent } from "@home/pages/rulechain/rulechain-page.component"; | |
31 | +import { ConfirmOnExitGuard } from "@core/guards/confirm-on-exit.guard"; | |
32 | +import { ruleChainType } from "@shared/models/rule-chain.models"; | |
33 | 33 | import { |
34 | 34 | importRuleChainBreadcumbLabelFunction, |
35 | 35 | ResolvedRuleChainMetaDataResolver, | ... | ... |
... | ... | @@ -86,13 +86,13 @@ export class EdgesTableConfigResolver implements Resolve<EntityTableConfig<EdgeI |
86 | 86 | this.config.deleteEntitiesTitle = count => this.translate.instant('edge.delete-edges-title', {count}); |
87 | 87 | this.config.deleteEntitiesContent = () => this.translate.instant('edge.delete-edges-text'); |
88 | 88 | |
89 | - this.config.loadEntity = id => this.edgeService.getEdge(id.id); | |
89 | + this.config.loadEntity = id => this.edgeService.getEdgeInfo(id.id); | |
90 | 90 | this.config.saveEntity = edge => { |
91 | 91 | return this.edgeService.saveEdge(edge).pipe( |
92 | 92 | tap(() => { |
93 | 93 | this.broadcast.broadcast('edgeSaved'); |
94 | 94 | }), |
95 | - mergeMap((savedEdge) => this.edgeService.getEdge(savedEdge.id.id) | |
95 | + mergeMap((savedEdge) => this.edgeService.getEdgeInfo(savedEdge.id.id) | |
96 | 96 | )); |
97 | 97 | }; |
98 | 98 | this.config.onEntityAction = action => this.onEdgeAction(action); | ... | ... |
... | ... | @@ -14,39 +14,40 @@ |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import { Injectable } from '@angular/core'; | |
17 | +import {Injectable} from '@angular/core'; | |
18 | 18 | |
19 | -import {ActivatedRouteSnapshot, Resolve, Route, Router} from '@angular/router'; | |
19 | +import {ActivatedRouteSnapshot, Resolve, Router} from '@angular/router'; | |
20 | 20 | import { |
21 | 21 | CellActionDescriptor, |
22 | 22 | checkBoxCell, |
23 | - DateEntityTableColumn, EntityColumn, | |
23 | + DateEntityTableColumn, | |
24 | + EntityColumn, | |
24 | 25 | EntityTableColumn, |
25 | 26 | EntityTableConfig, |
26 | - GroupActionDescriptor, HeaderActionDescriptor | |
27 | + GroupActionDescriptor, | |
28 | + HeaderActionDescriptor | |
27 | 29 | } from '@home/models/entity/entities-table-config.models'; |
28 | -import { TranslateService } from '@ngx-translate/core'; | |
29 | -import { DatePipe } from '@angular/common'; | |
30 | -import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; | |
31 | -import { EntityAction } from '@home/models/entity/entity-component.models'; | |
32 | -import { RuleChain, ruleChainType } from '@shared/models/rule-chain.models'; | |
33 | -import { RuleChainService } from '@core/http/rule-chain.service'; | |
34 | -import { RuleChainComponent } from '@modules/home/pages/rulechain/rulechain.component'; | |
35 | -import { DialogService } from '@core/services/dialog.service'; | |
36 | -import { RuleChainTabsComponent } from '@home/pages/rulechain/rulechain-tabs.component'; | |
37 | -import { ImportExportService } from '@home/components/import-export/import-export.service'; | |
38 | -import { ItemBufferService } from '@core/services/item-buffer.service'; | |
39 | -import { EdgeService } from "@core/http/edge.service"; | |
40 | -import {map, mergeMap} from "rxjs/operators"; | |
41 | -import { forkJoin, Observable } from "rxjs"; | |
30 | +import {TranslateService} from '@ngx-translate/core'; | |
31 | +import {DatePipe} from '@angular/common'; | |
32 | +import {EntityType, entityTypeResources, entityTypeTranslations} from '@shared/models/entity-type.models'; | |
33 | +import {EntityAction} from '@home/models/entity/entity-component.models'; | |
34 | +import {RuleChain, ruleChainType} from '@shared/models/rule-chain.models'; | |
35 | +import {RuleChainService} from '@core/http/rule-chain.service'; | |
36 | +import {RuleChainComponent} from '@modules/home/pages/rulechain/rulechain.component'; | |
37 | +import {DialogService} from '@core/services/dialog.service'; | |
38 | +import {RuleChainTabsComponent} from '@home/pages/rulechain/rulechain-tabs.component'; | |
39 | +import {ImportExportService} from '@home/components/import-export/import-export.service'; | |
40 | +import {ItemBufferService} from '@core/services/item-buffer.service'; | |
41 | +import {EdgeService} from "@core/http/edge.service"; | |
42 | +import {forkJoin, Observable} from "rxjs"; | |
42 | 43 | import { |
43 | 44 | AddEntitiesToEdgeDialogComponent, |
44 | 45 | AddEntitiesToEdgeDialogData |
45 | 46 | } from "@home/dialogs/add-entities-to-edge-dialog.component"; |
46 | -import { MatDialog } from "@angular/material/dialog"; | |
47 | -import { isDefined, isUndefined } from "@core/utils"; | |
48 | -import { PageLink } from "@shared/models/page/page-link"; | |
49 | -import { Edge } from "@shared/models/edge.models"; | |
47 | +import {MatDialog} from "@angular/material/dialog"; | |
48 | +import {isUndefined} from "@core/utils"; | |
49 | +import {PageLink} from "@shared/models/page/page-link"; | |
50 | +import {Edge} from "@shared/models/edge.models"; | |
50 | 51 | |
51 | 52 | @Injectable() |
52 | 53 | export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<RuleChain>> { |
... | ... | @@ -267,7 +268,8 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig< |
267 | 268 | if ($event) { |
268 | 269 | $event.stopPropagation(); |
269 | 270 | } |
270 | - this.importExport.importRuleChain().subscribe((ruleChainImport) => { | |
271 | + const expectedRuleChainType = this.config.componentsData.ruleChainScope === 'tenant' ? ruleChainType.core : ruleChainType.edge; | |
272 | + this.importExport.importRuleChain(expectedRuleChainType).subscribe((ruleChainImport) => { | |
271 | 273 | if (ruleChainImport) { |
272 | 274 | this.itembuffer.storeRuleChainImport(ruleChainImport); |
273 | 275 | this.router.navigateByUrl(`${this.router.routerState.snapshot.url}/ruleChain/import`); |
... | ... | @@ -488,17 +490,17 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig< |
488 | 490 | |
489 | 491 | isNonRootRuleChain(ruleChain: RuleChain) { |
490 | 492 | if (this.config.componentsData.ruleChainScope === 'edge') { |
491 | - return (isDefined(this.config.componentsData.edge.rootRuleChainId) && this.config.componentsData.edge.rootRuleChainId != null && this.config.componentsData.edge.rootRuleChainId.id != ruleChain.id.id); | |
493 | + return this.config.componentsData.edge.rootRuleChainId && true && this.config.componentsData.edge.rootRuleChainId.id != ruleChain.id.id; | |
492 | 494 | } |
493 | - return (isDefined(ruleChain)) && !ruleChain.root; | |
495 | + return !ruleChain.root; | |
494 | 496 | } |
495 | 497 | |
496 | 498 | isDefaultEdgeRuleChain(ruleChain) { |
497 | - return (isDefined(ruleChain)) && !ruleChain.root && this.config.componentsData.defaultEdgeRuleChainIds.includes(ruleChain.id.id); | |
499 | + return !ruleChain.root && this.config.componentsData.defaultEdgeRuleChainIds.includes(ruleChain.id.id); | |
498 | 500 | } |
499 | 501 | |
500 | 502 | isNonDefaultEdgeRuleChain(ruleChain) { |
501 | - return (isDefined(ruleChain)) && !ruleChain.root && !this.config.componentsData.defaultEdgeRuleChainIds.includes(ruleChain.id.id); | |
503 | + return !ruleChain.root && !this.config.componentsData.defaultEdgeRuleChainIds.includes(ruleChain.id.id); | |
502 | 504 | } |
503 | 505 | |
504 | 506 | fetchRuleChains(pageLink: PageLink) { | ... | ... |