+108
@@ -0,0 +1,108 @@
|
||||
package com.nanri.aiimage.modules.invalidasin.controller;
|
||||
|
||||
import com.nanri.aiimage.common.exception.BusinessException;
|
||||
import com.nanri.aiimage.modules.admin.support.AdminAuthSupport;
|
||||
import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataPageVo;
|
||||
import com.nanri.aiimage.modules.invalidasin.service.InvalidAsinDataService;
|
||||
import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity;
|
||||
import com.nanri.aiimage.modules.permission.model.vo.PermissionMenuItemVo;
|
||||
import com.nanri.aiimage.modules.permission.service.PermissionMenuService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class InvalidAsinDataControllerTest {
|
||||
|
||||
@Mock
|
||||
private InvalidAsinDataService invalidAsinDataService;
|
||||
@Mock
|
||||
private AdminAuthSupport adminAuthSupport;
|
||||
@Mock
|
||||
private PermissionMenuService permissionMenuService;
|
||||
@InjectMocks
|
||||
private InvalidAsinDataController controller;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ReflectionTestUtils.setField(controller, "internalToken", "test-internal-token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void trustedFlaskProxyUsesTheDatabaseUserInsteadOfRequestRole() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("X-Internal-Token", "test-internal-token");
|
||||
request.addParameter("operatorId", "7");
|
||||
request.addParameter("superAdmin", "true");
|
||||
AdminUserEntity operator = user(7L, "normal");
|
||||
when(adminAuthSupport.requireUser(request)).thenThrow(new BusinessException(401, "未登录"));
|
||||
when(permissionMenuService.requireUserOperator(7L)).thenReturn(operator);
|
||||
when(adminAuthSupport.currentRole(operator)).thenReturn(null);
|
||||
when(permissionMenuService.getUserColumnPermissions(7L, "admin"))
|
||||
.thenReturn(List.of(invalidAsinDataPermission()));
|
||||
when(invalidAsinDataService.page(1L, 15L, "", 3L, 7L, false))
|
||||
.thenReturn(new InvalidAsinDataPageVo());
|
||||
|
||||
controller.page(1L, 15L, "", 3L, request);
|
||||
|
||||
verify(invalidAsinDataService).page(1L, 15L, "", 3L, 7L, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void directRequestCannotForgeSuperAdminWithoutTrustedAuthentication() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("operatorId", "1");
|
||||
request.addParameter("superAdmin", "true");
|
||||
when(adminAuthSupport.requireUser(request)).thenThrow(new BusinessException(401, "未登录"));
|
||||
|
||||
assertThrows(BusinessException.class, () -> controller.page(1L, 15L, "", 3L, request));
|
||||
|
||||
verifyNoInteractions(invalidAsinDataService);
|
||||
verify(permissionMenuService, never()).requireUserOperator(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticatedSuperAdminRoleComesFromTheServerUser() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("superAdmin", "false");
|
||||
AdminUserEntity operator = user(1L, "super_admin");
|
||||
when(adminAuthSupport.requireUser(request)).thenReturn(operator);
|
||||
when(adminAuthSupport.currentRole(operator)).thenReturn("super_admin");
|
||||
when(invalidAsinDataService.page(1L, 15L, "", 3L, 1L, true))
|
||||
.thenReturn(new InvalidAsinDataPageVo());
|
||||
|
||||
controller.page(1L, 15L, "", 3L, request);
|
||||
|
||||
verify(invalidAsinDataService).page(1L, 15L, "", 3L, 1L, true);
|
||||
verify(permissionMenuService, never()).getUserColumnPermissions(eq(1L), eq("admin"));
|
||||
}
|
||||
|
||||
private AdminUserEntity user(Long id, String role) {
|
||||
AdminUserEntity user = new AdminUserEntity();
|
||||
user.setId(id);
|
||||
user.setRole(role);
|
||||
return user;
|
||||
}
|
||||
|
||||
private PermissionMenuItemVo invalidAsinDataPermission() {
|
||||
PermissionMenuItemVo permission = new PermissionMenuItemVo();
|
||||
permission.setColumnKey("admin_invalid_asin_data");
|
||||
permission.setRoutePath("invalid-asin-data");
|
||||
return permission;
|
||||
}
|
||||
}
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
package com.nanri.aiimage.modules.invalidasin.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import com.nanri.aiimage.common.exception.BusinessException;
|
||||
import com.nanri.aiimage.modules.invalidasin.mapper.InvalidAsinDataMapper;
|
||||
import com.nanri.aiimage.modules.invalidasin.model.dto.InvalidAsinDataCreateRequest;
|
||||
import com.nanri.aiimage.modules.invalidasin.model.dto.InvalidAsinDataUpdateRequest;
|
||||
import com.nanri.aiimage.modules.invalidasin.model.entity.InvalidAsinDataEntity;
|
||||
import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataItemVo;
|
||||
import com.nanri.aiimage.modules.invalidasin.model.vo.InvalidAsinDataPageVo;
|
||||
import com.nanri.aiimage.modules.shopkey.model.entity.ShopManageGroupEntity;
|
||||
import com.nanri.aiimage.modules.shopkey.service.ShopManageGroupService;
|
||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
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.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class InvalidAsinDataServiceTest {
|
||||
|
||||
@Mock
|
||||
private InvalidAsinDataMapper invalidAsinDataMapper;
|
||||
@Mock
|
||||
private ShopManageGroupService shopManageGroupService;
|
||||
@InjectMocks
|
||||
private InvalidAsinDataService service;
|
||||
|
||||
@Test
|
||||
void createManualRecordUsesAccessibleGroup() {
|
||||
InvalidAsinDataCreateRequest request = new InvalidAsinDataCreateRequest();
|
||||
request.setDataValue("B012345678");
|
||||
request.setBrand("Acme");
|
||||
request.setGroupId(9L);
|
||||
ShopManageGroupEntity group = group(9L, "group-a");
|
||||
InvalidAsinDataEntity saved = data(91L, "MANUAL", 9L);
|
||||
|
||||
when(shopManageGroupService.listAccessibleGroupIds(7L, false)).thenReturn(Set.of(12L, 9L));
|
||||
when(shopManageGroupService.getAccessibleById(9L, 7L, false)).thenReturn(group);
|
||||
when(invalidAsinDataMapper.selectOne(any())).thenReturn(null);
|
||||
when(invalidAsinDataMapper.insert(any(InvalidAsinDataEntity.class))).thenAnswer(invocation -> {
|
||||
invocation.getArgument(0, InvalidAsinDataEntity.class).setId(91L);
|
||||
return 1;
|
||||
});
|
||||
when(invalidAsinDataMapper.selectById(91L)).thenReturn(saved);
|
||||
|
||||
InvalidAsinDataItemVo item = service.create(request, 7L, false);
|
||||
|
||||
ArgumentCaptor<InvalidAsinDataEntity> captor = ArgumentCaptor.forClass(InvalidAsinDataEntity.class);
|
||||
verify(invalidAsinDataMapper).insert(captor.capture());
|
||||
assertEquals("B012345678", captor.getValue().getDataValue());
|
||||
assertEquals("acme", captor.getValue().getBrand());
|
||||
assertEquals(9L, captor.getValue().getGroupId());
|
||||
assertEquals("MANUAL", captor.getValue().getRecordSource());
|
||||
assertEquals("group-a", item.getGroupName());
|
||||
assertEquals("MANUAL", item.getRecordSource());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
void normalUserPageOnlyQueriesManualRowsInAccessibleGroups() {
|
||||
InvalidAsinDataEntity manual = data(91L, "MANUAL", 9L);
|
||||
when(shopManageGroupService.listAccessibleGroupIds(7L, false)).thenReturn(Set.of(10L, 9L));
|
||||
when(invalidAsinDataMapper.selectCount(any())).thenReturn(1L);
|
||||
when(invalidAsinDataMapper.selectList(any())).thenReturn(List.of(manual));
|
||||
when(shopManageGroupService.buildGroupNameMap(any())).thenReturn(Map.of(9L, "group-a"));
|
||||
|
||||
InvalidAsinDataPageVo page = service.page(1, 15, "", 10L, 7L, false);
|
||||
|
||||
ArgumentCaptor<LambdaQueryWrapper<InvalidAsinDataEntity>> captor = ArgumentCaptor.forClass((Class) LambdaQueryWrapper.class);
|
||||
verify(invalidAsinDataMapper).selectCount(captor.capture());
|
||||
TableInfoHelper.initTableInfo(
|
||||
new MapperBuilderAssistant(new MybatisConfiguration(), ""),
|
||||
InvalidAsinDataEntity.class);
|
||||
String sql = captor.getValue().getSqlSegment();
|
||||
assertTrue(sql.contains("record_source"));
|
||||
assertTrue(sql.contains("group_id"));
|
||||
assertTrue(captor.getValue().getParamNameValuePairs().containsValue("MANUAL"));
|
||||
assertTrue(captor.getValue().getParamNameValuePairs().containsValue(9L));
|
||||
assertFalse(captor.getValue().getParamNameValuePairs().containsValue(10L));
|
||||
assertEquals("group-a", page.getItems().getFirst().getGroupName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void superAdminPageHandlesRowsWithoutResolvableGroup() {
|
||||
InvalidAsinDataEntity automatic = data(92L, "AUTO", null);
|
||||
InvalidAsinDataEntity orphan = data(93L, "MANUAL", 999L);
|
||||
when(invalidAsinDataMapper.selectCount(any())).thenReturn(1L);
|
||||
when(invalidAsinDataMapper.selectList(any())).thenReturn(List.of(automatic, orphan));
|
||||
when(shopManageGroupService.buildGroupNameMap(any())).thenReturn(Map.of());
|
||||
|
||||
InvalidAsinDataPageVo page = service.page(1, 15, "", null, 1L, true);
|
||||
|
||||
assertEquals(2, page.getItems().size());
|
||||
assertEquals("AUTO", page.getItems().getFirst().getRecordSource());
|
||||
assertEquals("", page.getItems().getFirst().getGroupName());
|
||||
assertEquals("", page.getItems().get(1).getGroupName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
void superAdminPageFiltersByRequestedGroup() {
|
||||
when(invalidAsinDataMapper.selectCount(any())).thenReturn(0L);
|
||||
when(invalidAsinDataMapper.selectList(any())).thenReturn(List.of());
|
||||
|
||||
service.page(1, 15, "", 9L, 1L, true);
|
||||
|
||||
ArgumentCaptor<LambdaQueryWrapper<InvalidAsinDataEntity>> captor = ArgumentCaptor.forClass((Class) LambdaQueryWrapper.class);
|
||||
verify(invalidAsinDataMapper).selectCount(captor.capture());
|
||||
TableInfoHelper.initTableInfo(
|
||||
new MapperBuilderAssistant(new MybatisConfiguration(), ""),
|
||||
InvalidAsinDataEntity.class);
|
||||
assertTrue(captor.getValue().getSqlSegment().contains("group_id"));
|
||||
assertTrue(captor.getValue().getParamNameValuePairs().containsValue(9L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalUserCannotDeleteAutoRecord() {
|
||||
when(invalidAsinDataMapper.selectById(91L)).thenReturn(data(91L, "AUTO", null));
|
||||
|
||||
ResponseStatusException exception = assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> service.delete(91L, 7L, false));
|
||||
|
||||
assertEquals(403, exception.getStatusCode().value());
|
||||
verify(invalidAsinDataMapper, never()).deleteById(any(Long.class));
|
||||
verifyNoInteractions(shopManageGroupService);
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalUserCannotUpdateIntoAnotherAccessibleGroup() {
|
||||
InvalidAsinDataEntity record = data(91L, "MANUAL", 9L);
|
||||
InvalidAsinDataUpdateRequest request = new InvalidAsinDataUpdateRequest();
|
||||
request.setDataValue("B012345678");
|
||||
request.setBrand("New Brand");
|
||||
request.setGroupId(10L);
|
||||
when(invalidAsinDataMapper.selectById(91L)).thenReturn(record);
|
||||
when(shopManageGroupService.listAccessibleGroupIds(7L, false)).thenReturn(Set.of(10L, 9L));
|
||||
when(shopManageGroupService.getAccessibleById(9L, 7L, false)).thenReturn(group(9L, "group-a"));
|
||||
|
||||
ResponseStatusException exception = assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> service.update(91L, request, 7L, false));
|
||||
|
||||
assertEquals(403, exception.getStatusCode().value());
|
||||
assertEquals(9L, record.getGroupId());
|
||||
assertEquals("acme", record.getBrand());
|
||||
verify(invalidAsinDataMapper, never()).updateById(any(InvalidAsinDataEntity.class));
|
||||
verify(shopManageGroupService, never()).getAccessibleById(10L, 7L, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalUserCannotCreateInAnotherAccessibleGroup() {
|
||||
InvalidAsinDataCreateRequest request = new InvalidAsinDataCreateRequest();
|
||||
request.setDataValue("B012345678");
|
||||
request.setBrand("Acme");
|
||||
request.setGroupId(10L);
|
||||
when(shopManageGroupService.listAccessibleGroupIds(7L, false)).thenReturn(Set.of(10L, 9L));
|
||||
|
||||
ResponseStatusException exception = assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> service.create(request, 7L, false));
|
||||
|
||||
assertEquals(403, exception.getStatusCode().value());
|
||||
verify(invalidAsinDataMapper, never()).insert(any(InvalidAsinDataEntity.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalUserCannotDeleteRecordOutsideFixedGroup() {
|
||||
InvalidAsinDataEntity record = data(91L, "MANUAL", 10L);
|
||||
when(invalidAsinDataMapper.selectById(91L)).thenReturn(record);
|
||||
when(shopManageGroupService.listAccessibleGroupIds(7L, false)).thenReturn(Set.of(10L, 9L));
|
||||
|
||||
ResponseStatusException exception = assertThrows(
|
||||
ResponseStatusException.class,
|
||||
() -> service.delete(91L, 7L, false));
|
||||
|
||||
assertEquals(403, exception.getStatusCode().value());
|
||||
verify(invalidAsinDataMapper, never()).deleteById(any(Long.class));
|
||||
verify(shopManageGroupService, never()).getAccessibleById(any(Long.class), any(Long.class), org.mockito.ArgumentMatchers.eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalUserCreateRequiresAtLeastOneAccessibleGroup() {
|
||||
InvalidAsinDataCreateRequest request = new InvalidAsinDataCreateRequest();
|
||||
request.setDataValue("B012345678");
|
||||
request.setBrand("Acme");
|
||||
request.setGroupId(9L);
|
||||
when(shopManageGroupService.listAccessibleGroupIds(7L, false)).thenReturn(Set.of());
|
||||
|
||||
assertThrows(BusinessException.class, () -> service.create(request, 7L, false));
|
||||
|
||||
verify(invalidAsinDataMapper, never()).insert(any(InvalidAsinDataEntity.class));
|
||||
verify(shopManageGroupService, never()).getAccessibleById(any(Long.class), any(Long.class), org.mockito.ArgumentMatchers.eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void superAdminCanUpdateAutoRecordWithoutGroup() {
|
||||
InvalidAsinDataEntity record = data(91L, "AUTO", null);
|
||||
InvalidAsinDataUpdateRequest request = new InvalidAsinDataUpdateRequest();
|
||||
request.setDataValue("B012345678");
|
||||
request.setBrand("New Brand");
|
||||
when(invalidAsinDataMapper.selectById(91L)).thenReturn(record);
|
||||
when(invalidAsinDataMapper.selectOne(any())).thenReturn(null);
|
||||
|
||||
InvalidAsinDataItemVo item = service.update(91L, request, 1L, true);
|
||||
|
||||
assertEquals("AUTO", item.getRecordSource());
|
||||
assertNull(record.getGroupId());
|
||||
verify(invalidAsinDataMapper).updateById(record);
|
||||
verifyNoInteractions(shopManageGroupService);
|
||||
}
|
||||
|
||||
private ShopManageGroupEntity group(Long id, String groupName) {
|
||||
ShopManageGroupEntity group = new ShopManageGroupEntity();
|
||||
group.setId(id);
|
||||
group.setGroupName(groupName);
|
||||
return group;
|
||||
}
|
||||
|
||||
private InvalidAsinDataEntity data(Long id, String source, Long groupId) {
|
||||
InvalidAsinDataEntity entity = new InvalidAsinDataEntity();
|
||||
entity.setId(id);
|
||||
entity.setDataValue("B012345678");
|
||||
entity.setBrand("acme");
|
||||
entity.setGroupId(groupId);
|
||||
entity.setRecordSource(source);
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user