Browse Source

Audit Log improvements

pull/951/head
Andrew Shvayka 8 years ago
parent
commit
8db6820256
  1. 17
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  2. 11
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  3. 31
      application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java
  4. 1
      application/src/main/resources/thingsboard.yml
  5. 7
      common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java
  6. 1
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java
  7. 19
      dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java
  8. 14
      dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java
  9. 2
      dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java
  10. 15
      ui/src/app/common/types.constant.js
  11. 5
      ui/src/app/locale/locale.constant-en_US.json

17
application/src/main/java/org/thingsboard/server/controller/AlarmController.java

@ -26,6 +26,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmId; import org.thingsboard.server.common.data.alarm.AlarmId;
import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmInfo;
@ -33,6 +34,7 @@ import org.thingsboard.server.common.data.alarm.AlarmQuery;
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
@ -53,7 +55,6 @@ public class AlarmController extends BaseController {
checkParameter(ALARM_ID, strAlarmId); checkParameter(ALARM_ID, strAlarmId);
try { try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
return checkAlarmId(alarmId); return checkAlarmId(alarmId);
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
@ -79,8 +80,14 @@ public class AlarmController extends BaseController {
public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException { public Alarm saveAlarm(@RequestBody Alarm alarm) throws ThingsboardException {
try { try {
alarm.setTenantId(getCurrentUser().getTenantId()); alarm.setTenantId(getCurrentUser().getTenantId());
return checkNotNull(alarmService.createOrUpdateAlarm(alarm)); Alarm savedAlarm = checkNotNull(alarmService.createOrUpdateAlarm(alarm));
logEntityAction(savedAlarm.getId(), savedAlarm,
getCurrentUser().getCustomerId(),
savedAlarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
return savedAlarm;
} catch (Exception e) { } catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET), alarm,
null, alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e);
throw handleException(e); throw handleException(e);
} }
} }
@ -92,8 +99,9 @@ public class AlarmController extends BaseController {
checkParameter(ALARM_ID, strAlarmId); checkParameter(ALARM_ID, strAlarmId);
try { try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
checkAlarmId(alarmId); Alarm alarm = checkAlarmId(alarmId);
alarmService.ackAlarm(alarmId, System.currentTimeMillis()).get(); alarmService.ackAlarm(alarmId, System.currentTimeMillis()).get();
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_ACK, null);
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
} }
@ -106,8 +114,9 @@ public class AlarmController extends BaseController {
checkParameter(ALARM_ID, strAlarmId); checkParameter(ALARM_ID, strAlarmId);
try { try {
AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); AlarmId alarmId = new AlarmId(toUUID(strAlarmId));
checkAlarmId(alarmId); Alarm alarm = checkAlarmId(alarmId);
alarmService.clearAlarm(alarmId, null, System.currentTimeMillis()).get(); alarmService.clearAlarm(alarmId, null, System.currentTimeMillis()).get();
logEntityAction(alarmId, alarm, getCurrentUser().getCustomerId(), ActionType.ALARM_CLEAR, null);
} catch (Exception e) { } catch (Exception e) {
throw handleException(e); throw handleException(e);
} }

11
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -529,18 +529,16 @@ public abstract class BaseController {
return baseUrl; return baseUrl;
} }
protected <I extends UUIDBased & EntityId> I emptyId(EntityType entityType) { protected <I extends EntityId> I emptyId(EntityType entityType) {
return (I)EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID); return (I)EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID);
} }
protected <E extends BaseData<I> & HasName, protected <E extends HasName, I extends EntityId> void logEntityAction(I entityId, E entity, CustomerId customerId,
I extends UUIDBased & EntityId> void logEntityAction(I entityId, E entity, CustomerId customerId,
ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException {
logEntityAction(getCurrentUser(), entityId, entity, customerId, actionType, e, additionalInfo); logEntityAction(getCurrentUser(), entityId, entity, customerId, actionType, e, additionalInfo);
} }
protected <E extends BaseData<I> & HasName, protected <E extends HasName, I extends EntityId> void logEntityAction(User user, I entityId, E entity, CustomerId customerId,
I extends UUIDBased & EntityId> void logEntityAction(User user, I entityId, E entity, CustomerId customerId,
ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException { ActionType actionType, Exception e, Object... additionalInfo) throws ThingsboardException {
if (customerId == null || customerId.isNullUid()) { if (customerId == null || customerId.isNullUid()) {
customerId = user.getCustomerId(); customerId = user.getCustomerId();
@ -556,8 +554,7 @@ public abstract class BaseController {
return error != null ? (Exception.class.isInstance(error) ? (Exception) error : new Exception(error)) : null; return error != null ? (Exception.class.isInstance(error) ? (Exception) error : new Exception(error)) : null;
} }
private <E extends BaseData<I> & HasName, private <E extends HasName, I extends EntityId> void pushEntityActionToRuleEngine(I entityId, E entity, User user, CustomerId customerId,
I extends UUIDBased & EntityId> void pushEntityActionToRuleEngine(I entityId, E entity, User user, CustomerId customerId,
ActionType actionType, Object... additionalInfo) { ActionType actionType, Object... additionalInfo) {
String msgType = null; String msgType = null;
switch (actionType) { switch (actionType) {

31
application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java

@ -24,10 +24,13 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; 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.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory; 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.EntityRelation;
import org.thingsboard.server.common.data.relation.EntityRelationInfo; import org.thingsboard.server.common.data.relation.EntityRelationInfo;
import org.thingsboard.server.common.data.relation.EntityRelationsQuery; import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
@ -58,7 +61,15 @@ public class EntityRelationController extends BaseController {
relation.setTypeGroup(RelationTypeGroup.COMMON); relation.setTypeGroup(RelationTypeGroup.COMMON);
} }
relationService.saveRelation(relation); relationService.saveRelation(relation);
logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_ADD_OR_UPDATE, null, relation);
logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_ADD_OR_UPDATE, null, relation);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_ADD_OR_UPDATE, e, relation);
logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_ADD_OR_UPDATE, e, relation);
throw handleException(e); throw handleException(e);
} }
} }
@ -81,12 +92,21 @@ public class EntityRelationController extends BaseController {
checkEntityId(fromId); checkEntityId(fromId);
checkEntityId(toId); checkEntityId(toId);
RelationTypeGroup relationTypeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); RelationTypeGroup relationTypeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
EntityRelation relation = new EntityRelation(fromId, toId, strRelationType, relationTypeGroup);
try { try {
Boolean found = relationService.deleteRelation(fromId, toId, strRelationType, relationTypeGroup); Boolean found = relationService.deleteRelation(fromId, toId, strRelationType, relationTypeGroup);
if (!found) { if (!found) {
throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND); throw new ThingsboardException("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND);
} }
logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_DELETED, null, relation);
logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_DELETED, null, relation);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(relation.getFrom(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_DELETED, e, relation);
logEntityAction(relation.getTo(), null, getCurrentUser().getCustomerId(),
ActionType.RELATION_DELETED, e, relation);
throw handleException(e); throw handleException(e);
} }
} }
@ -102,7 +122,9 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId); checkEntityId(entityId);
try { try {
relationService.deleteEntityRelations(entityId); relationService.deleteEntityRelations(entityId);
logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, null);
} catch (Exception e) { } catch (Exception e) {
logEntityAction(entityId, null, getCurrentUser().getCustomerId(), ActionType.RELATIONS_DELETED, e);
throw handleException(e); throw handleException(e);
} }
} }
@ -210,8 +232,8 @@ public class EntityRelationController extends BaseController {
@RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {TO_ID, TO_TYPE}) @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {TO_ID, TO_TYPE})
@ResponseBody @ResponseBody
public List<EntityRelationInfo> findInfoByTo(@RequestParam(TO_ID) String strToId, public List<EntityRelationInfo> findInfoByTo(@RequestParam(TO_ID) String strToId,
@RequestParam(TO_TYPE) String strToType, @RequestParam(TO_TYPE) String strToType,
@RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException {
checkParameter(TO_ID, strToId); checkParameter(TO_ID, strToId);
checkParameter(TO_TYPE, strToType); checkParameter(TO_TYPE, strToType);
EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId); EntityId entityId = EntityIdFactory.getByTypeAndId(strToType, strToId);
@ -276,10 +298,11 @@ public class EntityRelationController extends BaseController {
private RelationTypeGroup parseRelationTypeGroup(String strRelationTypeGroup, RelationTypeGroup defaultValue) { private RelationTypeGroup parseRelationTypeGroup(String strRelationTypeGroup, RelationTypeGroup defaultValue) {
RelationTypeGroup result = defaultValue; RelationTypeGroup result = defaultValue;
if (strRelationTypeGroup != null && strRelationTypeGroup.trim().length()>0) { if (strRelationTypeGroup != null && strRelationTypeGroup.trim().length() > 0) {
try { try {
result = RelationTypeGroup.valueOf(strRelationTypeGroup); result = RelationTypeGroup.valueOf(strRelationTypeGroup);
} catch (IllegalArgumentException e) { } } catch (IllegalArgumentException e) {
}
} }
return result; return result;
} }

1
application/src/main/resources/thingsboard.yml

@ -385,6 +385,7 @@ audit_log:
"customer": "${AUDIT_LOG_MASK_CUSTOMER:W}" "customer": "${AUDIT_LOG_MASK_CUSTOMER:W}"
"user": "${AUDIT_LOG_MASK_USER:W}" "user": "${AUDIT_LOG_MASK_USER:W}"
"rule_chain": "${AUDIT_LOG_MASK_RULE_CHAIN:W}" "rule_chain": "${AUDIT_LOG_MASK_RULE_CHAIN:W}"
"alarm": "${AUDIT_LOG_MASK_ALARM:W}"
sink: sink:
# Type of external sink. possible options: none, elasticsearch # Type of external sink. possible options: none, elasticsearch
type: "${AUDIT_LOG_SINK_TYPE:none}" type: "${AUDIT_LOG_SINK_TYPE:none}"

7
common/data/src/main/java/org/thingsboard/server/common/data/audit/ActionType.java

@ -31,7 +31,12 @@ public enum ActionType {
ACTIVATED(false), // log string id ACTIVATED(false), // log string id
SUSPENDED(false), // log string id SUSPENDED(false), // log string id
CREDENTIALS_READ(true), // log device id CREDENTIALS_READ(true), // log device id
ATTRIBUTES_READ(true); // log attributes ATTRIBUTES_READ(true), // log attributes
RELATION_ADD_OR_UPDATE (false),
RELATION_DELETED (false),
RELATIONS_DELETED (false),
ALARM_ACK (false),
ALARM_CLEAR (false);
private final boolean isRead; private final boolean isRead;

1
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java

@ -60,4 +60,5 @@ public class EntityIdFactory {
} }
throw new IllegalArgumentException("EntityType " + type + " is not supported!"); throw new IllegalArgumentException("EntityType " + type + " is not supported!");
} }
} }

19
dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogService.java

@ -40,15 +40,14 @@ public interface AuditLogService {
TimePageData<AuditLog> findAuditLogsByTenantId(TenantId tenantId, TimePageLink pageLink); TimePageData<AuditLog> findAuditLogsByTenantId(TenantId tenantId, TimePageLink pageLink);
<E extends BaseData<I> & HasName, <E extends HasName, I extends EntityId> ListenableFuture<List<Void>> logEntityAction(
I extends UUIDBased & EntityId> ListenableFuture<List<Void>> logEntityAction( TenantId tenantId,
TenantId tenantId, CustomerId customerId,
CustomerId customerId, UserId userId,
UserId userId, String userName,
String userName, I entityId,
I entityId, E entity,
E entity, ActionType actionType,
ActionType actionType, Exception e, Object... additionalInfo);
Exception e, Object... additionalInfo);
} }

14
dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java

@ -43,6 +43,7 @@ import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.page.TimePageData; import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink; 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.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.dao.audit.sink.AuditLogSink; import org.thingsboard.server.dao.audit.sink.AuditLogSink;
@ -115,7 +116,7 @@ public class AuditLogServiceImpl implements AuditLogService {
} }
@Override @Override
public <E extends BaseData<I> & HasName, I extends UUIDBased & EntityId> ListenableFuture<List<Void>> public <E extends HasName, I extends EntityId> ListenableFuture<List<Void>>
logEntityAction(TenantId tenantId, CustomerId customerId, UserId userId, String userName, I entityId, E entity, logEntityAction(TenantId tenantId, CustomerId customerId, UserId userId, String userName, I entityId, E entity,
ActionType actionType, Exception e, Object... additionalInfo) { ActionType actionType, Exception e, Object... additionalInfo) {
if (canLog(entityId.getEntityType(), actionType)) { if (canLog(entityId.getEntityType(), actionType)) {
@ -156,14 +157,16 @@ public class AuditLogServiceImpl implements AuditLogService {
} }
} }
private <E extends BaseData<I> & HasName, I extends UUIDBased & EntityId> JsonNode constructActionData(I entityId, private <E extends HasName, I extends EntityId> JsonNode constructActionData(I entityId, E entity,
E entity,
ActionType actionType, ActionType actionType,
Object... additionalInfo) { Object... additionalInfo) {
ObjectNode actionData = objectMapper.createObjectNode(); ObjectNode actionData = objectMapper.createObjectNode();
switch(actionType) { switch(actionType) {
case ADDED: case ADDED:
case UPDATED: case UPDATED:
case ALARM_ACK:
case ALARM_CLEAR:
case RELATIONS_DELETED:
if (entity != null) { if (entity != null) {
ObjectNode entityNode = objectMapper.valueToTree(entity); ObjectNode entityNode = objectMapper.valueToTree(entity);
if (entityId.getEntityType() == EntityType.DASHBOARD) { if (entityId.getEntityType() == EntityType.DASHBOARD) {
@ -240,6 +243,11 @@ public class AuditLogServiceImpl implements AuditLogService {
actionData.put("unassignedCustomerId", strCustomerId); actionData.put("unassignedCustomerId", strCustomerId);
actionData.put("unassignedCustomerName", strCustomerName); actionData.put("unassignedCustomerName", strCustomerName);
break; break;
case RELATION_ADD_OR_UPDATE:
case RELATION_DELETED:
EntityRelation relation = extractParameter(EntityRelation.class, 0, additionalInfo);
actionData.set("relation", objectMapper.valueToTree(relation));
break;
} }
return actionData; return actionData;
} }

2
dao/src/main/java/org/thingsboard/server/dao/audit/DummyAuditLogServiceImpl.java

@ -57,7 +57,7 @@ public class DummyAuditLogServiceImpl implements AuditLogService {
} }
@Override @Override
public <E extends BaseData<I> & HasName, I extends UUIDBased & EntityId> ListenableFuture<List<Void>> logEntityAction(TenantId tenantId, CustomerId customerId, UserId userId, String userName, I entityId, E entity, ActionType actionType, Exception e, Object... additionalInfo) { public <E extends HasName, I extends EntityId> ListenableFuture<List<Void>> logEntityAction(TenantId tenantId, CustomerId customerId, UserId userId, String userName, I entityId, E entity, ActionType actionType, Exception e, Object... additionalInfo) {
return null; return null;
} }

15
ui/src/app/common/types.constant.js

@ -195,6 +195,21 @@ export default angular.module('thingsboard.types', [])
}, },
"ATTRIBUTES_READ": { "ATTRIBUTES_READ": {
name: "audit-log.type-attributes-read" name: "audit-log.type-attributes-read"
},
"RELATION_ADD_OR_UPDATE": {
name: "audit-log.type-relation-add-or-update"
},
"RELATION_DELETED": {
name: "audit-log.type-relation-delete"
},
"RELATIONS_DELETED": {
name: "audit-log.type-relations-delete"
},
"ALARM_ACK": {
name: "audit-log.type-alarm-ack"
},
"ALARM_CLEAR": {
name: "audit-log.type-alarm-clear"
} }
}, },
auditLogActionStatus: { auditLogActionStatus: {

5
ui/src/app/locale/locale.constant-en_US.json

@ -288,6 +288,11 @@
"type-suspended": "Suspended", "type-suspended": "Suspended",
"type-credentials-read": "Credentials read", "type-credentials-read": "Credentials read",
"type-attributes-read": "Attributes read", "type-attributes-read": "Attributes read",
"type-relation-add-or-update": "Relation updated",
"type-relation-delete": "Relation deleted",
"type-relations-delete": "All relation deleted",
"type-alarm-ack": "Acknowledged",
"type-alarm-clear": "Cleared",
"status-success": "Success", "status-success": "Success",
"status-failure": "Failure", "status-failure": "Failure",
"audit-log-details": "Audit log details", "audit-log-details": "Audit log details",

Loading…
Cancel
Save