Merge branch 'master' into develop/3.0

This commit is contained in:
Igor Kulikov 2020-04-01 09:48:16 +03:00
commit 7e8c90ec6d
9 changed files with 91 additions and 70 deletions

View File

@ -120,7 +120,9 @@ public class AlarmController extends BaseController {
try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
Alarm alarm = checkAlarmId(alarmId, Operation.WRITE);
alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, System.currentTimeMillis()).get();
long ackTs = System.currentTimeMillis();
alarmService.ackAlarm(getCurrentUser().getTenantId(), alarmId, ackTs).get();
alarm.setAckTs(ackTs);
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null);
} catch (Exception e) {
throw handleException(e);
@ -135,7 +137,9 @@ public class AlarmController extends BaseController {
try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
Alarm alarm = checkAlarmId(alarmId, Operation.WRITE);
alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, System.currentTimeMillis()).get();
long clearTs = System.currentTimeMillis();
alarmService.clearAlarm(getCurrentUser().getTenantId(), alarmId, null, clearTs).get();
alarm.setClearTs(clearTs);
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null);
} catch (Exception e) {
throw handleException(e);

View File

@ -24,13 +24,11 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.EntityRelationInfo;
import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
@ -38,6 +36,7 @@ import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.service.security.permission.Operation;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@ -167,7 +166,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByFrom(getTenantId(), entityId, typeGroup));
return checkNotNull(filterRelationsByReadPermission(relationService.findByFrom(getTenantId(), entityId, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
@ -185,7 +184,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findInfoByFrom(getTenantId(), entityId, typeGroup).get());
return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByFrom(getTenantId(), entityId, typeGroup).get()));
} catch (Exception e) {
throw handleException(e);
}
@ -205,7 +204,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByFromAndType(getTenantId(), entityId, strRelationType, typeGroup));
return checkNotNull(filterRelationsByReadPermission(relationService.findByFromAndType(getTenantId(), entityId, strRelationType, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
@ -223,7 +222,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByTo(getTenantId(), entityId, typeGroup));
return checkNotNull(filterRelationsByReadPermission(relationService.findByTo(getTenantId(), entityId, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
@ -241,7 +240,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findInfoByTo(getTenantId(), entityId, typeGroup).get());
return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByTo(getTenantId(), entityId, typeGroup).get()));
} catch (Exception e) {
throw handleException(e);
}
@ -261,7 +260,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId, Operation.READ);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByToAndType(getTenantId(), entityId, strRelationType, typeGroup));
return checkNotNull(filterRelationsByReadPermission(relationService.findByToAndType(getTenantId(), entityId, strRelationType, typeGroup)));
} catch (Exception e) {
throw handleException(e);
}
@ -276,7 +275,7 @@ public class EntityRelationController extends BaseController {
checkNotNull(query.getFilters());
checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try {
return checkNotNull(relationService.findByQuery(getTenantId(), query).get());
return checkNotNull(filterRelationsByReadPermission(relationService.findByQuery(getTenantId(), query).get()));
} catch (Exception e) {
throw handleException(e);
}
@ -291,12 +290,28 @@ public class EntityRelationController extends BaseController {
checkNotNull(query.getFilters());
checkEntityId(query.getParameters().getEntityId(), Operation.READ);
try {
return checkNotNull(relationService.findInfoByQuery(getTenantId(), query).get());
return checkNotNull(filterRelationsByReadPermission(relationService.findInfoByQuery(getTenantId(), query).get()));
} catch (Exception e) {
throw handleException(e);
}
}
private <T extends EntityRelation> List<T> filterRelationsByReadPermission(List<T> relationsByQuery) {
return relationsByQuery.stream().filter(relationByQuery -> {
try {
checkEntityId(relationByQuery.getTo(), Operation.READ);
} catch (ThingsboardException e) {
return false;
}
try {
checkEntityId(relationByQuery.getFrom(), Operation.READ);
} catch (ThingsboardException e) {
return false;
}
return true;
}).collect(Collectors.toList());
}
private RelationTypeGroup parseRelationTypeGroup(String strRelationTypeGroup, RelationTypeGroup defaultValue) {
RelationTypeGroup result = defaultValue;
if (strRelationTypeGroup != null && strRelationTypeGroup.trim().length() > 0) {

View File

@ -39,7 +39,7 @@ public interface AlarmService {
ListenableFuture<Boolean> ackAlarm(TenantId tenantId, AlarmId alarmId, long ackTs);
ListenableFuture<Boolean> clearAlarm(TenantId tenantId, AlarmId alarmId, JsonNode details, long ackTs);
ListenableFuture<Boolean> clearAlarm(TenantId tenantId, AlarmId alarmId, JsonNode details, long clearTs);
ListenableFuture<Alarm> findAlarmByIdAsync(TenantId tenantId, AlarmId alarmId);

View File

@ -407,8 +407,12 @@ final class MqttClientImpl implements MqttClient {
}
private MqttMessageIdVariableHeader getNewMessageId() {
this.nextMessageId.compareAndSet(0xffff, 1);
return MqttMessageIdVariableHeader.from(this.nextMessageId.getAndIncrement());
int messageId;
synchronized (this.nextMessageId) {
this.nextMessageId.compareAndSet(0xffff, 1);
messageId = this.nextMessageId.getAndIncrement();
}
return MqttMessageIdVariableHeader.from(messageId);
}
private Future<Void> createSubscription(String topic, MqttHandler handler, boolean once, MqttQoS qos) {

View File

@ -55,7 +55,7 @@ while :
echo "Done"
exit 0
;;
[yY]|[yY][eE]|[yY][eE]|[sS]|[yY]|"")
[yY]|[yY][eE]|[yY][eE][sS]|"")
echo "Cleaning up files"
rm -rf $CLIENT_FILE_PREFIX.jks
rm -rf $CLIENT_FILE_PREFIX.pub.pem

View File

@ -71,7 +71,7 @@ while :
echo "Done"
exit 0
;;
[yY]|[yY][eE]|[yY][eE]|[sS]|[yY]|"")
[yY]|[yY][eE]|[yY][eE][sS]|"")
echo "Cleaning up files"
rm -rf $SERVER_FILE_PREFIX.jks
rm -rf $SERVER_FILE_PREFIX.pub.pem
@ -129,7 +129,7 @@ if [[ $COPY = true ]]; then
[nN]|[nN][oO])
break
;;
[yY]|[yY][eE]|[yY][eE]|[sS]|[yY]|"")
[yY]|[yY][eE]|[yY][eE][sS]|"")
read -p "(Default: $SERVER_KEYSTORE_DIR): " dir
if [[ ! -z $dir ]]; then
DESTINATION=$dir;

View File

@ -616,7 +616,7 @@ export default class TbMapWidgetV2 {
locationChanged = true;
}
}
} else {
} else if (latData.length > 0 && lngData.length > 0) {
// Create or update marker
lat = latData[latData.length - 1][1];
lng = lngData[lngData.length - 1][1];

View File

@ -31,10 +31,6 @@ tb-timeseries-table-widget {
z-index: 10;
}
md-table-container {
overflow-x: visible;
}
md-tabs:not(.md-no-tab-content):not(.md-dynamic-height) {
min-height: 0;
}

View File

@ -38,56 +38,58 @@
</div>
</md-toolbar>
<md-tabs flex md-selected="vm.sourceIndex" ng-class="{'tb-headless': vm.sources.length === 1}"
<md-tabs md-selected="vm.sourceIndex" ng-class="{'tb-headless': vm.sources.length === 1}"
id="tabs" md-border-bottom flex>
<md-tab ng-repeat="source in vm.sources" label="{{ source.datasource.name }}">
<md-table-container class="flex">
<table md-table>
<thead fix-head md-head md-order="source.query.order" md-on-reorder="vm.onReorder(source)">
<tr md-row>
<th ng-show="vm.showTimestamp"
md-column md-order-by="0"
>
<span>Timestamp</span>
</th>
<th md-column
md-order-by="{{ h.index }}"
ng-repeat="h in source.ts.header"
>
<span>{{ h.dataKey.label }}</span>
</th>
</tr>
</thead>
<div class="tb-absolute-fill" layout="column">
<md-table-container flex>
<table md-table>
<thead fix-head md-head md-order="source.query.order" md-on-reorder="vm.onReorder(source)">
<tr md-row>
<th ng-show="vm.showTimestamp"
md-column md-order-by="0"
>
<span>Timestamp</span>
</th>
<th md-column
md-order-by="{{ h.index }}"
ng-repeat="h in source.ts.header"
>
<span>{{ h.dataKey.label }}</span>
</th>
</tr>
</thead>
<tbody md-body>
<tr md-row ng-repeat="row in source.ts.data track by $index" ng-click="vm.onRowClick($event, row)">
<td ng-show="$index > 0 || ($index === 0 && vm.showTimestamp)"
md-cell
ng-repeat="d in row track by $index"
ng-style="vm.cellStyle(source, $index, d)"
ng-bind-html="vm.cellContent(source, $index, row, d)"
></td>
<td md-cell class="tb-action-cell"
ng-style="{minWidth: vm.actionCellDescriptors.length*36+'px',
maxWidth: vm.actionCellDescriptors.length*36+'px',
width: vm.actionCellDescriptors.length*36+'px'}">
<md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors"
aria-label="{{ actionDescriptor.displayName }}"
ng-click="vm.onActionButtonClick($event, row, actionDescriptor)" ng-disabled="$root.loading">
<md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon>
<md-tooltip md-direction="top">
{{ actionDescriptor.displayName }}
</md-tooltip>
</md-button>
</td>
</tr>
</tbody>
</table>
<md-divider></md-divider>
<span ng-show="!vm.sources[vm.sourceIndex].data.length"
layout-align="center center"
class="no-data-found" translate>widget.no-data-found</span>
</md-table-container>
<tbody md-body>
<tr md-row ng-repeat="row in source.ts.data track by $index" ng-click="vm.onRowClick($event, row)">
<td ng-show="$index > 0 || ($index === 0 && vm.showTimestamp)"
md-cell
ng-repeat="d in row track by $index"
ng-style="vm.cellStyle(source, $index, d)"
ng-bind-html="vm.cellContent(source, $index, row, d)"
></td>
<td md-cell class="tb-action-cell"
ng-style="{minWidth: vm.actionCellDescriptors.length*36+'px',
maxWidth: vm.actionCellDescriptors.length*36+'px',
width: vm.actionCellDescriptors.length*36+'px'}">
<md-button class="md-icon-button" ng-repeat="actionDescriptor in vm.actionCellDescriptors"
aria-label="{{ actionDescriptor.displayName }}"
ng-click="vm.onActionButtonClick($event, row, actionDescriptor)" ng-disabled="$root.loading">
<md-icon aria-label="{{ actionDescriptor.displayName }}" class="material-icons">{{actionDescriptor.icon}}</md-icon>
<md-tooltip md-direction="top">
{{ actionDescriptor.displayName }}
</md-tooltip>
</md-button>
</td>
</tr>
</tbody>
</table>
<md-divider></md-divider>
<span ng-show="!vm.sources[vm.sourceIndex].data.length"
layout-align="center center"
class="no-data-found" translate>widget.no-data-found</span>
</md-table-container>
</div>
</md-tab>
</md-tabs>
<md-table-pagination ng-if="vm.displayPagination"