Add audit log details for telemetry deleted and telemetry updated types

This commit is contained in:
Viacheslav Kukhtyn 2020-12-25 18:24:31 +02:00
parent 9c44920fe7
commit f1fb0cedae
8 changed files with 61 additions and 12 deletions

View File

@ -716,6 +716,9 @@ public abstract class BaseController {
case TIMESERIES_UPDATED:
msgType = DataConstants.TIMESERIES_UPDATED;
break;
case TIMESERIES_DELETED:
msgType = DataConstants.TIMESERIES_DELETED;
break;
}
if (!StringUtils.isEmpty(msgType)) {
try {
@ -774,6 +777,14 @@ public abstract class BaseController {
} else if (actionType == ActionType.TIMESERIES_UPDATED) {
List<TsKvEntry> timeseries = extractParameter(List.class, 0, additionalInfo);
addTimeseries(entityNode, timeseries);
} else if (actionType == ActionType.TIMESERIES_DELETED) {
List<String> keys = extractParameter(List.class, 0, additionalInfo);
if (keys != null) {
ArrayNode timeseriesArrayNode = entityNode.putArray("timeseries");
keys.forEach(timeseriesArrayNode::add);
}
entityNode.put("startTs", extractParameter(Long.class, 1, additionalInfo));
entityNode.put("endTs", extractParameter(Long.class, 2, additionalInfo));
}
}
TbMsg tbMsg = TbMsg.newMsg(msgType, entityId, metaData, TbMsgDataType.JSON, json.writeValueAsString(entityNode));

View File

@ -298,7 +298,6 @@ public class TelemetryController extends BaseController {
deleteToTs = System.currentTimeMillis();
} else {
if (startTs == null || endTs == null) {
deleteToTs = endTs;
return getImmediateDeferredResult("When deleteAllDataForKeys is false, start and end timestamp values shouldn't be empty", HttpStatus.BAD_REQUEST);
} else {
deleteFromTs = startTs;
@ -316,13 +315,13 @@ public class TelemetryController extends BaseController {
Futures.addCallback(future, new FutureCallback<List<Void>>() {
@Override
public void onSuccess(@Nullable List<Void> tmp) {
logTimeseriesDeleted(user, entityId, keys, null);
logTimeseriesDeleted(user, entityId, keys, deleteFromTs, deleteToTs, null);
result.setResult(new ResponseEntity<>(HttpStatus.OK));
}
@Override
public void onFailure(Throwable t) {
logTimeseriesDeleted(user, entityId, keys, t);
logTimeseriesDeleted(user, entityId, keys, deleteFromTs, deleteToTs, t);
result.setResult(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
}
}, executor);
@ -443,6 +442,7 @@ public class TelemetryController extends BaseController {
if (entries.isEmpty()) {
return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST);
}
SecurityUser user = getCurrentUser();
return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> {
long tenantTtl = ttl;
if (!TenantId.SYS_TENANT_ID.equals(tenantId) && tenantTtl == 0) {
@ -590,10 +590,10 @@ public class TelemetryController extends BaseController {
};
}
private void logTimeseriesDeleted(SecurityUser user, EntityId entityId, List<String> keys, Throwable e) {
private void logTimeseriesDeleted(SecurityUser user, EntityId entityId, List<String> keys, long startTs, long endTs, Throwable e) {
try {
logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.TIMESERIES_DELETED, toException(e),
keys);
keys, startTs, endTs);
} catch (ThingsboardException te) {
log.warn("Failed to log timeseries delete", te);
}

View File

@ -60,6 +60,7 @@ public class DataConstants {
public static final String ATTRIBUTES_UPDATED = "ATTRIBUTES_UPDATED";
public static final String ATTRIBUTES_DELETED = "ATTRIBUTES_DELETED";
public static final String TIMESERIES_UPDATED = "TIMESERIES_UPDATED";
public static final String TIMESERIES_DELETED = "TIMESERIES_DELETED";
public static final String ALARM_ACK = "ALARM_ACK";
public static final String ALARM_CLEAR = "ALARM_CLEAR";
public static final String ENTITY_ASSIGNED_FROM_TENANT = "ENTITY_ASSIGNED_FROM_TENANT";

View File

@ -24,8 +24,8 @@ public enum ActionType {
UPDATED(false), // log entity
ATTRIBUTES_UPDATED(false), // log attributes/values
ATTRIBUTES_DELETED(false), // log attributes
TIMESERIES_DELETED(false), // log timeseries
TIMESERIES_UPDATED(false), // log timeseries update
TIMESERIES_DELETED(false), // log timeseries
RPC_CALL(false), // log method and params
CREDENTIALS_UPDATED(false), // log new credentials
ASSIGNED_TO_CUSTOMER(false), // log customer name

View File

@ -39,21 +39,23 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.dao.audit.sink.AuditLogSink;
import org.thingsboard.server.dao.device.provision.ProvisionRequest;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.device.provision.ProvisionRequest;
import org.thingsboard.server.dao.service.DataValidator;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import static org.thingsboard.server.dao.service.Validator.validateEntityId;
import static org.thingsboard.server.dao.service.Validator.validateId;
@ -265,6 +267,32 @@ public class AuditLogServiceImpl implements AuditLogService {
actionData.set("provisionRequest", objectMapper.valueToTree(request));
}
break;
case TIMESERIES_UPDATED:
actionData.put("entityId", entityId.toString());
List<TsKvEntry> updatedTimeseries = extractParameter(List.class, 0, additionalInfo);
if (updatedTimeseries != null) {
ArrayNode result = actionData.putArray("timeseries");
updatedTimeseries.stream()
.collect(Collectors.groupingBy(TsKvEntry::getTs))
.forEach((k, v) -> {
ObjectNode element = objectMapper.createObjectNode();
element.put("ts", k);
ObjectNode values = element.putObject("values");
v.forEach(kvEntry -> values.put(kvEntry.getKey(), kvEntry.getValueAsString()));
result.add(element);
});
}
break;
case TIMESERIES_DELETED:
actionData.put("entityId", entityId.toString());
List<String> timeseriesKeys = extractParameter(List.class, 0, additionalInfo);
if (timeseriesKeys != null) {
ArrayNode timeseriesArrayNode = actionData.putArray("timeseries");
timeseriesKeys.forEach(timeseriesArrayNode::add);
}
actionData.put("startTs", extractParameter(Long.class, 1, additionalInfo));
actionData.put("endTs", extractParameter(Long.class, 2, additionalInfo));
break;
}
return actionData;
}

View File

@ -35,7 +35,8 @@ import org.thingsboard.server.common.msg.session.SessionMsgType;
configClazz = EmptyNodeConfiguration.class,
relationTypes = {"Post attributes", "Post telemetry", "RPC Request from Device", "RPC Request to Device", "Activity Event", "Inactivity Event",
"Connect Event", "Disconnect Event", "Entity Created", "Entity Updated", "Entity Deleted", "Entity Assigned",
"Entity Unassigned", "Attributes Updated", "Attributes Deleted", "Alarm Acknowledged", "Alarm Cleared", "Other", "Entity Assigned From Tenant", "Entity Assigned To Tenant", "Timeseries Updated"},
"Entity Unassigned", "Attributes Updated", "Attributes Deleted", "Alarm Acknowledged", "Alarm Cleared", "Other", "Entity Assigned From Tenant", "Entity Assigned To Tenant",
"Timeseries Updated", "Timeseries Deleted"},
nodeDescription = "Route incoming messages by Message Type",
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.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
@ -91,7 +92,9 @@ public class TbMsgTypeSwitchNode implements TbNode {
} else if (msg.getType().equals(DataConstants.ENTITY_ASSIGNED_TO_TENANT)) {
relationType = "Entity Assigned To Tenant";
} else if (msg.getType().equals(DataConstants.TIMESERIES_UPDATED)) {
relationType = "Timeseries updated";
relationType = "Timeseries Updated";
} else if (msg.getType().equals(DataConstants.TIMESERIES_DELETED)) {
relationType = "Timeseries Deleted";
} else {
relationType = "Other";
}

View File

@ -53,7 +53,9 @@ export enum ActionType {
ASSIGNED_FROM_TENANT = 'ASSIGNED_FROM_TENANT',
ASSIGNED_TO_TENANT = 'ASSIGNED_TO_TENANT',
PROVISION_SUCCESS = 'PROVISION_SUCCESS',
PROVISION_FAILURE = 'PROVISION_FAILURE'
PROVISION_FAILURE = 'PROVISION_FAILURE',
TIMESERIES_UPDATED = 'TIMESERIES_UPDATED',
TIMESERIES_DELETED = 'TIMESERIES_DELETED'
}
export enum ActionStatus {
@ -87,7 +89,9 @@ export const actionTypeTranslations = new Map<ActionType, string>(
[ActionType.ASSIGNED_FROM_TENANT, 'audit-log.type-assigned-from-tenant'],
[ActionType.ASSIGNED_TO_TENANT, 'audit-log.type-assigned-to-tenant'],
[ActionType.PROVISION_SUCCESS, 'audit-log.type-provision-success'],
[ActionType.PROVISION_FAILURE, 'audit-log.type-provision-failure']
[ActionType.PROVISION_FAILURE, 'audit-log.type-provision-failure'],
[ActionType.TIMESERIES_UPDATED, 'audit-log.type-timeseries-updated'],
[ActionType.TIMESERIES_DELETED, 'audit-log.type-timeseries-deleted']
]
);

View File

@ -527,7 +527,9 @@
"type-assigned-from-tenant": "Assigned from Tenant",
"type-assigned-to-tenant": "Assigned to Tenant",
"type-provision-success": "Device provisioned",
"type-provision-failure": "Device provisioning was failed"
"type-provision-failure": "Device provisioning was failed",
"type-timeseries-updated": "Telemetry updated",
"type-timeseries-deleted": "Telemetry deleted"
},
"confirm-on-exit": {
"message": "You have unsaved changes. Are you sure you want to leave this page?",