|
|
@@ -0,0 +1,162 @@
|
|
|
+package com.etotem.cfc.config;
|
|
|
+
|
|
|
+import com.etotem.cfc.entity.User;
|
|
|
+import com.etotem.cfc.service.UserService;
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+import org.mockito.InjectMocks;
|
|
|
+import org.mockito.Mock;
|
|
|
+import org.mockito.junit.jupiter.MockitoExtension;
|
|
|
+import org.mockito.MockitoAnnotations;
|
|
|
+import org.junit.jupiter.api.extension.ExtendWith;
|
|
|
+
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.Set;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.*;
|
|
|
+import static org.mockito.Mockito.*;
|
|
|
+
|
|
|
+@ExtendWith(MockitoExtension.class)
|
|
|
+public class FamilyAccessInterceptorTest {
|
|
|
+
|
|
|
+ @Mock
|
|
|
+ private UserService userService;
|
|
|
+
|
|
|
+ @InjectMocks
|
|
|
+ private FamilyAccessInterceptor familyAccessInterceptor;
|
|
|
+
|
|
|
+ private HttpServletResponse response;
|
|
|
+
|
|
|
+ @BeforeEach
|
|
|
+ public void setUp() {
|
|
|
+ MockitoAnnotations.openMocks(this);
|
|
|
+ response = mock(HttpServletResponse.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testChildAccessValid() {
|
|
|
+ Long userId = 1L;
|
|
|
+ Long familyId = 1L;
|
|
|
+ User user = createMockUser(userId, familyId, "child");
|
|
|
+ when(userService.getEffectiveFamilyIds(userId)).thenReturn(Collections.singleton(familyId));
|
|
|
+
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ request.setMethod("POST");
|
|
|
+ request.setRequestURI("/api/dan-assessment/materials");
|
|
|
+ request.setParameter("familyId", familyId.toString());
|
|
|
+ request.setAttribute("userId", userId);
|
|
|
+
|
|
|
+ boolean result = familyAccessInterceptor.preHandle(request, response, null);
|
|
|
+ assertTrue(result);
|
|
|
+ // 验证没有调用参数抛出 403
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testChildAccessInvalid() {
|
|
|
+ Long userId = 1L;
|
|
|
+ Long userFamilyId = 1L;
|
|
|
+ Long requestedFamilyId = 2L;
|
|
|
+ User user = createMockUser(userId, userFamilyId, "child");
|
|
|
+ when(userService.getEffectiveFamilyIds(userId)).thenReturn(Collections.singleton(userFamilyId));
|
|
|
+
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ request.setMethod("POST");
|
|
|
+ request.setRequestURI("/api/dan-assessment/materials");
|
|
|
+ request.setParameter("familyId", requestedFamilyId.toString());
|
|
|
+ request.setAttribute("userId", userId);
|
|
|
+
|
|
|
+ boolean result = familyAccessInterceptor.preHandle(request, response, null);
|
|
|
+ assertFalse(result);
|
|
|
+ // 验证发送了 403 响应
|
|
|
+ verify(response).setStatus(HttpServletResponse.SC_FORBIDDEN);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testTeacherAccessValid() {
|
|
|
+ Long userId = 2L;
|
|
|
+ Long teacherFamilyId = 5L;
|
|
|
+ Long assignedFamilyId = 5L;
|
|
|
+ User user = createMockUser(userId, teacherFamilyId, "teacher");
|
|
|
+ when(userService.getEffectiveFamilyIds(userId)).thenReturn(Collections.singleton(assignedFamilyId));
|
|
|
+
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ request.setMethod("POST");
|
|
|
+ request.setRequestURI("/api/dan-assessment/materials");
|
|
|
+ request.setParameter("familyId", assignedFamilyId.toString());
|
|
|
+ request.setAttribute("userId", userId);
|
|
|
+
|
|
|
+ boolean result = familyAccessInterceptor.preHandle(request, response, null);
|
|
|
+ assertTrue(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testMissingFamilyId() {
|
|
|
+ Long userId = 1L;
|
|
|
+ Long familyId = 1L;
|
|
|
+ User user = createMockUser(userId, familyId, "child");
|
|
|
+ when(userService.getEffectiveFamilyIds(userId)).thenReturn(Collections.singleton(familyId));
|
|
|
+
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ request.setMethod("POST");
|
|
|
+ request.setRequestURI("/api/dan-assessment/materials");
|
|
|
+ // 不设置 familyId 则返回 true
|
|
|
+ request.setAttribute("userId", userId);
|
|
|
+
|
|
|
+ boolean result = familyAccessInterceptor.preHandle(request, response, null);
|
|
|
+ assertTrue(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testAdminPath() {
|
|
|
+ Long userId = 1L;
|
|
|
+ User user = createMockUser(userId, 1L, "admin");
|
|
|
+ when(userService.getEffectiveFamilyIds(userId)).thenReturn(Collections.singleton(1L));
|
|
|
+
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ request.setMethod("POST");
|
|
|
+ request.setRequestURI("/api/admin/users");
|
|
|
+ // 任何 familyId 都不应该被拒绝,因为 admin path 会被跳过
|
|
|
+ request.setParameter("familyId", "999"); // 不存在的 familyId
|
|
|
+ request.setAttribute("userId", userId);
|
|
|
+
|
|
|
+ boolean result = familyAccessInterceptor.preHandle(request, response, null);
|
|
|
+ assertTrue(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testNoUserId() {
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ request.setMethod("POST");
|
|
|
+ request.setRequestURI("/api/dan-assessment/materials");
|
|
|
+ request.setParameter("familyId", "1");
|
|
|
+ request.setAttribute("userId", null); // 没有 userId
|
|
|
+
|
|
|
+ boolean result = familyAccessInterceptor.preHandle(request, response, null);
|
|
|
+ assertTrue(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testEmptyEffectiveFamilyIds() {
|
|
|
+ Long userId = 1L;
|
|
|
+ User user = createMockUser(userId, null, "parent");
|
|
|
+ when(userService.getEffectiveFamilyIds(userId)).thenReturn(Collections.emptySet());
|
|
|
+
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ request.setMethod("POST");
|
|
|
+ request.setRequestURI("/api/dan-assessment/materials");
|
|
|
+ request.setParameter("familyId", "1");
|
|
|
+ request.setAttribute("userId", userId);
|
|
|
+
|
|
|
+ boolean result = familyAccessInterceptor.preHandle(request, response, null);
|
|
|
+ assertTrue(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ private User createMockUser(Long userId, Long familyId, String role) {
|
|
|
+ User user = new User();
|
|
|
+ user.setId(userId);
|
|
|
+ user.setFamilyId(familyId);
|
|
|
+ user.setTeacherFamilyIds(null);
|
|
|
+ return user;
|
|
|
+ }
|
|
|
+}
|