diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index fd91abed3a..26e61a495a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmQuery; @@ -47,6 +48,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.alarm.TbAlarmService; import org.thingsboard.server.service.security.model.SecurityUser; +import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; @@ -204,12 +206,13 @@ public class AlarmController extends BaseController { AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); UserId assigneeId = new UserId(UUID.fromString(strAssigneeId)); Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); - if (!getCurrentUser().getId().equals(assigneeId)) { - try { - checkEntityId(alarm.getOriginator(), Operation.WRITE, new SecurityUser(assigneeId)); - } catch (Exception e) { - throw new ThingsboardException("Assignee user doesn't have permission for alarm originator", ThingsboardErrorCode.PERMISSION_DENIED); - } + User assigneeUser = userService.findUserById(getTenantId(), assigneeId); + + SecurityUser assigneeSecurityUser = new SecurityUser(assigneeUser, false, null); + try { + checkEntityId(alarm.getOriginator(), Operation.WRITE, assigneeSecurityUser); + } catch (Exception e) { + throw new ThingsboardException("Assignee user doesn't have permission for alarm originator", ThingsboardErrorCode.PERMISSION_DENIED); } tbAlarmService.assign(alarm, getCurrentUser(), assigneeId).get(); } diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index 9ea269918e..e94a0646d9 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -154,6 +154,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { protected TenantId differentTenantId; protected CustomerId differentCustomerId; protected UserId customerUserId; + protected UserId differentCustomerUserId; @SuppressWarnings("rawtypes") private HttpMessageConverter mappingJackson2HttpMessageConverter; @@ -324,7 +325,8 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { differentCustomerUser.setCustomerId(savedDifferentCustomer.getId()); differentCustomerUser.setEmail(DIFFERENT_CUSTOMER_USER_EMAIL); - createUserAndLogin(differentCustomerUser, DIFFERENT_CUSTOMER_USER_PASSWORD); + differentCustomerUser = createUserAndLogin(differentCustomerUser, DIFFERENT_CUSTOMER_USER_PASSWORD); + differentCustomerUserId = differentCustomerUser.getId(); } } diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java index 05b6f15c61..cc793d8984 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java @@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.ResultActions; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; @@ -364,6 +365,18 @@ public abstract class BaseAlarmControllerTest extends AbstractControllerTest { tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_ASSIGN); } + @Test + public void testAssignAlarmViaDifferentTenant() throws Exception { + loginTenantAdmin(); + Alarm alarm = createAlarm(TEST_ALARM_TYPE); + + loginDifferentTenant(); + + Mockito.reset(tbClusterService, auditLogService); + + doPost("/api/alarm/" + alarm.getId() + "/assign/" + tenantAdminUserId.getId()).andExpect(status().isForbidden()); + } + @Test public void testReassignAlarm() throws Exception { loginTenantAdmin(); @@ -426,6 +439,38 @@ public abstract class BaseAlarmControllerTest extends AbstractControllerTest { tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_UNASSIGN); } + @Test + public void testUnassignTenantAlarmViaCustomer() throws Exception { + loginTenantAdmin(); + Alarm alarm = createAlarm(TEST_ALARM_TYPE); + Mockito.reset(tbClusterService, auditLogService); + long beforeAssignmentTs = System.currentTimeMillis(); + + doPost("/api/alarm/" + alarm.getId() + "/assign/" + tenantAdminUserId.getId()).andExpect(status().isOk()); + Alarm foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class); + Assert.assertNotNull(foundAlarm); + Assert.assertEquals(tenantAdminUserId, foundAlarm.getAssigneeId()); + Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs && foundAlarm.getAssignTs() < System.currentTimeMillis()); + + testNotifyEntityAllOneTime(foundAlarm, foundAlarm.getId(), foundAlarm.getOriginator(), + tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_ASSIGN); + + logout(); + loginCustomerUser(); + + Mockito.reset(tbClusterService, auditLogService); + beforeAssignmentTs = System.currentTimeMillis(); + + doDelete("/api/alarm/" + alarm.getId() + "/assign").andExpect(status().isOk()); + foundAlarm = doGet("/api/alarm/" + alarm.getId(), Alarm.class); + Assert.assertNotNull(foundAlarm); + Assert.assertNull(foundAlarm.getAssigneeId()); + Assert.assertTrue(foundAlarm.getAssignTs() > beforeAssignmentTs && foundAlarm.getAssignTs() < System.currentTimeMillis()); + + testNotifyEntityAllOneTime(foundAlarm, foundAlarm.getId(), foundAlarm.getOriginator(), + tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ALARM_UNASSIGN); + } + @Test public void testFindAlarmsViaCustomerUser() throws Exception { loginCustomerUser();