Commit f1fb0cedae51eb129e24b69a8b2ad44e2b57e463
1 parent
9c44920f
Add audit log details for telemetry deleted and telemetry updated types
Showing
8 changed files
with
61 additions
and
12 deletions
... | ... | @@ -716,6 +716,9 @@ public abstract class BaseController { |
716 | 716 | case TIMESERIES_UPDATED: |
717 | 717 | msgType = DataConstants.TIMESERIES_UPDATED; |
718 | 718 | break; |
719 | + case TIMESERIES_DELETED: | |
720 | + msgType = DataConstants.TIMESERIES_DELETED; | |
721 | + break; | |
719 | 722 | } |
720 | 723 | if (!StringUtils.isEmpty(msgType)) { |
721 | 724 | try { |
... | ... | @@ -774,6 +777,14 @@ public abstract class BaseController { |
774 | 777 | } else if (actionType == ActionType.TIMESERIES_UPDATED) { |
775 | 778 | List<TsKvEntry> timeseries = extractParameter(List.class, 0, additionalInfo); |
776 | 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 | 790 | TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode)); | ... | ... |
... | ... | @@ -298,7 +298,6 @@ public class TelemetryController extends BaseController { |
298 | 298 | deleteToTs = System.currentTimeMillis(); |
299 | 299 | } else { |
300 | 300 | if (startTs == null || endTs == null) { |
301 | - deleteToTs = endTs; | |
302 | 301 | return getImmediateDeferredResult("When deleteAllDataForKeys is false, start and end timestamp values shouldn't be empty", HttpStatus.BAD_REQUEST); |
303 | 302 | } else { |
304 | 303 | deleteFromTs = startTs; |
... | ... | @@ -316,13 +315,13 @@ public class TelemetryController extends BaseController { |
316 | 315 | Futures.addCallback(future, new FutureCallback<List<Void>>() { |
317 | 316 | @Override |
318 | 317 | public void onSuccess(@Nullable List<Void> tmp) { |
319 | - logTimeseriesDeleted(user, entityId, keys, null); | |
318 | + logTimeseriesDeleted(user, entityId, keys, deleteFromTs, deleteToTs, null); | |
320 | 319 | result.setResult(new ResponseEntity<>(HttpStatus.OK)); |
321 | 320 | } |
322 | 321 | |
323 | 322 | @Override |
324 | 323 | public void onFailure(Throwable t) { |
325 | - logTimeseriesDeleted(user, entityId, keys, t); | |
324 | + logTimeseriesDeleted(user, entityId, keys, deleteFromTs, deleteToTs, t); | |
326 | 325 | result.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR)); |
327 | 326 | } |
328 | 327 | }, executor); |
... | ... | @@ -443,6 +442,7 @@ public class TelemetryController extends BaseController { |
443 | 442 | if (entries.isEmpty()) { |
444 | 443 | return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST); |
445 | 444 | } |
445 | + SecurityUser user = getCurrentUser(); | |
446 | 446 | return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> { |
447 | 447 | long tenantTtl = ttl; |
448 | 448 | if (!TenantId.SYS_TENANT_ID.equals(tenantId) && tenantTtl == 0) { |
... | ... | @@ -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 | 594 | try { |
595 | 595 | logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.TIMESERIES_DELETED, toException(e), |
596 | - keys); | |
596 | + keys, startTs, endTs); | |
597 | 597 | } catch (ThingsboardException te) { |
598 | 598 | log.warn("Failed to log timeseries delete", te); |
599 | 599 | } | ... | ... |
... | ... | @@ -60,6 +60,7 @@ public class DataConstants { |
60 | 60 | public static final String ATTRIBUTES_UPDATED = "ATTRIBUTES_UPDATED"; |
61 | 61 | public static final String ATTRIBUTES_DELETED = "ATTRIBUTES_DELETED"; |
62 | 62 | public static final String TIMESERIES_UPDATED = "TIMESERIES_UPDATED"; |
63 | + public static final String TIMESERIES_DELETED = "TIMESERIES_DELETED"; | |
63 | 64 | public static final String ALARM_ACK = "ALARM_ACK"; |
64 | 65 | public static final String ALARM_CLEAR = "ALARM_CLEAR"; |
65 | 66 | public static final String ENTITY_ASSIGNED_FROM_TENANT = "ENTITY_ASSIGNED_FROM_TENANT"; | ... | ... |
... | ... | @@ -24,8 +24,8 @@ public enum ActionType { |
24 | 24 | UPDATED(false), // log entity |
25 | 25 | ATTRIBUTES_UPDATED(false), // log attributes/values |
26 | 26 | ATTRIBUTES_DELETED(false), // log attributes |
27 | - TIMESERIES_DELETED(false), // log timeseries | |
28 | 27 | TIMESERIES_UPDATED(false), // log timeseries update |
28 | + TIMESERIES_DELETED(false), // log timeseries | |
29 | 29 | RPC_CALL(false), // log method and params |
30 | 30 | CREDENTIALS_UPDATED(false), // log new credentials |
31 | 31 | ASSIGNED_TO_CUSTOMER(false), // log customer name | ... | ... |
... | ... | @@ -39,21 +39,23 @@ import org.thingsboard.server.common.data.id.EntityId; |
39 | 39 | import org.thingsboard.server.common.data.id.TenantId; |
40 | 40 | import org.thingsboard.server.common.data.id.UserId; |
41 | 41 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
42 | +import org.thingsboard.server.common.data.kv.TsKvEntry; | |
42 | 43 | import org.thingsboard.server.common.data.page.PageData; |
43 | 44 | import org.thingsboard.server.common.data.page.TimePageLink; |
44 | 45 | import org.thingsboard.server.common.data.relation.EntityRelation; |
45 | 46 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
46 | 47 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
47 | 48 | import org.thingsboard.server.dao.audit.sink.AuditLogSink; |
49 | +import org.thingsboard.server.dao.device.provision.ProvisionRequest; | |
48 | 50 | import org.thingsboard.server.dao.entity.EntityService; |
49 | 51 | import org.thingsboard.server.dao.exception.DataValidationException; |
50 | -import org.thingsboard.server.dao.device.provision.ProvisionRequest; | |
51 | 52 | import org.thingsboard.server.dao.service.DataValidator; |
52 | 53 | |
53 | 54 | import java.io.PrintWriter; |
54 | 55 | import java.io.StringWriter; |
55 | 56 | import java.util.List; |
56 | 57 | import java.util.UUID; |
58 | +import java.util.stream.Collectors; | |
57 | 59 | |
58 | 60 | import static org.thingsboard.server.dao.service.Validator.validateEntityId; |
59 | 61 | import static org.thingsboard.server.dao.service.Validator.validateId; |
... | ... | @@ -265,6 +267,32 @@ public class AuditLogServiceImpl implements AuditLogService { |
265 | 267 | actionData.set("provisionRequest", objectMapper.valueToTree(request)); |
266 | 268 | } |
267 | 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 | 297 | return actionData; |
270 | 298 | } | ... | ... |
... | ... | @@ -35,7 +35,8 @@ import org.thingsboard.server.common.msg.session.SessionMsgType; |
35 | 35 | configClazz = EmptyNodeConfiguration.class, |
36 | 36 | relationTypes = {"Post attributes", "Post telemetry", "RPC Request from Device", "RPC Request to Device", "Activity Event", "Inactivity Event", |
37 | 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 | 40 | nodeDescription = "Route incoming messages by Message Type", |
40 | 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 | 42 | uiResources = {"static/rulenode/rulenode-core-config.js"}, |
... | ... | @@ -91,7 +92,9 @@ public class TbMsgTypeSwitchNode implements TbNode { |
91 | 92 | } else if (msg.getType().equals(DataConstants.ENTITY_ASSIGNED_TO_TENANT)) { |
92 | 93 | relationType = "Entity Assigned To Tenant"; |
93 | 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 | 98 | } else { |
96 | 99 | relationType = "Other"; |
97 | 100 | } | ... | ... |
... | ... | @@ -53,7 +53,9 @@ export enum ActionType { |
53 | 53 | ASSIGNED_FROM_TENANT = 'ASSIGNED_FROM_TENANT', |
54 | 54 | ASSIGNED_TO_TENANT = 'ASSIGNED_TO_TENANT', |
55 | 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 | 61 | export enum ActionStatus { |
... | ... | @@ -87,7 +89,9 @@ export const actionTypeTranslations = new Map<ActionType, string>( |
87 | 89 | [ActionType.ASSIGNED_FROM_TENANT, 'audit-log.type-assigned-from-tenant'], |
88 | 90 | [ActionType.ASSIGNED_TO_TENANT, 'audit-log.type-assigned-to-tenant'], |
89 | 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 | 527 | "type-assigned-from-tenant": "Assigned from Tenant", |
528 | 528 | "type-assigned-to-tenant": "Assigned to Tenant", |
529 | 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 | 534 | "confirm-on-exit": { |
533 | 535 | "message": "You have unsaved changes. Are you sure you want to leave this page?", | ... | ... |