report_update

Change-Id: Ic98394db54f5aa263ec07b75d1ccca9f1d6f6cd0
diff --git a/src/main/java/com/example/g8backend/controller/AdminController.java b/src/main/java/com/example/g8backend/controller/AdminController.java
index 89208c6..64a0f01 100644
--- a/src/main/java/com/example/g8backend/controller/AdminController.java
+++ b/src/main/java/com/example/g8backend/controller/AdminController.java
@@ -1,23 +1,46 @@
 package com.example.g8backend.controller;
 
+import com.example.g8backend.dto.ApiResponse;
+import com.example.g8backend.entity.Report;
 import com.example.g8backend.service.AdminService;
+import com.example.g8backend.service.IReportService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
 
 @RestController
 @RequestMapping("/admin")
 public class AdminController {
     @Autowired
     private AdminService adminService;
-
+    private IReportService reportService;
     @PostMapping("/grant-vip/{userId}")
     @PreAuthorize("hasRole('ADMIN')") // 仅允许管理员访问
     public String grantVip(@PathVariable Long userId) {
         boolean success = adminService.grantVip(userId);
         return success ? "VIP授予成功" : "操作失败(用户不存在)";
     }
+    // 获取举报记录(支持按状态过滤)
+    @GetMapping("/reports")
+    @PreAuthorize("hasRole('ADMIN')")
+    public ApiResponse<List<Report>> getReports(
+            @RequestParam(required = false) String status) {
+        // 从安全上下文自动获取管理员ID
+        Long adminId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        return ApiResponse.success(reportService.getReports(status, adminId));
+    }
+    // 处理举报
+    @PutMapping("/reports/{reportId}")
+    @PreAuthorize("hasRole('ADMIN')")
+    public ApiResponse<String> resolveReport(
+            @PathVariable Long reportId,
+            @RequestParam String status,
+            @RequestParam(required = false) String notes) {
+        reportService.resolveReport(reportId, null, status, notes); // adminId在服务层自动获取
+        return ApiResponse.success("举报处理完成");
+    }
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/example/g8backend/controller/PostController.java b/src/main/java/com/example/g8backend/controller/PostController.java
index 1e0adf4..6800666 100644
--- a/src/main/java/com/example/g8backend/controller/PostController.java
+++ b/src/main/java/com/example/g8backend/controller/PostController.java
@@ -209,28 +209,4 @@
         }
     }
 
-
-    @GetMapping("/reports")
-    public ResponseEntity<ApiResponse<List<Report>>> getReports(
-            @RequestParam(required = false) String status) {
-        List<Report> reports = reportService.getReports(status);
-        return ResponseEntity.ok(ApiResponse.success(reports));
-    }
-
-    @PutMapping("/report/{reportId}")
-    public ResponseEntity<ApiResponse<String>> resolveReport(
-            @PathVariable Long reportId,
-            @RequestParam Long adminId,     // 实际部署时可从 token 解析或改为登录信息中获取
-            @RequestParam String status,
-            @RequestParam(required = false) String notes) {
-        try {
-            reportService.resolveReport(reportId, adminId, status, notes);
-            return ResponseEntity.ok(ApiResponse.message("举报处理完成"));
-        } catch (IllegalArgumentException e) {
-            return ResponseEntity.badRequest().body(ApiResponse.error(400, e.getMessage()));
-        }
-    }
-
-
-
 }
diff --git a/src/main/java/com/example/g8backend/service/IReportService.java b/src/main/java/com/example/g8backend/service/IReportService.java
index c1cf775..5c67fa8 100644
--- a/src/main/java/com/example/g8backend/service/IReportService.java
+++ b/src/main/java/com/example/g8backend/service/IReportService.java
@@ -11,5 +11,5 @@
     boolean resolveReport(Long reportId, Long adminUserId, String status, String notes);
 
     // 获取举报列表(按状态过滤)
-    List<Report> getReports(String status);
+    List<Report> getReports(String status,Long requesterUserId);
 }
\ No newline at end of file
diff --git a/src/main/java/com/example/g8backend/service/impl/ReportServiceImpl.java b/src/main/java/com/example/g8backend/service/impl/ReportServiceImpl.java
index f27de25..a4d5c1a 100644
--- a/src/main/java/com/example/g8backend/service/impl/ReportServiceImpl.java
+++ b/src/main/java/com/example/g8backend/service/impl/ReportServiceImpl.java
@@ -2,9 +2,12 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.example.g8backend.entity.Report;
+import com.example.g8backend.entity.User;
 import com.example.g8backend.mapper.ReportMapper;
+import com.example.g8backend.mapper.UserMapper;
 import com.example.g8backend.service.IReportService;
 import lombok.RequiredArgsConstructor;
+import org.springframework.security.access.AccessDeniedException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import java.time.LocalDateTime;
@@ -14,6 +17,7 @@
 @RequiredArgsConstructor
 public class ReportServiceImpl implements IReportService {
     private final ReportMapper reportMapper;
+    private final UserMapper userMapper; // 新增 UserMapper 用于获取用户角色
 
     @Override
     @Transactional
@@ -42,6 +46,11 @@
     @Override
     @Transactional
     public boolean resolveReport(Long reportId, Long adminUserId, String status, String notes) {
+        User adminUser = userMapper.selectById(adminUserId);
+        if (adminUser == null || !"ADMIN".equals(adminUser.getRole())) {
+            throw new AccessDeniedException("无权执行此操作:非管理员用户");
+        }
+
         Report report = reportMapper.selectById(reportId);
         if (report == null) {
             throw new IllegalArgumentException("举报记录不存在");
@@ -54,11 +63,13 @@
     }
 
     @Override
-    public List<Report> getReports(String status) {
+    public List<Report> getReports(String status, Long requesterUserId) {
+        User requester = userMapper.selectById(requesterUserId);
+        if (requester == null || !"ADMIN".equals(requester.getRole())) {
+            throw new AccessDeniedException("无权查看举报记录:非管理员用户");
+        }
         return reportMapper.selectList(
                 new QueryWrapper<Report>().eq("status", status)
         );
     }
-
-
 }
\ No newline at end of file
diff --git a/src/test/java/com/example/g8backend/service/ReportServiceImplTest.java b/src/test/java/com/example/g8backend/service/ReportServiceImplTest.java
index acd2730..8b59f82 100644
--- a/src/test/java/com/example/g8backend/service/ReportServiceImplTest.java
+++ b/src/test/java/com/example/g8backend/service/ReportServiceImplTest.java
@@ -2,112 +2,130 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.example.g8backend.entity.Report;
+import com.example.g8backend.entity.User;
 import com.example.g8backend.mapper.ReportMapper;
+import com.example.g8backend.mapper.UserMapper;
 import com.example.g8backend.service.impl.ReportServiceImpl;
 import org.junit.jupiter.api.BeforeEach;
 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 java.time.LocalDateTime;
-import java.util.Arrays;
+import java.lang.reflect.Field;
+import org.springframework.security.access.AccessDeniedException;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.*;
 
+@ExtendWith(MockitoExtension.class)
 class ReportServiceImplTest {
 
+    @Mock
     private ReportMapper reportMapper;
+
+    @Mock
+    private UserMapper userMapper;
+
+    @InjectMocks
     private ReportServiceImpl reportService;
 
+    private static final Long TEST_USER_ID = 1L;
+    private static final Long TEST_ADMIN_ID = 999L;
+    private static final Long TEST_REPORT_ID = 1000L;
+
+    private User adminUser;
+    private User normalUser;
+    private Report pendingReport;
+
     @BeforeEach
     void setUp() {
-        reportMapper = mock(ReportMapper.class);
-        reportService = new ReportServiceImpl(reportMapper);
+        // 初始化管理员用户
+        adminUser = new User();
+        adminUser.setUserId(TEST_ADMIN_ID);
+        adminUser.setRole("ADMIN");
+
+        // 初始化普通用户
+        normalUser = new User();
+        normalUser.setUserId(TEST_USER_ID);
+        normalUser.setRole("USER");
+
+        // 初始化待处理举报
+        pendingReport = new Report();
+        pendingReport.setReportId(TEST_REPORT_ID);
+        pendingReport.setStatus("pending");
     }
 
+    // ------------------------- submitReport 测试 -------------------------
     @Test
-    void submitReport_shouldSucceedIfNoPendingExists() {
-        Long userId = 1L;
-        Long postId = 2L;
-        String reason = "Spam content";
-
-        // 模拟:没有已有 pending 状态的举报
-        when(reportMapper.selectCount(any(QueryWrapper.class))).thenReturn(0L);
+    void submitReport_WhenNoDuplicate_ShouldReturnTrue() {
+        when(reportMapper.selectCount(any())).thenReturn(0L);
         when(reportMapper.insert(any(Report.class))).thenReturn(1);
 
-        boolean result = reportService.submitReport(userId, postId, reason);
-
+        boolean result = reportService.submitReport(TEST_USER_ID, 2L, "违规内容");
         assertTrue(result);
         verify(reportMapper).insert(any(Report.class));
     }
 
+    // ------------------------- resolveReport 测试 -------------------------
     @Test
-    void submitReport_shouldThrowIfPendingExists() {
-        Long userId = 1L;
-        Long postId = 2L;
-        String reason = "重复举报";
-
-        when(reportMapper.selectCount(any(QueryWrapper.class))).thenReturn(1L);
-
-        IllegalArgumentException exception = assertThrows(
-                IllegalArgumentException.class,
-                () -> reportService.submitReport(userId, postId, reason)
-        );
-
-        assertEquals("您已举报过该帖子,请勿重复提交", exception.getMessage());
-        verify(reportMapper, never()).insert(any(Report.class));
-    }
-
-    @Test
-    void resolveReport_shouldUpdateExistingReport() {
-        Long reportId = 10L;
-        Long adminId = 100L;
-        String status = "resolved";
-        String notes = "已处理";
-
+    void resolveReport_WhenAdminProcesses_ShouldSucceed() {
+        when(userMapper.selectById(TEST_ADMIN_ID)).thenReturn(adminUser);
         Report mockReport = new Report();
-        mockReport.setReportId(reportId);
         mockReport.setStatus("pending");
+        when(reportMapper.selectById(TEST_REPORT_ID)).thenReturn(mockReport);
 
-        when(reportMapper.selectById(reportId)).thenReturn(mockReport);
         when(reportMapper.updateById(any(Report.class))).thenReturn(1);
 
-        boolean result = reportService.resolveReport(reportId, adminId, status, notes);
+        boolean result = reportService.resolveReport(TEST_REPORT_ID, TEST_ADMIN_ID, "resolved", "已处理");
 
         assertTrue(result);
-        verify(reportMapper).updateById(any(Report.class));
+        verify(reportMapper).updateById(any(Report.class)); // 明确验证参数类型
     }
 
     @Test
-    void resolveReport_shouldThrowIfNotFound() {
-        Long reportId = 999L;
+    void resolveReport_WhenNonAdminAttempts_ShouldThrowAccessDenied() {
+        when(userMapper.selectById(TEST_USER_ID)).thenReturn(normalUser);
 
-        when(reportMapper.selectById(reportId)).thenReturn(null);
-
-        IllegalArgumentException exception = assertThrows(
-                IllegalArgumentException.class,
-                () -> reportService.resolveReport(reportId, 1L, "resolved", "无效举报")
+        // 使用正确的异常类型
+        assertThrows(AccessDeniedException.class, () ->
+                reportService.resolveReport(TEST_REPORT_ID, TEST_USER_ID, "resolved", null)
         );
-
-        assertEquals("举报记录不存在", exception.getMessage());
         verify(reportMapper, never()).updateById(any(Report.class));
     }
-
+    // ------------------------- getReports 测试 -------------------------
     @Test
-    void getReports_shouldReturnMatchingStatus() {
-        Report r1 = new Report();
-        r1.setStatus("pending");
+    void getReports_WhenAdminQueries_ShouldReturnFiltered() {
+        // 模拟管理员存在
+        when(userMapper.selectById(TEST_ADMIN_ID)).thenReturn(adminUser);
+        when(reportMapper.selectList(any())).thenReturn(Collections.singletonList(pendingReport));
 
-        Report r2 = new Report();
-        r2.setStatus("pending");
+        // 执行方法
+        List<Report> result = reportService.getReports("pending", TEST_ADMIN_ID);
+        assertEquals(1, result.size());
 
-        when(reportMapper.selectList(any(QueryWrapper.class)))
-                .thenReturn(Arrays.asList(r1, r2));
-
-        List<Report> reports = reportService.getReports("pending");
-
-        assertEquals(2, reports.size());
-        assertEquals("pending", reports.get(0).getStatus());
+        // 验证是否调用了 selectList 方法
         verify(reportMapper).selectList(any(QueryWrapper.class));
+
+        // 打印实际 SQL 用于调试(可选)
+        QueryWrapper<Report> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("status", "pending");
+        System.out.println("Expected SQL: " + queryWrapper.getTargetSql());
     }
-}
+    @Test
+    void getReports_WhenNonAdminQueries_ShouldThrowAccessDenied() {
+        when(userMapper.selectById(TEST_USER_ID)).thenReturn(normalUser);
+        assertThrows(AccessDeniedException.class, () ->
+                reportService.getReports("pending", TEST_USER_ID)
+        );
+        verify(reportMapper, never()).selectList(any());
+    }
+}
\ No newline at end of file