Commit f1fb0cedae51eb129e24b69a8b2ad44e2b57e463

Authored by Viacheslav Kukhtyn
1 parent 9c44920f

Add audit log details for telemetry deleted and telemetry updated types

@@ -716,6 +716,9 @@ public abstract class BaseController { @@ -716,6 +716,9 @@ public abstract class BaseController {
716 case TIMESERIES_UPDATED: 716 case TIMESERIES_UPDATED:
717 msgType = DataConstants.TIMESERIES_UPDATED; 717 msgType = DataConstants.TIMESERIES_UPDATED;
718 break; 718 break;
  719 + case TIMESERIES_DELETED:
  720 + msgType = DataConstants.TIMESERIES_DELETED;
  721 + break;
719 } 722 }
720 if (!StringUtils.isEmpty(msgType)) { 723 if (!StringUtils.isEmpty(msgType)) {
721 try { 724 try {
@@ -774,6 +777,14 @@ public abstract class BaseController { @@ -774,6 +777,14 @@ public abstract class BaseController {
774 } else if (actionType == ActionType.TIMESERIES_UPDATED) { 777 } else if (actionType == ActionType.TIMESERIES_UPDATED) {
775 List<TsKvEntry> timeseries = extractParameter(List.class, 0, additionalInfo); 778 List<TsKvEntry> timeseries = extractParameter(List.class, 0, additionalInfo);
776 addTimeseries(entityNode, timeseries); 779 addTimeseries(entityNode, timeseries);
  780 + } else if (actionType == ActionType.TIMESERIES_DELETED) {
  781 + List<String> keys = extractParameter(List.class, 0, additionalInfo);
  782 + if (keys != null) {
  783 + ArrayNode timeseriesArrayNode = entityNode.putArray("timeseries");
  784 + keys.forEach(timeseriesArrayNode::add);
  785 + }
  786 + entityNode.put("startTs", extractParameter(Long.class, 1, additionalInfo));
  787 + entityNode.put("endTs", extractParameter(Long.class, 2, additionalInfo));
777 } 788 }
778 } 789 }
779 TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode)); 790 TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode));
@@ -298,7 +298,6 @@ public class TelemetryController extends BaseController { @@ -298,7 +298,6 @@ public class TelemetryController extends BaseController {
298 deleteToTs = System.currentTimeMillis(); 298 deleteToTs = System.currentTimeMillis();
299 } else { 299 } else {
300 if (startTs == null || endTs == null) { 300 if (startTs == null || endTs == null) {
301 - deleteToTs = endTs;  
302 return getImmediateDeferredResult("When deleteAllDataForKeys is false, start and end timestamp values shouldn't be empty", HttpStatus.BAD_REQUEST); 301 return getImmediateDeferredResult("When deleteAllDataForKeys is false, start and end timestamp values shouldn't be empty", HttpStatus.BAD_REQUEST);
303 } else { 302 } else {
304 deleteFromTs = startTs; 303 deleteFromTs = startTs;
@@ -316,13 +315,13 @@ public class TelemetryController extends BaseController { @@ -316,13 +315,13 @@ public class TelemetryController extends BaseController {
316 Futures.addCallback(future, new FutureCallback<List<Void>>() { 315 Futures.addCallback(future, new FutureCallback<List<Void>>() {
317 @Override 316 @Override
318 public void onSuccess(@Nullable List<Void> tmp) { 317 public void onSuccess(@Nullable List<Void> tmp) {
319 - logTimeseriesDeleted(user, entityId, keys, null); 318 + logTimeseriesDeleted(user, entityId, keys, deleteFromTs, deleteToTs, null);
320 result.setResult(new ResponseEntity<>(HttpStatus.OK)); 319 result.setResult(new ResponseEntity<>(HttpStatus.OK));
321 } 320 }
322 321
323 @Override 322 @Override
324 public void onFailure(Throwable t) { 323 public void onFailure(Throwable t) {
325 - logTimeseriesDeleted(user, entityId, keys, t); 324 + logTimeseriesDeleted(user, entityId, keys, deleteFromTs, deleteToTs, t);
326 result.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); 325 result.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
327 } 326 }
328 }, executor); 327 }, executor);
@@ -443,6 +442,7 @@ public class TelemetryController extends BaseController { @@ -443,6 +442,7 @@ public class TelemetryController extends BaseController {
443 if (entries.isEmpty()) { 442 if (entries.isEmpty()) {
444 return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST); 443 return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST);
445 } 444 }
  445 + SecurityUser user = getCurrentUser();
446 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> { 446 return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> {
447 long tenantTtl = ttl; 447 long tenantTtl = ttl;
448 if (!TenantId.SYS_TENANT_ID.equals(tenantId) && tenantTtl == 0) { 448 if (!TenantId.SYS_TENANT_ID.equals(tenantId) && tenantTtl == 0) {
@@ -590,10 +590,10 @@ public class TelemetryController extends BaseController { @@ -590,10 +590,10 @@ public class TelemetryController extends BaseController {
590 }; 590 };
591 } 591 }
592 592
593 - private void logTimeseriesDeleted(SecurityUser user, EntityId entityId, List<String> keys, Throwable e) { 593 + private void logTimeseriesDeleted(SecurityUser user, EntityId entityId, List<String> keys, long startTs, long endTs, Throwable e) {
594 try { 594 try {
595 logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.TIMESERIES_DELETED, toException(e), 595 logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.TIMESERIES_DELETED, toException(e),
596 - keys); 596 + keys, startTs, endTs);
597 } catch (ThingsboardException te) { 597 } catch (ThingsboardException te) {
598 log.warn("Failed to log timeseries delete", te); 598 log.warn("Failed to log timeseries delete", te);
599 } 599 }
@@ -60,6 +60,7 @@ public class DataConstants { @@ -60,6 +60,7 @@ public class DataConstants {
60 public static final String ATTRIBUTES_UPDATED = "ATTRIBUTES_UPDATED"; 60 public static final String ATTRIBUTES_UPDATED = "ATTRIBUTES_UPDATED";
61 public static final String ATTRIBUTES_DELETED = "ATTRIBUTES_DELETED"; 61 public static final String ATTRIBUTES_DELETED = "ATTRIBUTES_DELETED";
62 public static final String TIMESERIES_UPDATED = "TIMESERIES_UPDATED"; 62 public static final String TIMESERIES_UPDATED = "TIMESERIES_UPDATED";
  63 + public static final String TIMESERIES_DELETED = "TIMESERIES_DELETED";
63 public static final String ALARM_ACK = "ALARM_ACK"; 64 public static final String ALARM_ACK = "ALARM_ACK";
64 public static final String ALARM_CLEAR = "ALARM_CLEAR"; 65 public static final String ALARM_CLEAR = "ALARM_CLEAR";
65 public static final String ENTITY_ASSIGNED_FROM_TENANT = "ENTITY_ASSIGNED_FROM_TENANT"; 66 public static final String ENTITY_ASSIGNED_FROM_TENANT = "ENTITY_ASSIGNED_FROM_TENANT";
@@ -24,8 +24,8 @@ public enum ActionType { @@ -24,8 +24,8 @@ public enum ActionType {
24 UPDATED(false), // log entity 24 UPDATED(false), // log entity
25 ATTRIBUTES_UPDATED(false), // log attributes/values 25 ATTRIBUTES_UPDATED(false), // log attributes/values
26 ATTRIBUTES_DELETED(false), // log attributes 26 ATTRIBUTES_DELETED(false), // log attributes
27 - TIMESERIES_DELETED(false), // log timeseries  
28 TIMESERIES_UPDATED(false), // log timeseries update 27 TIMESERIES_UPDATED(false), // log timeseries update
  28 + TIMESERIES_DELETED(false), // log timeseries
29 RPC_CALL(false), // log method and params 29 RPC_CALL(false), // log method and params
30 CREDENTIALS_UPDATED(false), // log new credentials 30 CREDENTIALS_UPDATED(false), // log new credentials
31 ASSIGNED_TO_CUSTOMER(false), // log customer name 31 ASSIGNED_TO_CUSTOMER(false), // log customer name
@@ -39,21 +39,23 @@ import org.thingsboard.server.common.data.id.EntityId; @@ -39,21 +39,23 @@ import org.thingsboard.server.common.data.id.EntityId;
39 import org.thingsboard.server.common.data.id.TenantId; 39 import org.thingsboard.server.common.data.id.TenantId;
40 import org.thingsboard.server.common.data.id.UserId; 40 import org.thingsboard.server.common.data.id.UserId;
41 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 41 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  42 +import org.thingsboard.server.common.data.kv.TsKvEntry;
42 import org.thingsboard.server.common.data.page.PageData; 43 import org.thingsboard.server.common.data.page.PageData;
43 import org.thingsboard.server.common.data.page.TimePageLink; 44 import org.thingsboard.server.common.data.page.TimePageLink;
44 import org.thingsboard.server.common.data.relation.EntityRelation; 45 import org.thingsboard.server.common.data.relation.EntityRelation;
45 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 46 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
46 import org.thingsboard.server.common.data.security.DeviceCredentials; 47 import org.thingsboard.server.common.data.security.DeviceCredentials;
47 import org.thingsboard.server.dao.audit.sink.AuditLogSink; 48 import org.thingsboard.server.dao.audit.sink.AuditLogSink;
  49 +import org.thingsboard.server.dao.device.provision.ProvisionRequest;
48 import org.thingsboard.server.dao.entity.EntityService; 50 import org.thingsboard.server.dao.entity.EntityService;
49 import org.thingsboard.server.dao.exception.DataValidationException; 51 import org.thingsboard.server.dao.exception.DataValidationException;
50 -import org.thingsboard.server.dao.device.provision.ProvisionRequest;  
51 import org.thingsboard.server.dao.service.DataValidator; 52 import org.thingsboard.server.dao.service.DataValidator;
52 53
53 import java.io.PrintWriter; 54 import java.io.PrintWriter;
54 import java.io.StringWriter; 55 import java.io.StringWriter;
55 import java.util.List; 56 import java.util.List;
56 import java.util.UUID; 57 import java.util.UUID;
  58 +import java.util.stream.Collectors;
57 59
58 import static org.thingsboard.server.dao.service.Validator.validateEntityId; 60 import static org.thingsboard.server.dao.service.Validator.validateEntityId;
59 import static org.thingsboard.server.dao.service.Validator.validateId; 61 import static org.thingsboard.server.dao.service.Validator.validateId;
@@ -265,6 +267,32 @@ public class AuditLogServiceImpl implements AuditLogService { @@ -265,6 +267,32 @@ public class AuditLogServiceImpl implements AuditLogService {
265 actionData.set("provisionRequest", objectMapper.valueToTree(request)); 267 actionData.set("provisionRequest", objectMapper.valueToTree(request));
266 } 268 }
267 break; 269 break;
  270 + case TIMESERIES_UPDATED:
  271 + actionData.put("entityId", entityId.toString());
  272 + List<TsKvEntry> updatedTimeseries = extractParameter(List.class, 0, additionalInfo);
  273 + if (updatedTimeseries != null) {
  274 + ArrayNode result = actionData.putArray("timeseries");
  275 + updatedTimeseries.stream()
  276 + .collect(Collectors.groupingBy(TsKvEntry::getTs))
  277 + .forEach((k, v) -> {
  278 + ObjectNode element = objectMapper.createObjectNode();
  279 + element.put("ts", k);
  280 + ObjectNode values = element.putObject("values");
  281 + v.forEach(kvEntry -> values.put(kvEntry.getKey(), kvEntry.getValueAsString()));
  282 + result.add(element);
  283 + });
  284 + }
  285 + break;
  286 + case TIMESERIES_DELETED:
  287 + actionData.put("entityId", entityId.toString());
  288 + List<String> timeseriesKeys = extractParameter(List.class, 0, additionalInfo);
  289 + if (timeseriesKeys != null) {
  290 + ArrayNode timeseriesArrayNode = actionData.putArray("timeseries");
  291 + timeseriesKeys.forEach(timeseriesArrayNode::add);
  292 + }
  293 + actionData.put("startTs", extractParameter(Long.class, 1, additionalInfo));
  294 + actionData.put("endTs", extractParameter(Long.class, 2, additionalInfo));
  295 + break;
268 } 296 }
269 return actionData; 297 return actionData;
270 } 298 }
@@ -35,7 +35,8 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; @@ -35,7 +35,8 @@ import org.thingsboard.server.common.msg.session.SessionMsgType;
35 configClazz = EmptyNodeConfiguration.class, 35 configClazz = EmptyNodeConfiguration.class,
36 relationTypes = {"Post attributes", "Post telemetry", "RPC Request from Device", "RPC Request to Device", "Activity Event", "Inactivity Event", 36 relationTypes = {"Post attributes", "Post telemetry", "RPC Request from Device", "RPC Request to Device", "Activity Event", "Inactivity Event",
37 "Connect Event", "Disconnect Event", "Entity Created", "Entity Updated", "Entity Deleted", "Entity Assigned", 37 "Connect Event", "Disconnect Event", "Entity Created", "Entity Updated", "Entity Deleted", "Entity Assigned",
38 - "Entity Unassigned", "Attributes Updated", "Attributes Deleted", "Alarm Acknowledged", "Alarm Cleared", "Other", "Entity Assigned From Tenant", "Entity Assigned To Tenant", "Timeseries Updated"}, 38 + "Entity Unassigned", "Attributes Updated", "Attributes Deleted", "Alarm Acknowledged", "Alarm Cleared", "Other", "Entity Assigned From Tenant", "Entity Assigned To Tenant",
  39 + "Timeseries Updated", "Timeseries Deleted"},
39 nodeDescription = "Route incoming messages by Message Type", 40 nodeDescription = "Route incoming messages by Message Type",
40 nodeDetails = "Sends messages with message types <b>\"Post attributes\", \"Post telemetry\", \"RPC Request\"</b> etc. via corresponding chain, otherwise <b>Other</b> chain is used.", 41 nodeDetails = "Sends messages with message types <b>\"Post attributes\", \"Post telemetry\", \"RPC Request\"</b> etc. via corresponding chain, otherwise <b>Other</b> chain is used.",
41 uiResources = {"static/rulenode/rulenode-core-config.js"}, 42 uiResources = {"static/rulenode/rulenode-core-config.js"},
@@ -91,7 +92,9 @@ public class TbMsgTypeSwitchNode implements TbNode { @@ -91,7 +92,9 @@ public class TbMsgTypeSwitchNode implements TbNode {
91 } else if (msg.getType().equals(DataConstants.ENTITY_ASSIGNED_TO_TENANT)) { 92 } else if (msg.getType().equals(DataConstants.ENTITY_ASSIGNED_TO_TENANT)) {
92 relationType = "Entity Assigned To Tenant"; 93 relationType = "Entity Assigned To Tenant";
93 } else if (msg.getType().equals(DataConstants.TIMESERIES_UPDATED)) { 94 } else if (msg.getType().equals(DataConstants.TIMESERIES_UPDATED)) {
94 - relationType = "Timeseries updated"; 95 + relationType = "Timeseries Updated";
  96 + } else if (msg.getType().equals(DataConstants.TIMESERIES_DELETED)) {
  97 + relationType = "Timeseries Deleted";
95 } else { 98 } else {
96 relationType = "Other"; 99 relationType = "Other";
97 } 100 }
@@ -53,7 +53,9 @@ export enum ActionType { @@ -53,7 +53,9 @@ export enum ActionType {
53 ASSIGNED_FROM_TENANT = 'ASSIGNED_FROM_TENANT', 53 ASSIGNED_FROM_TENANT = 'ASSIGNED_FROM_TENANT',
54 ASSIGNED_TO_TENANT = 'ASSIGNED_TO_TENANT', 54 ASSIGNED_TO_TENANT = 'ASSIGNED_TO_TENANT',
55 PROVISION_SUCCESS = 'PROVISION_SUCCESS', 55 PROVISION_SUCCESS = 'PROVISION_SUCCESS',
56 - PROVISION_FAILURE = 'PROVISION_FAILURE' 56 + PROVISION_FAILURE = 'PROVISION_FAILURE',
  57 + TIMESERIES_UPDATED = 'TIMESERIES_UPDATED',
  58 + TIMESERIES_DELETED = 'TIMESERIES_DELETED'
57 } 59 }
58 60
59 export enum ActionStatus { 61 export enum ActionStatus {
@@ -87,7 +89,9 @@ export const actionTypeTranslations = new Map<ActionType, string>( @@ -87,7 +89,9 @@ export const actionTypeTranslations = new Map<ActionType, string>(
87 [ActionType.ASSIGNED_FROM_TENANT, 'audit-log.type-assigned-from-tenant'], 89 [ActionType.ASSIGNED_FROM_TENANT, 'audit-log.type-assigned-from-tenant'],
88 [ActionType.ASSIGNED_TO_TENANT, 'audit-log.type-assigned-to-tenant'], 90 [ActionType.ASSIGNED_TO_TENANT, 'audit-log.type-assigned-to-tenant'],
89 [ActionType.PROVISION_SUCCESS, 'audit-log.type-provision-success'], 91 [ActionType.PROVISION_SUCCESS, 'audit-log.type-provision-success'],
90 - [ActionType.PROVISION_FAILURE, 'audit-log.type-provision-failure'] 92 + [ActionType.PROVISION_FAILURE, 'audit-log.type-provision-failure'],
  93 + [ActionType.TIMESERIES_UPDATED, 'audit-log.type-timeseries-updated'],
  94 + [ActionType.TIMESERIES_DELETED, 'audit-log.type-timeseries-deleted']
91 ] 95 ]
92 ); 96 );
93 97
@@ -527,7 +527,9 @@ @@ -527,7 +527,9 @@
527 "type-assigned-from-tenant": "Assigned from Tenant", 527 "type-assigned-from-tenant": "Assigned from Tenant",
528 "type-assigned-to-tenant": "Assigned to Tenant", 528 "type-assigned-to-tenant": "Assigned to Tenant",
529 "type-provision-success": "Device provisioned", 529 "type-provision-success": "Device provisioned",
530 - "type-provision-failure": "Device provisioning was failed" 530 + "type-provision-failure": "Device provisioning was failed",
  531 + "type-timeseries-updated": "Telemetry updated",
  532 + "type-timeseries-deleted": "Telemetry deleted"
531 }, 533 },
532 "confirm-on-exit": { 534 "confirm-on-exit": {
533 "message": "You have unsaved changes. Are you sure you want to leave this page?", 535 "message": "You have unsaved changes. Are you sure you want to leave this page?",