diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java index c7e4f2cd0b..b2962acf97 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/DefaultTbNotificationEntityService.java @@ -351,6 +351,10 @@ public class DefaultTbNotificationEntityService implements TbNotificationEntityS return EdgeEventActionType.RELATION_ADD_OR_UPDATE; case RELATION_DELETED: return EdgeEventActionType.RELATION_DELETED; + case ASSIGNED_TO_CUSTOMER: + return EdgeEventActionType.ASSIGNED_TO_CUSTOMER; + case UNASSIGNED_FROM_CUSTOMER: + return EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER; case ASSIGNED_TO_EDGE: return EdgeEventActionType.ASSIGNED_TO_EDGE; case UNASSIGNED_FROM_EDGE: diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java index 8207427716..e118346588 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/asset/DefaultTbAssetService.java @@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; @@ -35,6 +34,8 @@ import org.thingsboard.server.service.security.model.SecurityUser; import java.util.List; +import static org.thingsboard.server.service.entitiy.DefaultTbNotificationEntityService.edgeTypeByActionType; + @Service @TbCoreComponent @AllArgsConstructor @@ -80,7 +81,7 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb try { Asset savedAsset = checkNotNull(assetService.assignAssetToCustomer(tenantId, assetId, customerId)); notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, - actionType, EdgeEventActionType.ASSIGNED_TO_CUSTOMER, user, true, customerId.toString(), customer.getName()); + actionType, edgeTypeByActionType(actionType), user, true, customerId.toString(), customer.getName()); return savedAsset; } catch (Exception e) { @@ -99,7 +100,7 @@ public class DefaultTbAssetService extends AbstractTbEntityService implements Tb CustomerId customerId = customer.getId(); notificationEntityService.notifyAssignOrUnassignEntityToCustomer(tenantId, assetId, customerId, savedAsset, - actionType, EdgeEventActionType.UNASSIGNED_FROM_CUSTOMER, user, + actionType, edgeTypeByActionType(actionType), user, true, customerId.toString(), customer.getName()); return savedAsset; diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java index fad0feea51..30b03ead3a 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java @@ -16,6 +16,7 @@ package org.thingsboard.server.controller; import lombok.extern.slf4j.Slf4j; +import org.mockito.ArgumentMatcher; import org.mockito.Mockito; import org.springframework.boot.test.mock.mockito.SpyBean; import org.thingsboard.server.cluster.TbClusterService; @@ -33,6 +34,7 @@ import org.thingsboard.server.dao.audit.AuditLogService; import org.thingsboard.server.dao.model.ModelConstants; import java.util.Locale; +import java.util.Objects; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -50,9 +52,10 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { protected void testNotifyEntityAllOneTime(HasName entity, EntityId entityId, EntityId originatorId, TenantId tenantId, CustomerId customerId, UserId userId, String userName, ActionType actionType, Object... additionalInfo) { - testSendNotificationMsgToEdgeServiceTime(entityId, tenantId, actionType, 1); - testLogEntityActionOneTime(entity, originatorId, tenantId, customerId, userId, userName, actionType, additionalInfo); - testPushMsgToRuleEngineTime(originatorId, tenantId, 1); + int cntTime = 1; + testSendNotificationMsgToEdgeServiceTime(entityId, tenantId, actionType, cntTime); + logEntityAction(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo); + testPushMsgToRuleEngineTime(originatorId, tenantId, cntTime); Mockito.reset(tbClusterService, auditLogService); } @@ -67,20 +70,23 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { protected void testNotifyEntityOneTimeMsgToEdgeServiceNever(HasName entity, EntityId entityId, EntityId originatorId, TenantId tenantId, CustomerId customerId, UserId userId, String userName, ActionType actionType, Object... additionalInfo) { + int cntTime = 1; testNotificationMsgToEdgeServiceNever(entityId); - testLogEntityActionOneTime(entity, originatorId, tenantId, customerId, userId, userName, actionType, additionalInfo); - testPushMsgToRuleEngineTime(originatorId, tenantId, 1); + logEntityAction(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo); + testPushMsgToRuleEngineTime(originatorId, tenantId, cntTime); Mockito.reset(tbClusterService, auditLogService); } - protected void testNotifyEntityManyTimeMsgToEdgeServiceNever(HasName entity, HasName originator, - TenantId tenantId, CustomerId customerId, UserId userId, String userName, - ActionType actionType, int cntTime, Object... additionalInfo) { + protected void testNotifyManyEntityManyTimeMsgToEdgeServiceNever(HasName entity, HasName originator, + TenantId tenantId, CustomerId customerId, UserId userId, String userName, + ActionType actionType, int cntTime, Object... additionalInfo) { EntityId entityId = createEntityId_NULL_UUID(entity); EntityId originatorId = createEntityId_NULL_UUID(originator); testNotificationMsgToEdgeServiceNever(entityId); - testLogEntityActionManyTime(entity,originatorId, tenantId, customerId, - userId, userName, actionType, cntTime, additionalInfo); + ArgumentMatcher matcherEntityClassEquals = argument -> argument.getClass().equals(entity.getClass()); + ArgumentMatcher matcherOriginatorId = argument -> argument.getClass().equals(originatorId.getClass()); + logEntityActionAdditionalInfo(matcherEntityClassEquals, matcherOriginatorId, tenantId, customerId, userId, userName, actionType, cntTime, + additionalInfo); testPushMsgToRuleEngineTime(originatorId, tenantId, cntTime); Mockito.reset(tbClusterService, auditLogService); } @@ -88,37 +94,37 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { protected void testNotifyEntityBroadcastEntityStateChangeEventOneTimeMsgToEdgeServiceNever(HasName entity, EntityId entityId, EntityId originatorId, TenantId tenantId, CustomerId customerId, UserId userId, String userName, ActionType actionType, Object... additionalInfo) { + int cntTime = 1; testNotificationMsgToEdgeServiceNever(entityId); - testLogEntityActionOneTime(entity, originatorId, tenantId, customerId, userId, userName, actionType, additionalInfo); - testPushMsgToRuleEngineTime(originatorId, tenantId, 1); - testBroadcastEntityStateChangeEventTime(entityId, tenantId, 1); + logEntityAction(entity, originatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo); + testPushMsgToRuleEngineTime(originatorId, tenantId, cntTime); + testBroadcastEntityStateChangeEventTime(entityId, tenantId, cntTime); Mockito.reset(tbClusterService, auditLogService); } - protected void testNotifyEntityOneTimeError(HasName entity, TenantId tenantId, - UserId userId, String userName, ActionType actionType, Exception exp, - Object... additionalInfo) { + protected void testNotifyEntityEqualsOneTimeError(HasName entity, TenantId tenantId, + UserId userId, String userName, ActionType actionType, Exception exp, + Object... additionalInfo) { CustomerId customer_NULL_UUID = (CustomerId) EntityIdFactory.getByTypeAndUuid(EntityType.CUSTOMER, ModelConstants.NULL_UUID); - EntityId entity_NULL_UUID = createEntityId_NULL_UUID(entity); - testNotificationMsgToEdgeServiceNever(entity_NULL_UUID); - if (additionalInfo.length > 0) { - Mockito.verify(auditLogService, times(1)) - .logEntityAction(Mockito.eq(tenantId), - Mockito.eq(customer_NULL_UUID), Mockito.eq(userId), Mockito.eq(userName), - Mockito.eq(entity_NULL_UUID), Mockito.any(entity.getClass()), Mockito.eq(actionType), - Mockito.argThat(argument -> - argument.getMessage().contains(exp.getMessage())), - Mockito.eq(additionalInfo) - ); - } else { - Mockito.verify(auditLogService, times(1)) - .logEntityAction(Mockito.eq(tenantId), - Mockito.eq(customer_NULL_UUID), Mockito.eq(userId), Mockito.eq(userName), - Mockito.eq(entity_NULL_UUID), Mockito.any(entity.getClass()), Mockito.eq(actionType), - Mockito.argThat((argument -> argument.getMessage().contains(exp.getMessage()) & argument.getClass().equals(exp.getClass()))) - ); - } - testPushMsgToRuleEngineNever(entity_NULL_UUID); + EntityId entity_originator_NULL_UUID = createEntityId_NULL_UUID(entity); + testNotificationMsgToEdgeServiceNever(entity_originator_NULL_UUID); + ArgumentMatcher matcherEntityEquals = argument -> argument.getClass().equals(entity.getClass()); + ArgumentMatcher matcherError = argument -> argument.getMessage().contains(exp.getMessage()); + logEntityActionErrorAdditionalInfo(matcherEntityEquals, entity_originator_NULL_UUID, tenantId, customer_NULL_UUID, userId, + userName, actionType, 1, matcherError, additionalInfo); + testPushMsgToRuleEngineNever(entity_originator_NULL_UUID); + } + + protected void testNotifyEntityIsNullOneTimeError(HasName entity, TenantId tenantId, + UserId userId, String userName, ActionType actionType, Exception exp, + Object... additionalInfo) { + CustomerId customer_NULL_UUID = (CustomerId) EntityIdFactory.getByTypeAndUuid(EntityType.CUSTOMER, ModelConstants.NULL_UUID); + EntityId entity_originator_NULL_UUID = createEntityId_NULL_UUID(entity); + testNotificationMsgToEdgeServiceNever(entity_originator_NULL_UUID); + ArgumentMatcher matcherEntityIsNull = Objects::isNull; + ArgumentMatcher matcherError = argument -> argument.getMessage().contains(exp.getMessage()) & argument.getClass().equals(exp.getClass()); + logEntityActionErrorAdditionalInfo(matcherEntityIsNull, entity_originator_NULL_UUID, tenantId, customer_NULL_UUID, userId, userName, actionType, 1, matcherError, additionalInfo); + testPushMsgToRuleEngineNever(entity_originator_NULL_UUID); } protected void testNotifyEntityNever(EntityId entityId, HasName entity) { @@ -145,47 +151,16 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { Mockito.any(entityId.getClass()), Mockito.any(), Mockito.any()); } - private void testLogEntityActionOneTime(HasName entity, EntityId originatorId, TenantId tenantId, CustomerId customerId, - UserId userId, String userName, ActionType actionType, Object... additionalInfo) { - if (additionalInfo.length == 0) { - Mockito.verify(auditLogService, times(1)).logEntityAction(Mockito.eq(tenantId), Mockito.eq(customerId), - Mockito.eq(userId), Mockito.eq(userName), Mockito.eq(originatorId), - Mockito.eq(entity), Mockito.eq(actionType), Mockito.isNull()); - } else { - String additionalInfoStr = extractParameter(String.class, 0, additionalInfo); - Mockito.verify(auditLogService, times(1)).logEntityAction(Mockito.eq(tenantId), Mockito.eq(customerId), - Mockito.eq(userId), Mockito.eq(userName), Mockito.eq(originatorId), - Mockito.eq(entity), Mockito.eq(actionType), Mockito.isNull(), Mockito.eq(additionalInfoStr)); - } - } - - private void testLogEntityActionManyTime(HasName entity, EntityId originatorId, TenantId tenantId, CustomerId customerId, - UserId userId, String userName, ActionType actionType, int cntTime, Object... additionalInfo) { - if (additionalInfo.length == 0) { - Mockito.verify(auditLogService, times(cntTime)).logEntityAction(Mockito.eq(tenantId), Mockito.eq(customerId), - Mockito.eq(userId), Mockito.eq(userName), Mockito.any(originatorId.getClass()), - Mockito.any(entity.getClass()), Mockito.eq(actionType), Mockito.isNull()); - } else { - String additionalInfoStr = extractParameter(String.class, 0, additionalInfo); - Mockito.verify(auditLogService, times(cntTime)).logEntityAction(Mockito.eq(tenantId), Mockito.eq(customerId), - Mockito.eq(userId), Mockito.eq(userName), Mockito.any(originatorId.getClass()), - Mockito.any(entity.getClass()), Mockito.eq(actionType), Mockito.isNull(), Mockito.eq(additionalInfoStr)); - } - } - private void testPushMsgToRuleEngineTime(EntityId originatorId, TenantId tenantId, int cntTime) { - if (cntTime ==1) { - Mockito.verify(tbClusterService, times(cntTime)).pushMsgToRuleEngine(Mockito.eq(tenantId), - Mockito.eq(originatorId), Mockito.any(TbMsg.class), Mockito.isNull()); - } else { - Mockito.verify(tbClusterService, times(cntTime)).pushMsgToRuleEngine(Mockito.eq(tenantId), - Mockito.any(originatorId.getClass()), Mockito.any(TbMsg.class), Mockito.isNull()); - } + ArgumentMatcher matcherOriginatorId = cntTime == 1 ? argument -> argument.equals(originatorId) : + argument -> argument.getClass().equals(originatorId.getClass()); + Mockito.verify(tbClusterService, times(cntTime)).pushMsgToRuleEngine(Mockito.eq(tenantId), + Mockito.argThat(matcherOriginatorId), Mockito.any(TbMsg.class), Mockito.isNull()); } private void testSendNotificationMsgToEdgeServiceTime(EntityId entityId, TenantId tenantId, ActionType actionType, int cntTime) { Mockito.verify(tbClusterService, times(cntTime)).sendNotificationMsgToEdgeService(Mockito.eq(tenantId), - Mockito.isNull(), Mockito.eq(entityId), Mockito.isNull(), Mockito.isNull(), + Mockito.any(), Mockito.eq(entityId), Mockito.any(), Mockito.isNull(), Mockito.eq(edgeTypeByActionType(actionType))); } @@ -194,6 +169,112 @@ public abstract class AbstractNotifyEntityTest extends AbstractWebTest { Mockito.any(entityId.getClass()), Mockito.any(ComponentLifecycleEvent.class)); } + private void logEntityAction(HasName entity, EntityId originatorId, TenantId tenantId, + CustomerId customerId, UserId userId, String userName, + ActionType actionType, int cntTime, Object... additionalInfo) { + ArgumentMatcher matcherEntityEquals = argument -> argument.equals(entity); + ArgumentMatcher matcherOriginatorId = argument -> argument.equals(originatorId); + logEntityActionAdditionalInfo(matcherEntityEquals, matcherOriginatorId, tenantId, customerId, userId, userName, actionType, cntTime, additionalInfo); + } + + private void logEntityActionAdditionalInfo(ArgumentMatcher matcherEntity, ArgumentMatcher matcherOriginatorId, TenantId tenantId, + CustomerId customerId, UserId userId, String userName, + ActionType actionType, int cntTime, Object... additionalInfo) { + switch (additionalInfo.length) { + case 1: + Mockito.verify(auditLogService, times(cntTime)) + .logEntityAction(Mockito.eq(tenantId), + Mockito.eq(customerId), + Mockito.eq(userId), + Mockito.eq(userName), + Mockito.argThat(matcherOriginatorId), + Mockito.argThat(matcherEntity), + Mockito.eq(actionType), + Mockito.isNull(), + Mockito.eq(extractParameter(String.class, 0, additionalInfo))); + break; + case 2: + Mockito.verify(auditLogService, times(cntTime)) + .logEntityAction(Mockito.eq(tenantId), + Mockito.eq(customerId), + Mockito.eq(userId), + Mockito.eq(userName), + Mockito.argThat(matcherOriginatorId), + Mockito.argThat(matcherEntity), + Mockito.eq(actionType), + Mockito.isNull(), + Mockito.eq(extractParameter(String.class, 0, additionalInfo)), + Mockito.eq(extractParameter(String.class, 1, additionalInfo))); + break; + case 3: + Mockito.verify(auditLogService, times(cntTime)) + .logEntityAction(Mockito.eq(tenantId), + Mockito.eq(customerId), + Mockito.eq(userId), + Mockito.eq(userName), + Mockito.argThat(matcherOriginatorId), + Mockito.argThat(matcherEntity), + Mockito.eq(actionType), + Mockito.isNull(), + Mockito.eq(extractParameter(String.class, 0, additionalInfo)), + Mockito.eq(extractParameter(String.class, 1, additionalInfo)), + Mockito.eq(extractParameter(String.class, 2, additionalInfo))); + break; + default: + Mockito.verify(auditLogService, times(cntTime)) + .logEntityAction(Mockito.eq(tenantId), + Mockito.eq(customerId), + Mockito.eq(userId), + Mockito.eq(userName), + Mockito.argThat(matcherOriginatorId), + Mockito.argThat(matcherEntity), + Mockito.eq(actionType), + Mockito.isNull()); + } + } + + private void logEntityActionErrorAdditionalInfo(ArgumentMatcher matcherEntity, EntityId originatorId, TenantId tenantId, + CustomerId customerId, UserId userId, String userName, + ActionType actionType, int cntTime, ArgumentMatcher matcherError, Object... additionalInfo) { + switch (additionalInfo.length) { + case 1: + Mockito.verify(auditLogService, times(cntTime)) + .logEntityAction(Mockito.eq(tenantId), + Mockito.eq(customerId), + Mockito.eq(userId), + Mockito.eq(userName), + Mockito.eq(originatorId), + Mockito.argThat(matcherEntity), + Mockito.eq(actionType), + Mockito.argThat(matcherError), + Mockito.eq(extractParameter(String.class, 0, additionalInfo))); + break; + case 2: + Mockito.verify(auditLogService, times(cntTime)) + .logEntityAction(Mockito.eq(tenantId), + Mockito.eq(customerId), + Mockito.eq(userId), + Mockito.eq(userName), + Mockito.eq(originatorId), + Mockito.argThat(matcherEntity), + Mockito.eq(actionType), + Mockito.argThat(matcherError), + Mockito.eq(extractParameter(String.class, 0, additionalInfo)), + Mockito.eq(extractParameter(String.class, 1, additionalInfo))); + break; + default: + Mockito.verify(auditLogService, times(cntTime)) + .logEntityAction(Mockito.eq(tenantId), + Mockito.eq(customerId), + Mockito.eq(userId), + Mockito.eq(userName), + Mockito.eq(originatorId), + Mockito.argThat(matcherEntity), + Mockito.eq(actionType), + Mockito.argThat(matcherError)); + } + } + private T extractParameter(Class clazz, int index, Object... additionalInfo) { T result = null; if (additionalInfo != null && additionalInfo.length > index) { diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java index 0861ab34c8..0f8f2d11be 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java @@ -22,17 +22,20 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.service.stats.DefaultRuleEngineStatisticsService; @@ -83,8 +86,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { Asset asset = new Asset(); asset.setName("My asset"); asset.setType("default"); + + Mockito.reset(tbClusterService, auditLogService); + Asset savedAsset = doPost("/api/asset", asset, Asset.class); + testNotifyEntityOneTimeMsgToEdgeServiceNever(savedAsset, savedAsset.getId(), savedAsset.getId(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED); + Assert.assertNotNull(savedAsset); Assert.assertNotNull(savedAsset.getId()); Assert.assertTrue(savedAsset.getCreatedTime() > 0); @@ -93,9 +102,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { Assert.assertEquals(NULL_UUID, savedAsset.getCustomerId().getId()); Assert.assertEquals(asset.getName(), savedAsset.getName()); + Mockito.reset(tbClusterService, auditLogService); + savedAsset.setName("My new asset"); doPost("/api/asset", savedAsset, Asset.class); + testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED); + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class); Assert.assertEquals(foundAsset.getName(), savedAsset.getName()); } @@ -105,13 +119,33 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { Asset asset = new Asset(); asset.setName(RandomStringUtils.randomAlphabetic(300)); asset.setType("default"); - doPost("/api/asset", asset).andExpect(statusReason(containsString("length of name must be equal or less than 255"))); + + Mockito.reset(tbClusterService, auditLogService); + + String msgError = "length of name must be equal or less than 255"; + doPost("/api/asset", asset).andExpect(statusReason(containsString(msgError))); + + + testNotifyEntityEqualsOneTimeError(asset, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); + Mockito.reset(tbClusterService, auditLogService); + asset.setName("Normal name"); asset.setType(RandomStringUtils.randomAlphabetic(300)); - doPost("/api/asset", asset).andExpect(statusReason(containsString("length of type must be equal or less than 255"))); + msgError = "length of type must be equal or less than 255"; + doPost("/api/asset", asset).andExpect(statusReason(containsString(msgError))); + + testNotifyEntityEqualsOneTimeError(asset, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); + Mockito.reset(tbClusterService, auditLogService); + asset.setType("default"); asset.setLabel(RandomStringUtils.randomAlphabetic(300)); - doPost("/api/asset", asset).andExpect(statusReason(containsString("length of label must be equal or less than 255"))); + msgError = "length of label must be equal or less than 255"; + doPost("/api/asset", asset).andExpect(statusReason(containsString(msgError))); + + testNotifyEntityEqualsOneTimeError(asset, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); } @Test @@ -122,7 +156,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { Asset savedAsset = doPost("/api/asset", asset, Asset.class); loginDifferentTenant(); + + Mockito.reset(tbClusterService, auditLogService); + doPost("/api/asset", savedAsset, Asset.class, status().isForbidden()); + + testNotifyEntityNever(savedAsset.getId(), savedAsset); + deleteDifferentTenant(); } @@ -140,12 +180,21 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { @Test public void testFindAssetTypesByTenantId() throws Exception { List assets = new ArrayList<>(); - for (int i = 0; i < 3; i++) { + + Mockito.reset(tbClusterService, auditLogService); + + int cntTime = 3; + for (int i = 0; i < cntTime; i++) { Asset asset = new Asset(); asset.setName("My asset B" + i); asset.setType("typeB"); assets.add(doPost("/api/asset", asset, Asset.class)); } + + testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Asset(), new Asset(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.ADDED, cntTime); + for (int i = 0; i < 7; i++) { Asset asset = new Asset(); asset.setName("My asset C" + i); @@ -176,9 +225,15 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { asset.setType("default"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); + Mockito.reset(tbClusterService, auditLogService); + doDelete("/api/asset/" + savedAsset.getId().getId().toString()) .andExpect(status().isOk()); + testNotifyEntityOneTimeMsgToEdgeServiceNever(savedAsset, savedAsset.getId(), savedAsset.getId(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.DELETED, savedAsset.getId().getId().toString()); + doGet("/api/asset/" + savedAsset.getId().getId().toString()) .andExpect(status().isNotFound()); } @@ -202,9 +257,16 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { view.setType("default"); EntityView savedView = doPost("/api/entityView", view, EntityView.class); + Mockito.reset(tbClusterService, auditLogService); + doDelete("/api/asset/" + savedAsset1.getId().getId().toString()) .andExpect(status().isBadRequest()); + String msgError = "Can't delete asset that has entity views"; + + testNotifyEntityIsNullOneTimeError(savedAsset1, savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.DELETED, new DataValidationException(msgError), savedAsset1.getId().getId().toString()); + savedView.setEntityId(savedAsset2.getId()); doPost("/api/entityView", savedView, EntityView.class); @@ -220,18 +282,32 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { public void testSaveAssetWithEmptyType() throws Exception { Asset asset = new Asset(); asset.setName("My asset"); + + Mockito.reset(tbClusterService, auditLogService); + + String msgError = "Asset type should be specified"; doPost("/api/asset", asset) .andExpect(status().isBadRequest()) - .andExpect(statusReason(containsString("Asset type should be specified"))); + .andExpect(statusReason(containsString(msgError))); + + testNotifyEntityEqualsOneTimeError(asset, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); } @Test public void testSaveAssetWithEmptyName() throws Exception { Asset asset = new Asset(); asset.setType("default"); + + Mockito.reset(tbClusterService, auditLogService); + + String msgError = "Asset name should be specified"; doPost("/api/asset", asset) .andExpect(status().isBadRequest()) - .andExpect(statusReason(containsString("Asset name should be specified"))); + .andExpect(statusReason(containsString(msgError))); + + testNotifyEntityEqualsOneTimeError(asset, savedTenant.getId(), + tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); } @Test @@ -245,17 +321,29 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { customer.setTitle("My customer"); Customer savedCustomer = doPost("/api/customer", customer, Customer.class); + Mockito.reset(tbClusterService, auditLogService); + Asset assignedAsset = doPost("/api/customer/" + savedCustomer.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); Assert.assertEquals(savedCustomer.getId(), assignedAsset.getCustomerId()); + testNotifyEntityAllOneTime(assignedAsset, assignedAsset.getId(), assignedAsset.getId(), + savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.ASSIGNED_TO_CUSTOMER, savedCustomer.getId().toString(), savedCustomer.getTitle()); + Asset foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class); Assert.assertEquals(savedCustomer.getId(), foundAsset.getCustomerId()); + Mockito.reset(tbClusterService, auditLogService); + Asset unassignedAsset = doDelete("/api/customer/asset/" + savedAsset.getId().getId().toString(), Asset.class); Assert.assertEquals(ModelConstants.NULL_UUID, unassignedAsset.getCustomerId().getId()); + testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(), + savedTenant.getId(), savedCustomer.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.UNASSIGNED_FROM_CUSTOMER, savedCustomer.getId().toString(), savedCustomer.getTitle()); + foundAsset = doGet("/api/asset/" + savedAsset.getId().getId().toString(), Asset.class); Assert.assertEquals(ModelConstants.NULL_UUID, foundAsset.getCustomerId().getId()); } @@ -267,9 +355,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { asset.setType("default"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); + Mockito.reset(tbClusterService, auditLogService); + + String msgError = "Asset name should be specified"; doPost("/api/customer/" + Uuids.timeBased().toString() + "/asset/" + savedAsset.getId().getId().toString()) .andExpect(status().isNotFound()); + + testNotifyEntityNever(asset.getId(), asset); } @Test @@ -301,10 +394,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { asset.setType("default"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); + Mockito.reset(tbClusterService, auditLogService); + doPost("/api/customer/" + savedCustomer.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString()) .andExpect(status().isForbidden()); + testNotifyEntityNever(savedAsset.getId(), savedAsset); + loginSysAdmin(); doDelete("/api/tenant/" + savedTenant2.getId().getId().toString()) @@ -314,7 +411,11 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { @Test public void testFindTenantAssets() throws Exception { List assets = new ArrayList<>(); - for (int i = 0; i < 178; i++) { + int cntEntity = 178; + + Mockito.reset(tbClusterService, auditLogService); + + for (int i = 0; i < cntEntity; i++) { Asset asset = new Asset(); asset.setName("Asset" + i); asset.setType("default"); @@ -332,6 +433,10 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { } } while (pageData.hasNext()); + testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Asset(), new Asset(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.ADDED, cntEntity); + loadedAssets.removeIf(asset -> asset.getType().equals(DefaultRuleEngineStatisticsService.TB_SERVICE_QUEUE)); Collections.sort(assets, idComparator); @@ -731,17 +836,31 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { asset.setType("default"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); + Mockito.reset(tbClusterService, auditLogService); + doPost("/api/edge/" + savedEdge.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ASSIGNED_TO_EDGE, + savedAsset.getId().getId().toString(), savedEdge.getId().getId().toString(), edge.getName()); + + PageData pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/assets?", new TypeReference>() {}, new PageLink(100)); Assert.assertEquals(1, pageData.getData().size()); + Mockito.reset(tbClusterService, auditLogService); + doDelete("/api/edge/" + savedEdge.getId().getId().toString() + "/asset/" + savedAsset.getId().getId().toString(), Asset.class); + + testNotifyEntityAllOneTime(savedAsset, savedAsset.getId(), savedAsset.getId(), + savedTenant.getId(), tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), + ActionType.UNASSIGNED_FROM_EDGE, savedAsset.getId().getId().toString(), savedEdge.getId().getId().toString(), savedEdge.getName()); + pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/assets?", new TypeReference>() {}, new PageLink(100)); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java index cc4bc84b7b..1e2349985f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java @@ -129,7 +129,8 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest String msgError = "length of title must be equal or less than 255"; doPost("/api/customer", customer).andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + customer.setTenantId(savedTenant.getId()); + testNotifyEntityEqualsOneTimeError(customer,savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); Mockito.reset(tbClusterService, auditLogService); @@ -138,7 +139,7 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest msgError = "length of city must be equal or less than 255"; doPost("/api/customer", customer).andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + testNotifyEntityEqualsOneTimeError(customer,savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); Mockito.reset(tbClusterService, auditLogService); @@ -147,7 +148,7 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest msgError = "length of country must be equal or less than 255"; doPost("/api/customer", customer).andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + testNotifyEntityEqualsOneTimeError(customer,savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); Mockito.reset(tbClusterService, auditLogService); @@ -156,7 +157,7 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest msgError = "length of phone must be equal or less than 255"; doPost("/api/customer", customer).andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + testNotifyEntityEqualsOneTimeError(customer,savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); Mockito.reset(tbClusterService, auditLogService); @@ -165,7 +166,7 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest msgError = "length of state must be equal or less than 255"; doPost("/api/customer", customer).andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + testNotifyEntityEqualsOneTimeError(customer,savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); Mockito.reset(tbClusterService, auditLogService); @@ -174,7 +175,7 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest msgError = "length of zip or postal code must be equal or less than 255"; doPost("/api/customer", customer).andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + testNotifyEntityEqualsOneTimeError(customer,savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); } @@ -248,7 +249,7 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest .andExpect(status().isBadRequest()) .andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + testNotifyEntityEqualsOneTimeError(customer,savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); } @@ -265,7 +266,7 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest .andExpect(status().isBadRequest()) .andExpect(statusReason(containsString(msgError))); - testNotifyEntityOneTimeError(customer, savedTenant.getId(), + testNotifyEntityEqualsOneTimeError(customer, savedTenant.getId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED, new DataValidationException(msgError)); } @@ -273,12 +274,12 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest public void testFindCustomers() throws Exception { TenantId tenantId = savedTenant.getId(); - int cntTime = 135; + int cntEntity = 135; Mockito.reset(tbClusterService, auditLogService); - List> futures = new ArrayList<>(cntTime); - for (int i = 0; i < cntTime; i++) { + List> futures = new ArrayList<>(cntEntity); + for (int i = 0; i < cntEntity; i++) { Customer customer = new Customer(); customer.setTenantId(tenantId); customer.setTitle("Customer" + i); @@ -287,9 +288,9 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest } List customers = Futures.allAsList(futures).get(TIMEOUT, TimeUnit.SECONDS); - testNotifyEntityManyTimeMsgToEdgeServiceNever(new Customer(), new Customer(), + testNotifyManyEntityManyTimeMsgToEdgeServiceNever(new Customer(), new Customer(), tenantId, tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), - ActionType.ADDED, cntTime); + ActionType.ADDED, cntEntity); List loadedCustomers = new ArrayList<>(135); PageLink pageLink = new PageLink(23);