Added routing key and secret

This commit is contained in:
Volodymyr Babak 2019-10-28 12:13:01 +02:00
parent 4327f4d3a6
commit d3bda85a93
24 changed files with 552 additions and 8 deletions

View File

@ -88,6 +88,10 @@
<groupId>org.thingsboard.common</groupId>
<artifactId>queue</artifactId>
</dependency>
<dependency>
<groupId>org.thingsboard.common</groupId>
<artifactId>edge-api</artifactId>
</dependency>
<dependency>
<groupId>org.thingsboard</groupId>
<artifactId>dao</artifactId>

View File

@ -0,0 +1,104 @@
/**
* Copyright © 2016-2019 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.service.edge.rpc;
import com.google.common.io.Resources;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.edge.gen.EdgeProtos;
import org.thingsboard.server.common.edge.gen.EdgeRpcServiceGrpc;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.IOException;
@Service
@Slf4j
@ConditionalOnProperty(prefix = "edges.rpc", value = "enabled", havingValue = "true")
public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase {
@Value("${edges.rpc.port}")
private int rpcPort;
@Value("${edges.rpc.ssl.enabled}")
private boolean sslEnabled;
@Value("${edges.rpc.ssl.cert}")
private String certFileResource;
@Value("${edges.rpc.ssl.privateKey}")
private String privateKeyResource;
private Server server;
@PostConstruct
public void init() {
log.info("Initializing Edge RPC service!");
ServerBuilder builder = ServerBuilder.forPort(rpcPort).addService(this);
if (sslEnabled) {
try {
File certFile = new File(Resources.getResource(certFileResource).toURI());
File privateKeyFile = new File(Resources.getResource(privateKeyResource).toURI());
builder.useTransportSecurity(certFile, privateKeyFile);
} catch (Exception e) {
log.error("Unable to set up SSL context. Reason: " + e.getMessage(), e);
throw new RuntimeException("Unable to set up SSL context!", e);
}
}
server = builder.build();
log.info("Going to start Edge RPC server using port: {}", rpcPort);
try {
server.start();
} catch (IOException e) {
log.error("Failed to start Edge RPC server!", e);
throw new RuntimeException("Failed to start Edge RPC server!");
}
log.info("Edge RPC service initialized!");
}
@PreDestroy
public void destroy() {
if (server != null) {
server.shutdownNow();
}
}
@Override
public StreamObserver<EdgeProtos.UplinkMsg> sendUplink(StreamObserver<EdgeProtos.DownlinkMsg> responseObserver) {
log.info("sendUplink [{}]", responseObserver);
return new StreamObserver<EdgeProtos.UplinkMsg>() {
@Override
public void onNext(EdgeProtos.UplinkMsg uplinkMsg) {
log.info("onNext [{}]", uplinkMsg);
}
@Override
public void onError(Throwable throwable) {
log.info("onError", throwable);
}
@Override
public void onCompleted() {
log.info("onCompleted");
}
};
}
}

View File

@ -495,6 +495,17 @@ transport:
bind_port: "${COAP_BIND_PORT:5683}"
timeout: "${COAP_TIMEOUT:10000}"
# Edges parameters
edges:
rpc:
enabled: "${EDGES_RPC_ENABLED:true}"
port: "${EDGES_RPC_PORT:60061}"
ssl:
# Enable/disable SSL support
enabled: "${EDGES_RPC_SSL_ENABLED:false}"
cert: "${EDGES_RPC_SSL_CERT:certChainFile.pem}"
privateKey: "${EDGES_RPC_SSL_PRIVATE_KEY:privateKeyFile.pem}"
swagger:
api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}"
security_path_regex: "${SWAGGER_SECURITY_PATH_REGEX:/api.*}"

View File

@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import java.util.List;
import java.util.Optional;
public interface EdgeService {
@ -35,6 +36,8 @@ public interface EdgeService {
Edge findEdgeByTenantIdAndName(TenantId tenantId, String name);
Optional<Edge> findEdgeByRoutingKey(TenantId tenantId, String routingKey);
Edge saveEdge(Edge edge);
Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, CustomerId customerId);

View File

@ -44,6 +44,8 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
private String name;
private String type;
private String label;
private String routingKey;
private String secret;
private transient JsonNode configuration;
public Edge() {
@ -60,6 +62,8 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
this.customerId = edge.getCustomerId();
this.type = edge.getType();
this.name = edge.getName();
this.routingKey = edge.getRoutingKey();
this.secret = edge.getSecret();
this.configuration = edge.getConfiguration();
}

129
common/edge-api/pom.xml Normal file
View File

@ -0,0 +1,129 @@
<!--
Copyright © 2016-2019 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.thingsboard</groupId>
<version>2.4.1-SNAPSHOT</version>
<artifactId>common</artifactId>
</parent>
<groupId>org.thingsboard.common</groupId>
<artifactId>edge-api</artifactId>
<packaging>jar</packaging>
<name>Thingsboard Server Remote Edge wrapper</name>
<url>https://thingsboard.io</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<main.dir>${basedir}/../..</main.dir>
</properties>
<dependencies>
<dependency>
<groupId>org.thingsboard.common</groupId>
<artifactId>data</artifactId>
</dependency>
<dependency>
<groupId>org.thingsboard.common</groupId>
<artifactId>message</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<exclusions>
<exclusion>
<artifactId>netty-transport</artifactId>
<groupId>io.netty</groupId>
</exclusion>
<exclusion>
<artifactId>netty-common</artifactId>
<groupId>io.netty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>thingsboard-repo-deploy</id>
<name>ThingsBoard Repo Deployment</name>
<url>https://repo.thingsboard.io/artifactory/libs-release-public</url>
</repository>
</distributionManagement>
</project>

View File

@ -0,0 +1,84 @@
/**
* Copyright © 2016-2019 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.edge.rpc;
import com.google.common.io.Resources;
import io.grpc.ManagedChannel;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyChannelBuilder;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.edge.gen.EdgeProtos;
import org.thingsboard.server.common.edge.gen.EdgeRpcServiceGrpc;
import javax.net.ssl.SSLException;
import java.io.File;
import java.net.URISyntaxException;
@Service
@Slf4j
public class EdgeGrpcClient implements EdgeRpcClient {
@Value("${cloud.rpc.host}")
private String rpcHost;
@Value("${cloud.rpc.port}")
private int rpcPort;
@Value("${cloud.rpc.timeout}")
private int timeoutSecs;
@Value("${cloud.rpc.ssl.enabled}")
private boolean sslEnabled;
@Value("${cloud.rpc.ssl.cert}")
private String certResource;
private ManagedChannel channel;
private StreamObserver<EdgeProtos.UplinkMsg> inputStream;
@Override
public void connect() {
NettyChannelBuilder builder = NettyChannelBuilder.forAddress(rpcHost, rpcPort).usePlaintext();
if (sslEnabled) {
try {
builder.sslContext(GrpcSslContexts.forClient().trustManager(new File(Resources.getResource(certResource).toURI())).build());
} catch (URISyntaxException | SSLException e) {
log.error("Failed to initialize channel!", e);
throw new RuntimeException(e);
}
}
channel = builder.build();
EdgeRpcServiceGrpc.EdgeRpcServiceStub stub = EdgeRpcServiceGrpc.newStub(channel);
StreamObserver<EdgeProtos.DownlinkMsg> responseObserver = new StreamObserver<EdgeProtos.DownlinkMsg>() {
@Override
public void onNext(EdgeProtos.DownlinkMsg downlinkMsg) {
log.info("onNext [{}]", downlinkMsg);
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onCompleted() {
}
};
inputStream = stub.sendUplink(responseObserver);
inputStream.onNext(EdgeProtos.UplinkMsg.newBuilder().setMsgType(EdgeProtos.UplinkMsgType.DELETE_DEVICE_MESSAGE).build());
}
}

View File

@ -0,0 +1,21 @@
/**
* Copyright © 2016-2019 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.edge.rpc;
public interface EdgeRpcClient {
void connect();
}

View File

@ -0,0 +1,49 @@
/**
* Copyright © 2016-2019 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.
*/
syntax = "proto3";
option java_package = "org.thingsboard.server.common.edge.gen";
option java_outer_classname = "EdgeProtos";
package edge;
// Interface exported by the ThingsBoard PRC Edge.
service EdgeRpcService {
rpc sendUplink(stream UplinkMsg) returns (stream DownlinkMsg) {}
}
/**
* Data Structures;
*/
message UplinkMsg {
UplinkMsgType msgType = 1;
}
message DownlinkMsg {
DownlinkMsgType msgType = 1;
}
enum UplinkMsgType {
SAVE_DEVICE_MESSAGE = 0;
DELETE_DEVICE_MESSAGE = 1;
}
enum DownlinkMsgType {
SAVE_ENTITY_MESSAGE = 0;
DELETE_ENTITY_MESSAGE = 1;
}

View File

@ -40,6 +40,7 @@
<module>queue</module>
<module>transport</module>
<module>dao-api</module>
<module>edge-api</module>
</modules>
</project>

View File

@ -46,6 +46,7 @@ import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.tenant.TenantDao;
import javax.annotation.Nullable;
@ -111,6 +112,13 @@ public class BaseEdgeService extends AbstractEntityService implements EdgeServic
return edgeOpt.orElse(null);
}
@Override
public Optional<Edge> findEdgeByRoutingKey(TenantId tenantId, String routingKey) {
log.trace("Executing findEdgeByRoutingKey [{}]", routingKey);
Validator.validateString(routingKey, "Incorrect edge routingKey for search request.");
return edgeDao.findByRoutingKey(tenantId.getId(), routingKey);
}
@CacheEvict(cacheNames = EDGE_CACHE, key = "{#edge.tenantId, #edge.name}")
@Override
public Edge saveEdge(Edge edge) {

View File

@ -86,4 +86,9 @@ public class CassandraEdgeDao extends CassandraAbstractSearchTextDao<EdgeEntity,
public ListenableFuture<List<EntitySubtype>> findTenantEdgeTypesAsync(UUID tenantId) {
return null;
}
@Override
public Optional<Edge> findByRoutingKey(UUID tenantId, String routingKey) {
return Optional.empty();
}
}

View File

@ -116,5 +116,12 @@ public interface EdgeDao extends Dao<Edge> {
*/
ListenableFuture<List<EntitySubtype>> findTenantEdgeTypesAsync(UUID tenantId);
/**
* Find edge by routing Key.
*
* @param routingKey the edge routingKey
* @return the optional edge object
*/
Optional<Edge> findByRoutingKey(UUID tenantId, String routingKey);
}

View File

@ -361,7 +361,8 @@ public class ModelConstants {
public static final String EDGE_CONFIGURATION_PROPERTY = "configuration";
public static final String EDGE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
public static final String EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_tenant_and_search_text";
public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key";
public static final String EDGE_SECRET_PROPERTY = "secret";
/**

View File

@ -5,7 +5,7 @@
* 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
* 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,
@ -37,6 +37,8 @@ import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CONFIGURATION
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LABEL_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_SECRET_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
@ -70,6 +72,12 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
@Column(name = SEARCH_TEXT_PROPERTY)
private String searchText;
@Column(name = EDGE_ROUTING_KEY_PROPERTY)
private String routingKey;
@Column(name = EDGE_SECRET_PROPERTY)
private String secret;
@Column(name = EDGE_CONFIGURATION_PROPERTY, codec = JsonCodec.class)
private JsonNode configuration;
@ -90,6 +98,8 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
this.type = edge.getType();
this.name = edge.getName();
this.label = edge.getLabel();
this.routingKey = edge.getRoutingKey();
this.secret = edge.getSecret();
this.configuration = edge.getConfiguration();
this.additionalInfo = edge.getAdditionalInfo();
}
@ -112,6 +122,8 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
edge.setType(type);
edge.setName(name);
edge.setLabel(label);
edge.setRoutingKey(routingKey);
edge.setSecret(secret);
edge.setConfiguration(configuration);
edge.setAdditionalInfo(additionalInfo);
return edge;

View File

@ -5,7 +5,7 @@
* 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
* 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,
@ -35,11 +35,12 @@ import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import static org.thingsboard.server.dao.model.ModelConstants.ASSET_CUSTOMER_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LABEL_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_SECRET_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TYPE_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
@ -69,6 +70,12 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
@Column(name = SEARCH_TEXT_PROPERTY)
private String searchText;
@Column(name = EDGE_ROUTING_KEY_PROPERTY)
private String routingKey;
@Column(name = EDGE_SECRET_PROPERTY)
private String secret;
@Type(type = "json")
@Column(name = ModelConstants.EDGE_CONFIGURATION_PROPERTY)
private JsonNode configuration;
@ -94,6 +101,8 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
this.type = edge.getType();
this.name = edge.getName();
this.label = edge.getLabel();
this.routingKey = edge.getRoutingKey();
this.secret = edge.getSecret();
this.configuration = edge.getConfiguration();
this.additionalInfo = edge.getAdditionalInfo();
}
@ -125,6 +134,8 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
edge.setType(type);
edge.setName(name);
edge.setLabel(label);
edge.setRoutingKey(routingKey);
edge.setSecret(secret);
edge.setConfiguration(configuration);
edge.setAdditionalInfo(additionalInfo);
return edge;

View File

@ -76,4 +76,5 @@ public interface EdgeRepository extends CrudRepository<EdgeEntity, String> {
List<EdgeEntity> findEdgesByTenantIdAndIdIn(String tenantId, List<String> edgeIds);
EdgeEntity findByRoutingKey(String routingKey);
}

View File

@ -5,7 +5,7 @@
* 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
* 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,
@ -126,6 +126,12 @@ public class JpaEdgeDao extends JpaAbstractSearchTextDao<EdgeEntity, Edge> imple
return service.submit(() -> convertTenantEdgeTypesToDto(tenantId, edgeRepository.findTenantEdgeTypes(fromTimeUUID(tenantId))));
}
@Override
public Optional<Edge> findByRoutingKey(UUID tenantId, String routingKey) {
Edge edge = DaoUtil.getData(edgeRepository.findByRoutingKey(routingKey));
return Optional.ofNullable(edge);
}
private List<EntitySubtype> convertTenantEdgeTypesToDto(UUID tenantId, List<String> types) {
List<EntitySubtype> list = Collections.emptyList();
if (types != null && !types.isEmpty()) {

View File

@ -257,6 +257,8 @@ CREATE TABLE IF NOT EXISTS edge (
type varchar(255),
name varchar(255),
label varchar(255),
routing_key varchar(255),
secret varchar(255),
search_text varchar(255),
tenant_id varchar(31)
);

View File

@ -406,6 +406,11 @@
<artifactId>coap</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.thingsboard.common</groupId>
<artifactId>edge-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.thingsboard</groupId>
<artifactId>dao</artifactId>

View File

@ -27,7 +27,7 @@
<div layout="row">
<md-button ngclipboard data-clipboard-action="copy"
ngclipboard-success="onEdgeIdCopied(e)"
ngclipboard-success="onEdgeIdCopied()"
data-clipboard-text="{{edge.id.id}}" ng-show="!isEdit"
class="md-raised">
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
@ -69,4 +69,34 @@
<textarea ng-model="edge.additionalInfo.description" rows="2"></textarea>
</md-input-container>
</fieldset>
<div layout="row">
<md-input-container class="md-block" flex>
<label translate>edge.edge-key</label>
<input ng-model="edge.routingKey" disabled>
</md-input-container>
<md-button class="md-icon-button" style="margin-top: 14px;"
ngclipboard data-clipboard-action="copy"
ngclipboard-success="onEdgeInfoCopied('key')"
data-clipboard-text="{{edge.routingKey}}">
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
<md-tooltip md-direction="top">
{{ 'edge.copy-edge-key' | translate }}
</md-tooltip>
</md-button>
</div>
<div layout="row">
<md-input-container class="md-block" flex>
<label translate>edge.edge-secret</label>
<input ng-model="edge.secret" disabled>
</md-input-container>
<md-button class="md-icon-button" style="margin-top: 14px;"
ngclipboard data-clipboard-action="copy"
data-clipboard-text="{{edge.secret}}"
ngclipboard-success="onEdgeInfoCopied('secret')">
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
<md-tooltip md-direction="top">
{{ 'edge.copy-edge-secret' | translate }}
</md-tooltip>
</md-button>
</div>
</md-content>

View File

@ -20,7 +20,7 @@ import edgeFieldsetTemplate from './edge-fieldset.tpl.html';
/* eslint-enable import/no-unresolved, import/default */
/*@ngInject*/
export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, toast, types, customerService) {
export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, utils, toast, types, customerService) {
var linker = function (scope, element) {
var template = $templateCache.get(edgeFieldsetTemplate);
element.html(template);
@ -32,6 +32,10 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD
scope.$watch('edge', function(newVal) {
if (newVal) {
if (!scope.edge.id) {
scope.edge.routingKey = utils.guid('');
scope.edge.secret = generateSecret(20);
}
if (scope.edge.customerId && scope.edge.customerId.id !== types.id.nullUid) {
scope.isAssignedToCustomer = true;
customerService.getShortCustomerInfo(scope.edge.customerId.id).then(
@ -48,12 +52,38 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD
}
});
function generateSecret(length) {
if (angular.isUndefined(length) || length == null) {
length = 1;
}
var l = length > 10 ? 10 : length;
var str = Math.random().toString(36).substr(2, l);
if(str.length >= length){
return str;
}
return str.concat(generateSecret(length - str.length));
}
scope.onEdgeIdCopied = function() {
toast.showSuccess($translate.instant('edge.id-copied-message'), 750, angular.element(element).parent().parent(), 'bottom left');
};
$compile(element.contents())(scope);
scope.onEdgeInfoCopied = function(type) {
let translateInstant = "";
switch (type) {
case 'key':
translateInstant = "edge.edge-key-copied-message";
break;
case 'secret':
translateInstant = "edge.edge-secret-copied-message";
break;
}
toast.showSuccess($translate.instant(translateInstant), 750, angular.element(element).parent().parent(), 'top left');
};
};
return {
restrict: "E",

View File

@ -602,6 +602,16 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
}
);
return deferred.promise;
case types.entityType.edge:
openImportDialogCSV($event, entityType, 'edge.import', 'edge.edge-file').then(
function success() {
deferred.resolve();
},
function fail() {
deferred.reject();
}
);
return deferred.promise;
}
}

View File

@ -777,7 +777,13 @@
"unassign-from-edge": "Unassign from edge",
"dashboards": "Edge Dashboards",
"manage-edge-rulechains": "Manage edge rule chains",
"rulechains": "Edge Rule Chains"
"rulechains": "Edge Rule Chains",
"edge-key": "Edge key",
"copy-edge-key": "Copy edge key",
"edge-key-copied-message": "Edge key has been copied to clipboard",
"edge-secret": "Edge secret",
"copy-edge-secret": "Copy edge secret",
"edge-secret-copied-message": "Edge secret has been copied to clipboard"
},
"error": {
"unable-to-connect": "Unable to connect to the server! Please check your internet connection.",