处理后台新需求
Build Backend JAR / build (push) Failing after 16m58s

This commit is contained in:
supernijia
2026-08-09 20:08:39 +08:00
parent f7e26ee266
commit 38216a1885
42 changed files with 3425 additions and 424 deletions
@@ -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;
}
}
@@ -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;
}
}