Merge pull request #11421 from irynamatveieva/fix/audit-logs-alarm-deleted
Fix null entityId in audit log when alarm is deleted
This commit is contained in:
		
						commit
						e0244c2970
					
				@ -196,7 +196,7 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
 | 
			
		||||
    public Boolean delete(Alarm alarm, User user) {
 | 
			
		||||
        TenantId tenantId = alarm.getTenantId();
 | 
			
		||||
        logEntityActionService.logEntityAction(tenantId, alarm.getOriginator(), alarm, alarm.getCustomerId(),
 | 
			
		||||
                ActionType.ALARM_DELETE, user);
 | 
			
		||||
                ActionType.ALARM_DELETE, user, alarm.getId());
 | 
			
		||||
        return alarmSubscriptionService.deleteAlarm(tenantId, alarm.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -260,7 +260,7 @@ public class AlarmControllerTest extends AbstractControllerTest {
 | 
			
		||||
        doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk());
 | 
			
		||||
 | 
			
		||||
        testNotifyEntityAllOneTime(new Alarm(alarm), alarm.getId(), alarm.getOriginator(),
 | 
			
		||||
                tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ALARM_DELETE);
 | 
			
		||||
                tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ALARM_DELETE, alarm.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -273,7 +273,7 @@ public class AlarmControllerTest extends AbstractControllerTest {
 | 
			
		||||
        doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk());
 | 
			
		||||
 | 
			
		||||
        testNotifyEntityAllOneTime(new Alarm(alarm), alarm.getId(), alarm.getOriginator(),
 | 
			
		||||
                tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_DELETE);
 | 
			
		||||
                tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_DELETE, alarm.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
 | 
			
		||||
@ -129,7 +129,7 @@ public class DefaultTbAlarmServiceTest {
 | 
			
		||||
    public void testDelete() {
 | 
			
		||||
        service.delete(new Alarm(), new User());
 | 
			
		||||
 | 
			
		||||
        verify(logEntityActionService, times(1)).logEntityAction(any(), any(), any(), any(), eq(ActionType.ALARM_DELETE), any());
 | 
			
		||||
        verify(logEntityActionService, times(1)).logEntityAction(any(), any(), any(), any(), eq(ActionType.ALARM_DELETE), any(), any());
 | 
			
		||||
        verify(alarmSubscriptionService, times(1)).deleteAlarm(any(), any());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,52 +22,72 @@ import java.util.Optional;
 | 
			
		||||
 | 
			
		||||
public enum ActionType {
 | 
			
		||||
 | 
			
		||||
    ADDED(false, TbMsgType.ENTITY_CREATED), // log entity
 | 
			
		||||
    DELETED(false, TbMsgType.ENTITY_DELETED), // log string id
 | 
			
		||||
    UPDATED(false, TbMsgType.ENTITY_UPDATED), // log entity
 | 
			
		||||
    ATTRIBUTES_UPDATED(false, TbMsgType.ATTRIBUTES_UPDATED), // log attributes/values
 | 
			
		||||
    ATTRIBUTES_DELETED(false, TbMsgType.ATTRIBUTES_DELETED), // log attributes
 | 
			
		||||
    TIMESERIES_UPDATED(false, TbMsgType.TIMESERIES_UPDATED), // log timeseries update
 | 
			
		||||
    TIMESERIES_DELETED(false, TbMsgType.TIMESERIES_DELETED), // log timeseries
 | 
			
		||||
    RPC_CALL(false, null), // log method and params
 | 
			
		||||
    CREDENTIALS_UPDATED(false, null), // log new credentials
 | 
			
		||||
    ASSIGNED_TO_CUSTOMER(false, TbMsgType.ENTITY_ASSIGNED), // log customer name
 | 
			
		||||
    UNASSIGNED_FROM_CUSTOMER(false, TbMsgType.ENTITY_UNASSIGNED), // log customer name
 | 
			
		||||
    ACTIVATED(false, null), // log string id
 | 
			
		||||
    SUSPENDED(false, null), // log string id
 | 
			
		||||
    CREDENTIALS_READ(true, null), // log device id
 | 
			
		||||
    ATTRIBUTES_READ(true, null), // log attributes
 | 
			
		||||
    RELATION_ADD_OR_UPDATE(false, TbMsgType.RELATION_ADD_OR_UPDATE),
 | 
			
		||||
    RELATION_DELETED(false, TbMsgType.RELATION_DELETED),
 | 
			
		||||
    RELATIONS_DELETED(false, TbMsgType.RELATIONS_DELETED),
 | 
			
		||||
    REST_API_RULE_ENGINE_CALL(false, null), // log call to rule engine from REST API
 | 
			
		||||
    ALARM_ACK(false, TbMsgType.ALARM_ACK),
 | 
			
		||||
    ALARM_CLEAR(false, TbMsgType.ALARM_CLEAR),
 | 
			
		||||
    ALARM_DELETE(false, TbMsgType.ALARM_DELETE),
 | 
			
		||||
    ALARM_ASSIGNED(false, TbMsgType.ALARM_ASSIGNED),
 | 
			
		||||
    ALARM_UNASSIGNED(false, TbMsgType.ALARM_UNASSIGNED),
 | 
			
		||||
    LOGIN(false, null),
 | 
			
		||||
    LOGOUT(false, null),
 | 
			
		||||
    LOCKOUT(false, null),
 | 
			
		||||
    ASSIGNED_FROM_TENANT(false, TbMsgType.ENTITY_ASSIGNED_FROM_TENANT),
 | 
			
		||||
    ASSIGNED_TO_TENANT(false, TbMsgType.ENTITY_ASSIGNED_TO_TENANT),
 | 
			
		||||
    PROVISION_SUCCESS(false, TbMsgType.PROVISION_SUCCESS),
 | 
			
		||||
    PROVISION_FAILURE(false, TbMsgType.PROVISION_FAILURE),
 | 
			
		||||
    ASSIGNED_TO_EDGE(false, TbMsgType.ENTITY_ASSIGNED_TO_EDGE), // log edge name
 | 
			
		||||
    UNASSIGNED_FROM_EDGE(false, TbMsgType.ENTITY_UNASSIGNED_FROM_EDGE),
 | 
			
		||||
    ADDED_COMMENT(false, TbMsgType.COMMENT_CREATED),
 | 
			
		||||
    UPDATED_COMMENT(false, TbMsgType.COMMENT_UPDATED),
 | 
			
		||||
    DELETED_COMMENT(false, null),
 | 
			
		||||
    SMS_SENT(false, null);
 | 
			
		||||
    ADDED(TbMsgType.ENTITY_CREATED), // log entity
 | 
			
		||||
    DELETED(TbMsgType.ENTITY_DELETED), // log string id
 | 
			
		||||
    UPDATED(TbMsgType.ENTITY_UPDATED), // log entity
 | 
			
		||||
    ATTRIBUTES_UPDATED(TbMsgType.ATTRIBUTES_UPDATED), // log attributes/values
 | 
			
		||||
    ATTRIBUTES_DELETED(TbMsgType.ATTRIBUTES_DELETED), // log attributes
 | 
			
		||||
    TIMESERIES_UPDATED(TbMsgType.TIMESERIES_UPDATED), // log timeseries update
 | 
			
		||||
    TIMESERIES_DELETED(TbMsgType.TIMESERIES_DELETED), // log timeseries
 | 
			
		||||
    RPC_CALL, // log method and params
 | 
			
		||||
    CREDENTIALS_UPDATED, // log new credentials
 | 
			
		||||
    ASSIGNED_TO_CUSTOMER(TbMsgType.ENTITY_ASSIGNED), // log customer name
 | 
			
		||||
    UNASSIGNED_FROM_CUSTOMER(TbMsgType.ENTITY_UNASSIGNED), // log customer name
 | 
			
		||||
    ACTIVATED, // log string id
 | 
			
		||||
    SUSPENDED, // log string id
 | 
			
		||||
    CREDENTIALS_READ(true), // log device id
 | 
			
		||||
    ATTRIBUTES_READ(true), // log attributes
 | 
			
		||||
    RELATION_ADD_OR_UPDATE(TbMsgType.RELATION_ADD_OR_UPDATE),
 | 
			
		||||
    RELATION_DELETED(TbMsgType.RELATION_DELETED),
 | 
			
		||||
    RELATIONS_DELETED(TbMsgType.RELATIONS_DELETED),
 | 
			
		||||
    REST_API_RULE_ENGINE_CALL, // log call to rule engine from REST API
 | 
			
		||||
    ALARM_ACK(TbMsgType.ALARM_ACK, true),
 | 
			
		||||
    ALARM_CLEAR(TbMsgType.ALARM_CLEAR, true),
 | 
			
		||||
    ALARM_DELETE(TbMsgType.ALARM_DELETE, true),
 | 
			
		||||
    ALARM_ASSIGNED(TbMsgType.ALARM_ASSIGNED, true),
 | 
			
		||||
    ALARM_UNASSIGNED(TbMsgType.ALARM_UNASSIGNED, true),
 | 
			
		||||
    LOGIN,
 | 
			
		||||
    LOGOUT,
 | 
			
		||||
    LOCKOUT,
 | 
			
		||||
    ASSIGNED_FROM_TENANT(TbMsgType.ENTITY_ASSIGNED_FROM_TENANT),
 | 
			
		||||
    ASSIGNED_TO_TENANT(TbMsgType.ENTITY_ASSIGNED_TO_TENANT),
 | 
			
		||||
    PROVISION_SUCCESS(TbMsgType.PROVISION_SUCCESS),
 | 
			
		||||
    PROVISION_FAILURE(TbMsgType.PROVISION_FAILURE),
 | 
			
		||||
    ASSIGNED_TO_EDGE(TbMsgType.ENTITY_ASSIGNED_TO_EDGE), // log edge name
 | 
			
		||||
    UNASSIGNED_FROM_EDGE(TbMsgType.ENTITY_UNASSIGNED_FROM_EDGE),
 | 
			
		||||
    ADDED_COMMENT(TbMsgType.COMMENT_CREATED),
 | 
			
		||||
    UPDATED_COMMENT(TbMsgType.COMMENT_UPDATED),
 | 
			
		||||
    DELETED_COMMENT,
 | 
			
		||||
    SMS_SENT;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private final boolean isRead;
 | 
			
		||||
    private final boolean read;
 | 
			
		||||
 | 
			
		||||
    private final TbMsgType ruleEngineMsgType;
 | 
			
		||||
 | 
			
		||||
    ActionType(boolean isRead, TbMsgType ruleEngineMsgType) {
 | 
			
		||||
        this.isRead = isRead;
 | 
			
		||||
    @Getter
 | 
			
		||||
    private final boolean alarmAction;
 | 
			
		||||
 | 
			
		||||
    ActionType() {
 | 
			
		||||
        this(false, null, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ActionType(boolean read) {
 | 
			
		||||
        this(read, null, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ActionType(TbMsgType ruleEngineMsgType) {
 | 
			
		||||
        this(false, ruleEngineMsgType, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ActionType(TbMsgType ruleEngineMsgType, boolean isAlarmAction) {
 | 
			
		||||
        this(false, ruleEngineMsgType, isAlarmAction);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ActionType(boolean read, TbMsgType ruleEngineMsgType, boolean alarmAction) {
 | 
			
		||||
        this.read = read;
 | 
			
		||||
        this.ruleEngineMsgType = ruleEngineMsgType;
 | 
			
		||||
        this.alarmAction = alarmAction;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Optional<TbMsgType> getRuleEngineMsgType() {
 | 
			
		||||
 | 
			
		||||
@ -17,10 +17,16 @@ package org.thingsboard.server.common.data.audit;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.EnumSet;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.ACTIVATED;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.ALARM_ACK;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.ALARM_ASSIGNED;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.ALARM_CLEAR;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.ALARM_DELETE;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.ALARM_UNASSIGNED;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.ATTRIBUTES_READ;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.CREDENTIALS_READ;
 | 
			
		||||
import static org.thingsboard.server.common.data.audit.ActionType.CREDENTIALS_UPDATED;
 | 
			
		||||
@ -35,7 +41,7 @@ import static org.thingsboard.server.common.data.audit.ActionType.SUSPENDED;
 | 
			
		||||
 | 
			
		||||
class ActionTypeTest {
 | 
			
		||||
 | 
			
		||||
    private static final List<ActionType> typesWithNullRuleEngineMsgType = List.of(
 | 
			
		||||
    private final Set<ActionType> typesWithNullRuleEngineMsgType = EnumSet.of(
 | 
			
		||||
            RPC_CALL,
 | 
			
		||||
            CREDENTIALS_UPDATED,
 | 
			
		||||
            ACTIVATED,
 | 
			
		||||
@ -50,6 +56,12 @@ class ActionTypeTest {
 | 
			
		||||
            REST_API_RULE_ENGINE_CALL
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    private final Set<ActionType> alarmActionTypes = EnumSet.of(
 | 
			
		||||
            ALARM_ACK, ALARM_CLEAR, ALARM_DELETE, ALARM_ASSIGNED, ALARM_UNASSIGNED
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    private final Set<ActionType> readActionTypes = EnumSet.of(CREDENTIALS_READ, ATTRIBUTES_READ);
 | 
			
		||||
 | 
			
		||||
    // backward-compatibility tests
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@ -64,4 +76,28 @@ class ActionTypeTest {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void isAlarmActionTest() {
 | 
			
		||||
        var types = ActionType.values();
 | 
			
		||||
        for (var type : types) {
 | 
			
		||||
            if (alarmActionTypes.contains(type)) {
 | 
			
		||||
                assertThat(type.isAlarmAction()).isTrue();
 | 
			
		||||
            } else {
 | 
			
		||||
                assertThat(type.isAlarmAction()).isFalse();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    void isReadActionTypeTest() {
 | 
			
		||||
        var types = ActionType.values();
 | 
			
		||||
        for (var type : types) {
 | 
			
		||||
            if (readActionTypes.contains(type)) {
 | 
			
		||||
                assertThat(type.isRead()).isTrue();
 | 
			
		||||
            } else {
 | 
			
		||||
                assertThat(type.isRead()).isFalse();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.HasName;
 | 
			
		||||
import org.thingsboard.server.common.data.StringUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.alarm.AlarmComment;
 | 
			
		||||
import org.thingsboard.server.common.data.alarm.AlarmInfo;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionStatus;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.AuditLog;
 | 
			
		||||
@ -122,15 +123,7 @@ public class AuditLogServiceImpl implements AuditLogService {
 | 
			
		||||
            JsonNode actionData = constructActionData(entityId, entity, actionType, additionalInfo);
 | 
			
		||||
            ActionStatus actionStatus = ActionStatus.SUCCESS;
 | 
			
		||||
            String failureDetails = "";
 | 
			
		||||
            String entityName = "N/A";
 | 
			
		||||
            if (entity != null) {
 | 
			
		||||
                entityName = entity.getName();
 | 
			
		||||
            } else {
 | 
			
		||||
                try {
 | 
			
		||||
                    entityName = entityService.fetchEntityName(tenantId, entityId).orElse(entityName);
 | 
			
		||||
                } catch (Exception ignored) {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            String entityName = getEntityName(tenantId, entityId, entity, actionType);
 | 
			
		||||
            if (e != null) {
 | 
			
		||||
                actionStatus = ActionStatus.FAILURE;
 | 
			
		||||
                failureDetails = getFailureStack(e);
 | 
			
		||||
@ -157,6 +150,27 @@ public class AuditLogServiceImpl implements AuditLogService {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private <E extends HasName, I extends EntityId> String getEntityName(TenantId tenantId, I entityId, E entity, ActionType actionType) {
 | 
			
		||||
        if (entity == null) {
 | 
			
		||||
            return fetchEntityName(tenantId, entityId);
 | 
			
		||||
        }
 | 
			
		||||
        if (!actionType.isAlarmAction()) {
 | 
			
		||||
            return entity.getName();
 | 
			
		||||
        }
 | 
			
		||||
        if (entity instanceof AlarmInfo alarmInfo) {
 | 
			
		||||
            return alarmInfo.getOriginatorName();
 | 
			
		||||
        }
 | 
			
		||||
        return fetchEntityName(tenantId, entityId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private <I extends EntityId> String fetchEntityName(TenantId tenantId, I entityId) {
 | 
			
		||||
        try {
 | 
			
		||||
            return entityService.fetchEntityName(tenantId, entityId).orElse("N/A");
 | 
			
		||||
        } catch (Exception ignored) {
 | 
			
		||||
            return "N/A";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private <E extends HasName, I extends EntityId> JsonNode constructActionData(I entityId, E entity,
 | 
			
		||||
                                                                                 ActionType actionType,
 | 
			
		||||
                                                                                 Object... additionalInfo) {
 | 
			
		||||
@ -192,6 +206,10 @@ public class AuditLogServiceImpl implements AuditLogService {
 | 
			
		||||
                actionData.set("comment", comment.getComment());
 | 
			
		||||
                break;
 | 
			
		||||
            case ALARM_DELETE:
 | 
			
		||||
                EntityId alarmId = extractParameter(EntityId.class, additionalInfo);
 | 
			
		||||
                actionData.put("alarmId", alarmId != null ? alarmId.toString() : null);
 | 
			
		||||
                actionData.put("originatorId", entityId.toString());
 | 
			
		||||
                break;
 | 
			
		||||
            case DELETED:
 | 
			
		||||
            case ACTIVATED:
 | 
			
		||||
            case SUSPENDED:
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,144 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2024 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.dao.audit;
 | 
			
		||||
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.junit.jupiter.api.extension.ExtendWith;
 | 
			
		||||
import org.mockito.ArgumentCaptor;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.junit.jupiter.MockitoExtension;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.server.common.data.alarm.Alarm;
 | 
			
		||||
import org.thingsboard.server.common.data.alarm.AlarmComment;
 | 
			
		||||
import org.thingsboard.server.common.data.alarm.AlarmInfo;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.AuditLog;
 | 
			
		||||
import org.thingsboard.server.common.data.id.AlarmId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
import org.thingsboard.server.dao.audit.sink.AuditLogSink;
 | 
			
		||||
import org.thingsboard.server.dao.entity.EntityService;
 | 
			
		||||
import org.thingsboard.server.dao.service.validator.AuditLogDataValidator;
 | 
			
		||||
import org.thingsboard.server.dao.sql.JpaExecutorService;
 | 
			
		||||
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
import java.util.concurrent.Callable;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
 | 
			
		||||
@ExtendWith(MockitoExtension.class)
 | 
			
		||||
public class AuditLogServiceImplTest {
 | 
			
		||||
 | 
			
		||||
    private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("9114e9ac-6c28-4019-a2a7-b948cb9500d5"));
 | 
			
		||||
    private final CustomerId CUSTOMER_ID = new CustomerId(UUID.fromString("d15822ef-09eb-49a6-9068-21b9c8ae3356"));
 | 
			
		||||
    private final UserId USER_ID = new UserId(UUID.fromString("47a2c904-3a47-4530-91bb-51068a4610a7"));
 | 
			
		||||
    private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("b913c12a-9942-4cbd-9481-c42dad4831b0"));
 | 
			
		||||
 | 
			
		||||
    private final String USER_NAME = "Test User";
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private AuditLogServiceImpl auditLogService;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private EntityService entityService;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private AuditLogLevelFilter auditLogLevelFilter;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private AuditLogDataValidator auditLogDataValidator;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private JpaExecutorService executor;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private AuditLogDao auditLogDao;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private AuditLogSink auditLogSink;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void givenEntityIsNull_whenLogEntityAction_thenShouldFetchEntityName() throws Exception {
 | 
			
		||||
        // GIVEN
 | 
			
		||||
        given(auditLogLevelFilter.logEnabled(any(), any())).willReturn(true);
 | 
			
		||||
        given(entityService.fetchEntityName(any(), any())).willReturn(Optional.of("Test device"));
 | 
			
		||||
 | 
			
		||||
        // WHEN
 | 
			
		||||
        auditLogService.logEntityAction(TENANT_ID, CUSTOMER_ID, USER_ID, USER_NAME, DEVICE_ID, null, ActionType.ADDED, null);
 | 
			
		||||
 | 
			
		||||
        // THEN
 | 
			
		||||
        then(entityService).should().fetchEntityName(TENANT_ID, DEVICE_ID);
 | 
			
		||||
        verifyEntityName("Test device");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void givenActionTypeIsAlarmActionAndEntityIsAlarm_whenLogEntityAction_thenShouldGetEntityName() throws Exception {
 | 
			
		||||
        // GIVEN
 | 
			
		||||
        given(auditLogLevelFilter.logEnabled(any(), any())).willReturn(true);
 | 
			
		||||
        Alarm alarm = new Alarm(new AlarmId(UUID.fromString("55f577b3-6ef5-4b99-92dc-70eb78b2a970")));
 | 
			
		||||
        alarm.setType("Test alarm");
 | 
			
		||||
        AlarmComment comment = new AlarmComment();
 | 
			
		||||
        comment.setComment(JacksonUtil.toJsonNode("{\"comment\": \"test\"}"));
 | 
			
		||||
 | 
			
		||||
        // WHEN
 | 
			
		||||
        auditLogService.logEntityAction(TENANT_ID, CUSTOMER_ID, USER_ID, USER_NAME, alarm.getId(), alarm, ActionType.ADDED_COMMENT, null, comment);
 | 
			
		||||
 | 
			
		||||
        // THEN
 | 
			
		||||
        verifyEntityName("Test alarm");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void givenActionTypeIsAlarmActionAndEntityIsAlarmInfo_whenLogEntityAction_thenShouldGetEntityOriginatorName() throws Exception {
 | 
			
		||||
        // GIVEN
 | 
			
		||||
        given(auditLogLevelFilter.logEnabled(any(), any())).willReturn(true);
 | 
			
		||||
        AlarmInfo alarmInfo = new AlarmInfo();
 | 
			
		||||
        alarmInfo.setOriginatorName("Test device");
 | 
			
		||||
 | 
			
		||||
        // WHEN
 | 
			
		||||
        auditLogService.logEntityAction(TENANT_ID, CUSTOMER_ID, USER_ID, USER_NAME, DEVICE_ID, alarmInfo, ActionType.ALARM_ASSIGNED, null);
 | 
			
		||||
 | 
			
		||||
        // THEN
 | 
			
		||||
        verifyEntityName("Test device");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void givenActionTypeIsAlarmActionAndEntityIsAlarm_whenLogEntityAction_thenShouldFetchEntityName() throws Exception {
 | 
			
		||||
        // GIVEN
 | 
			
		||||
        given(auditLogLevelFilter.logEnabled(any(), any())).willReturn(true);
 | 
			
		||||
        given(entityService.fetchEntityName(any(), any())).willReturn(Optional.of("Test alarm"));
 | 
			
		||||
 | 
			
		||||
        // WHEN
 | 
			
		||||
        auditLogService.logEntityAction(TENANT_ID, CUSTOMER_ID, USER_ID, USER_NAME, DEVICE_ID, new Alarm(), ActionType.ALARM_DELETE, null);
 | 
			
		||||
 | 
			
		||||
        // THEN
 | 
			
		||||
        then(entityService).should().fetchEntityName(TENANT_ID, DEVICE_ID);
 | 
			
		||||
        verifyEntityName("Test alarm");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void verifyEntityName(String entityName) throws Exception {
 | 
			
		||||
        then(auditLogDataValidator).should().validate(any(AuditLog.class), any());
 | 
			
		||||
        ArgumentCaptor<Callable> submitTask = ArgumentCaptor.forClass(Callable.class);
 | 
			
		||||
        then(executor).should().submit(submitTask.capture());
 | 
			
		||||
        submitTask.getValue().call();
 | 
			
		||||
        ArgumentCaptor<AuditLog> auditLogEntry = ArgumentCaptor.forClass(AuditLog.class);
 | 
			
		||||
        then(auditLogDao).should().save(eq(TENANT_ID), auditLogEntry.capture());
 | 
			
		||||
        assertThat(auditLogEntry.getValue().getEntityName()).isEqualTo(entityName);
 | 
			
		||||
        then(auditLogSink).should().logAction(any());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -958,11 +958,11 @@
 | 
			
		||||
        "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",
 | 
			
		||||
        "type-alarm-delete": "Deleted",
 | 
			
		||||
        "type-alarm-assign": "Assigned",
 | 
			
		||||
        "type-alarm-unassign": "Unassigned",
 | 
			
		||||
        "type-alarm-ack": "Alarm acknowledged",
 | 
			
		||||
        "type-alarm-clear": "Alarm cleared",
 | 
			
		||||
        "type-alarm-delete": "Alarm deleted",
 | 
			
		||||
        "type-alarm-assign": "Alarm assigned",
 | 
			
		||||
        "type-alarm-unassign": "Alarm unassigned",
 | 
			
		||||
        "type-added-comment": "Added comment",
 | 
			
		||||
        "type-updated-comment": "Updated comment",
 | 
			
		||||
        "type-deleted-comment": "Deleted comment",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user