Kaynağa Gözat

Merge branch 'lyy_fix_springSecurityWithJwt' of WengPuHong/seecoder-devcloud into master

LiuYiYe 5 yıl önce
ebeveyn
işleme
59b6650908

+ 3 - 0
web/src/main/java/cn/seecoder/web/dao/bug_list/BugListMapper.java

@@ -27,4 +27,7 @@ public interface BugListMapper {
 
 
     @Select("select * from bug_list where project_id = #{projectId}")
     @Select("select * from bug_list where project_id = #{projectId}")
     List<BugListPO> selectByProjectId(int projectId);
     List<BugListPO> selectByProjectId(int projectId);
+
+    @Select("select * from bug_list where id = #{bugId}")
+    BugListPO selectById(int bugId);
 }
 }

+ 241 - 0
web/src/main/java/cn/seecoder/web/infrastructure/config/AuthTools.java

@@ -0,0 +1,241 @@
+package cn.seecoder.web.infrastructure.config;
+
+import cn.seecoder.common.util.SpringUtil;
+import cn.seecoder.web.dao.APITest.APITestMapper;
+import cn.seecoder.web.dao.bug_list.BugListMapper;
+import cn.seecoder.web.dao.func_test.FuncTestCaseMapper;
+import cn.seecoder.web.dao.func_test.FuncTestStepMapper;
+import cn.seecoder.web.dao.pipeline.PipelineMapper;
+import cn.seecoder.web.dao.pipeline.PipelineRecordMapper;
+import cn.seecoder.web.dao.tree.TreeNodeMapper;
+import cn.seecoder.web.model.po.APITest.TestInfo;
+import cn.seecoder.web.model.po.bug_list.BugListPO;
+import cn.seecoder.web.model.po.func_test.FuncTestCasePO;
+import cn.seecoder.web.model.po.func_test.FuncTestStepPO;
+import cn.seecoder.web.model.po.pipeline.PipelinePO;
+import cn.seecoder.web.model.po.pipeline.PipelineRecordPO;
+import cn.seecoder.web.model.po.tree.TreeNodePO;
+import cn.seecoder.web.model.po.user.UserPO;
+import cn.seecoder.web.model.vo.pipeline.PipelineUpdateConfigVO;
+import cn.seecoder.web.model.vo.tree.TreeNodeUpdateBasicVO;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.nju.edu.gitlab.SeecoderGitlabApi;
+import com.nju.edu.gitlab.SeecoderGitlabException;
+import com.nju.edu.gitlab.vo.ProjectVO;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class AuthTools {
+    private final APITestMapper apiTestMapper;
+    private final FuncTestCaseMapper funcTestCaseMapper;
+    private final FuncTestStepMapper funcTestStepMapper;
+    private final TreeNodeMapper treeNodeMapper;
+    private final BugListMapper bugListMapper;
+    private final PipelineMapper pipelineMapper;
+    private final PipelineRecordMapper pipelineRecordMapper;
+
+    @Autowired
+    public AuthTools(APITestMapper apiTestMapper,
+                     FuncTestCaseMapper funcTestCaseMapper,
+                     FuncTestStepMapper funcTestStepMapper,
+                     TreeNodeMapper treeNodeMapper,
+                     BugListMapper bugListMapper,
+                     PipelineMapper pipelineMapper,
+                     PipelineRecordMapper pipelineRecordMapper) {
+        this.apiTestMapper = apiTestMapper;
+        this.funcTestCaseMapper = funcTestCaseMapper;
+        this.funcTestStepMapper = funcTestStepMapper;
+        this.treeNodeMapper = treeNodeMapper;
+        this.bugListMapper = bugListMapper;
+        this.pipelineMapper = pipelineMapper;
+        this.pipelineRecordMapper = pipelineRecordMapper;
+    }
+
+    private UserPO getCurrentUser() {
+        return (UserPO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+    }
+
+    public boolean checkProjOwnershipParam(HttpServletRequest request) {
+        String projectIdStr = request.getParameter("projectId");
+        if (!StringUtils.isNumeric(projectIdStr)) {
+            return false;
+        }
+        Integer projectId = Integer.parseInt(projectIdStr);
+        return checkProjOwnership(projectId);
+    }
+
+    public boolean checkProjOwnership (Integer projectId) {
+        UserPO userPO = getCurrentUser();
+        SeecoderGitlabApi seecoderGitlabApi = SpringUtil.getBean(SeecoderGitlabApi.class);
+        try {
+            List<ProjectVO> projects = seecoderGitlabApi.getAllProjectsByUserId(userPO.getId());
+            if (projects.stream().noneMatch(project -> project.getProjectId().equals(projectId))){
+                return false;
+            }
+        } catch (SeecoderGitlabException e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+
+    public boolean checkTestOwnershipParam(HttpServletRequest request) {
+        String testIdStr = request.getParameter("testId");
+        if (!StringUtils.isNumeric(testIdStr)) {
+            return false;
+        }
+        Integer testId = Integer.parseInt(testIdStr);
+        return checkTestOwnership(testId);
+    }
+
+    public boolean checkTestOwnership (Integer testId) {
+        TestInfo testInfo = apiTestMapper.selectByTestId(testId);
+        if (testInfo == null) {
+            return false;
+        }
+        Integer projectId = testInfo.getProjectId();
+        return checkProjOwnership(projectId);
+    }
+
+    public boolean checkTestCaseOwnershipParam(HttpServletRequest request) {
+        String testCaseIdStr = request.getParameter("testCaseId");
+        if (!StringUtils.isNumeric(testCaseIdStr)) {
+            return false;
+        }
+        Integer testCaseId = Integer.parseInt(testCaseIdStr);
+        return checkTestCaseOwnership(testCaseId);
+    }
+
+    public boolean checkTestCaseOwnership (Integer testCaseId) {
+        FuncTestCasePO funcTestCasePO = funcTestCaseMapper.selectById(testCaseId);
+        Integer projectId = funcTestCasePO.getProjectId();
+        return checkProjOwnership(projectId);
+    }
+
+    public boolean checkTestStepOwnershipParam (HttpServletRequest request) {
+        String testStepIdStr = request.getParameter("testStepId");
+        if (!StringUtils.isNumeric(testStepIdStr)) {
+            return false;
+        }
+        Integer testStepId = Integer.parseInt(testStepIdStr);
+        return checkTestStepOwnership(testStepId);
+    }
+
+    public boolean checkTestStepOwnership (Integer testStepId) {
+        List<FuncTestStepPO> funcTestStepPOS = funcTestStepMapper.selectByTestCaseId(testStepId);
+        if (funcTestStepPOS == null) {
+            return false;
+        }
+        Integer testCaseId = funcTestStepPOS.get(0).getTestCaseId();
+        return checkTestCaseOwnership(testCaseId);
+    }
+
+    public boolean checkTreeNodeOwnershipBody (HttpServletRequest request) throws IOException {
+        ObjectMapper mapper = new ObjectMapper();
+        String requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
+        TreeNodeUpdateBasicVO treeNodeUpdateBasicVO = mapper.readValue(requestBody, TreeNodeUpdateBasicVO.class);
+        return checkTreeNodeOwnership(treeNodeUpdateBasicVO.getId());
+    }
+
+    public boolean checkTreeNodeOwnershipParam (HttpServletRequest request) {
+        String treeNodeIdStr = request.getParameter("treeId");
+        if (!StringUtils.isNumeric(treeNodeIdStr)) {
+            return false;
+        }
+        Integer treeNodeId = Integer.parseInt(treeNodeIdStr);
+        return checkTreeNodeOwnership(treeNodeId);
+    }
+
+    public boolean checkTreeNodeOwnership (Integer treeNodeId) {
+        TreeNodePO treeNodeById = treeNodeMapper.getTreeNodeById(treeNodeId);
+        if (treeNodeById == null) {
+            return false;
+        }
+        Integer projectId = treeNodeById.getProjectId();
+        return checkProjOwnership(projectId);
+    }
+
+    public boolean checkBugOwnershipParam (HttpServletRequest request) {
+        String bugIdStr = request.getParameter("bugId");
+        if (!StringUtils.isNumeric(bugIdStr)) {
+            return false;
+        }
+        Integer bugId = Integer.parseInt(bugIdStr);
+        return checkBugOwnership(bugId);
+    }
+
+    public boolean checkBugOwnership (Integer bugId) {
+        BugListPO bugListPO = bugListMapper.selectById(bugId);
+        if (bugListPO == null) {
+            return false;
+        }
+        Integer projectId = bugListPO.getProjectId();
+        return checkProjOwnership(projectId);
+    }
+
+    public boolean checkProjPipelineBody (HttpServletRequest request) throws IOException {
+        ObjectMapper mapper = new ObjectMapper();
+        String requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
+        PipelineUpdateConfigVO pipelineUpdateConfigVO = mapper.readValue(requestBody, PipelineUpdateConfigVO.class);
+        return checkProjPipeline(pipelineUpdateConfigVO.getProjectId(), pipelineUpdateConfigVO.getPipelineId());
+    }
+
+    public boolean checkProjPipelineParam (HttpServletRequest request) {
+        String projectIdStr = request.getParameter("projectId");
+        String pipelineIdStr = request.getParameter("pipelineId");
+        if (!StringUtils.isNumeric(projectIdStr) || !StringUtils.isNumeric(pipelineIdStr)) {
+            return false;
+        }
+        Integer projectId = Integer.parseInt(projectIdStr);
+        Integer pipelineId = Integer.parseInt(pipelineIdStr);
+        return checkProjPipeline(projectId, pipelineId);
+    }
+
+    public boolean checkProjPipeline (Integer projectId, Integer pipelineId) {
+        // check if pipelineId owned by projectId
+        PipelinePO pipelinePO = pipelineMapper.selectById(pipelineId);
+        Integer projectId1 = pipelinePO.getProjectId();
+        if (!projectId1.equals(projectId)) {
+            return false;
+        }
+        // check if own project
+        return checkProjOwnership(projectId);
+    }
+
+    public boolean checkPipelineOwnership (Integer pipelineId) {
+        PipelinePO pipelinePO = pipelineMapper.selectById(pipelineId);
+        if (pipelinePO == null) {
+            return false;
+        }
+        Integer projectId = pipelinePO.getProjectId();
+        return checkProjOwnership(projectId);
+    }
+
+    public boolean checkPipelineRecordOwnershipParam (HttpServletRequest request) {
+        String pipelineRecordIdStr = request.getParameter("recordId");
+        if (!StringUtils.isNumeric(pipelineRecordIdStr)) {
+            return false;
+        }
+        Integer pipelineRecordId = Integer.parseInt(pipelineRecordIdStr);
+        return checkPipelineRecordOwnership(pipelineRecordId);
+    }
+
+    public boolean checkPipelineRecordOwnership (Integer pipelineRecordId) {
+        PipelineRecordPO pipelineRecordPO = pipelineRecordMapper.selectById(pipelineRecordId);
+        if (pipelineRecordPO == null) {
+            return false;
+        }
+        Integer pipelineId = pipelineRecordPO.getPipelineId();
+        return checkPipelineOwnership(pipelineId);
+    }
+}

+ 64 - 12
web/src/main/java/cn/seecoder/web/infrastructure/config/WebSecurityConfig.java

@@ -4,7 +4,7 @@ import cn.seecoder.web.infrastructure.security.JwtAuthenticationTokenFilter;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.DependsOn;
+import org.springframework.http.HttpMethod;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@@ -25,22 +25,22 @@ import cn.seecoder.web.infrastructure.security.WebSecurityConstants;
 @Configuration
 @Configuration
 @EnableWebSecurity
 @EnableWebSecurity
 @EnableGlobalMethodSecurity(prePostEnabled = true)  //  启用方法级别的权限认证
 @EnableGlobalMethodSecurity(prePostEnabled = true)  //  启用方法级别的权限认证
-@DependsOn("userServiceImpl")
+//@DependsOn("userServiceImpl")
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
 
-
     private final JwtAuthenticationTokenFilter filter;
     private final JwtAuthenticationTokenFilter filter;
-
-
+    private final AuthTools authTools;
 
 
     @Autowired
     @Autowired
-    public WebSecurityConfig(JwtAuthenticationTokenFilter filter) {
+    public WebSecurityConfig(JwtAuthenticationTokenFilter filter, AuthTools authTools) {
         super();
         super();
         this.filter = filter;
         this.filter = filter;
+        this.authTools = authTools;
     }
     }
 
 
     @Override
     @Override
     protected void configure(HttpSecurity http) throws Exception {
     protected void configure(HttpSecurity http) throws Exception {
+
         //访问控制
         //访问控制
         http
         http
                 //访问swagger
                 //访问swagger
@@ -51,17 +51,69 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/**/*api-docs*/**").permitAll()
                 .antMatchers("/**/*api-docs*/**").permitAll()
                 .antMatchers("/**/hook").permitAll()
                 .antMatchers("/**/hook").permitAll()
                 .antMatchers("/**/query/**").permitAll()
                 .antMatchers("/**/query/**").permitAll()
+                // API Test Controller
+                .antMatchers(HttpMethod.GET, "/api/test/list/{projectId}").access("@authTools.checkProjOwnership(#projectId)")
+                .antMatchers(HttpMethod.GET, "/api/test/delete/{testId}").access("@authTools.checkTestOwnership(#testId)")
+                .antMatchers(HttpMethod.GET, "/api/test/execute/{testId}").access("@authTools.checkTestOwnership(#testId)")
+                .antMatchers(HttpMethod.GET, "/api/test/result/{testId}").access("@authTools.checkTestOwnership(#testId)")
+                .antMatchers(HttpMethod.GET, "/api/test/latest/{testId}").access("@authTools.checkTestOwnership(#testId)")
+                // Auto Test Controller
+                .antMatchers("/api/auto_test/list/{projectId}").access("@authTools.checkProjOwnership(#projectId)")
+                // Bug List Controller
+                .antMatchers("/api/bug_list/list").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/bug_list").access("@authTools.checkProjOwnershipParam(request)")
+                // Func Test Controller
+                .antMatchers(HttpMethod.GET, "/api/func_test").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.POST, "/api/func_test").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/func_test").access("@authTools.checkTestCaseOwnershipParam(request)")
+                .antMatchers(HttpMethod.DELETE, "/api/func_test").access("@authTools.checkTestCaseOwnershipParam(request)")
+                .antMatchers(HttpMethod.GET, "/api/func_test/steps").access("@authTools.checkTestCaseOwnershipParam(request)")
+                .antMatchers(HttpMethod.POST, "/api/func_test/steps").access("@authTools.checkTestCaseOwnershipParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/func_test/steps").access("@authTools.checkTestStepOwnershipParam(request)")
+                .antMatchers(HttpMethod.DELETE, "/api/func_test/steps").access("@authTools.checkTestStepOwnershipParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/func_test/finish").access("@authTools.checkTestCaseOwnershipParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/func_test/reopen").access("@authTools.checkTestCaseOwnershipParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/func_test/steps/state").access("@authTools.checkTestStepOwnershipParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/func_test/record/latest").access("@authTools.checkProjOwnershipParam(request)")
+                // Commit Controller
+                .antMatchers("/api/commits/tree").access("@authTools.checkTreeNodeOwnershipParam(request)")
+                .antMatchers("/api/commits/bug_list").access("@authTools.checkBugOwnershipParam(request)")
+                // Deployment Controller
+                .antMatchers(HttpMethod.GET, "/api/deployments/list").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.POST, "/api/deployments").access("@authTools.checkProjPipelineParam(request)")
+                .antMatchers(HttpMethod.DELETE, "/api/deployments").access("@authTools.checkProjPipelineParam(request)")
+                .antMatchers(HttpMethod.GET, "/api/deployments/log").access("@authTools.checkProjPipelineParam(request)")
+                // Pipeline Controller
+                .antMatchers(HttpMethod.GET, "/api/pipelines/list").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.GET, "/api/pipelines").access("@authTools.checkProjPipelineParam(request)")
+                .antMatchers(HttpMethod.GET, "/api/pipelines/record/list").access("@authTools.checkProjPipelineParam(request)")
+                .antMatchers(HttpMethod.GET, "/api/pipelines/record").access("@authTools.checkPipelineRecordOwnershipParam(request)")
+                .antMatchers(HttpMethod.GET, "/api/pipelines/record/details").access("@authTools.checkPipelineRecordOwnershipParam(request)")
+                .antMatchers(HttpMethod.DELETE, "/api/pipelines").access("@authTools.checkProjPipelineParam(request)")
+                .antMatchers(HttpMethod.PUT, "/api/pipelines/config").access("@authTools.checkProjPipelineBody(request)")
+                // Project Controller
+                .antMatchers(HttpMethod.GET, "/api/project/{projectId}").access("@authTools.checkProjOwnership(#projectId)")
+                .antMatchers(HttpMethod.GET, "/api/project/members").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.POST, "/api/project/members").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.POST, "/api/project/relate/code").access("@authTools.checkProjOwnershipParam(request)")
+                .antMatchers(HttpMethod.POST, "/api/project/relate").access("@authTools.checkProjOwnershipParam(request)")
+                // SQL Controller
+                .antMatchers(HttpMethod.GET, "/api/sql/instances").access("@authTools.checkProjOwnershipParam(request)")
+                // Tree Nodes Controller
+                .antMatchers(HttpMethod.GET, "/api/tree/{projectId}").access("@authTools.checkProjOwnership(#projectId)")
+                .antMatchers(HttpMethod.DELETE, "/api/tree/node/{nodeId}").access("@authTools.checkTreeNodeOwnership(#nodeId)")
+                .antMatchers(HttpMethod.POST, "/api/tree/subNode/{fatherId}").access("@authTools.checkTreeNodeOwnership(#fatherId)")
+                .antMatchers(HttpMethod.PUT, "/api/tree/node").access("@authTools.checkTreeNodeOwnershipBody(request)")
+                .antMatchers(HttpMethod.PUT, "/api/tree/node/type/task/{projectId}").access("@authTools.checkProjOwnership(#projectId)")
+
                 .and()
                 .and()
                 .authorizeRequests()
                 .authorizeRequests()
                 //跨域的Options请求进行放行
                 //跨域的Options请求进行放行
                 .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                 .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
-                .antMatchers("/**").hasAnyRole(WebSecurityConstants.STUDENT_ROLE, WebSecurityConstants.ADMIN_ROLE)
+                .antMatchers("/**").hasAnyRole(WebSecurityConstants.STUDENT_ROLE, WebSecurityConstants.ADMIN_ROLE, WebSecurityConstants.TEACHER_ROLE)
                 //其他所有接口都要在登陆认证状态下请求
                 //其他所有接口都要在登陆认证状态下请求
                 .anyRequest().authenticated();
                 .anyRequest().authenticated();
 
 
-
-
-
         //开启跨域
         //开启跨域
         http.cors();
         http.cors();
 
 
@@ -75,14 +127,14 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
 
     @Bean
     @Bean
     public AuthenticationManager authenticationManager() throws Exception {
     public AuthenticationManager authenticationManager() throws Exception {
-        return super.authenticationManagerBean() ;
+        return super.authenticationManagerBean();
     }
     }
 
 
     /**
     /**
      * 本地测试时的跨域设置
      * 本地测试时的跨域设置
      */
      */
     @Bean
     @Bean
-    CorsConfigurationSource corsConfigurationSource(){
+    CorsConfigurationSource corsConfigurationSource() {
         return httpServletRequest -> {
         return httpServletRequest -> {
             CorsConfiguration cfg = new CorsConfiguration();
             CorsConfiguration cfg = new CorsConfiguration();
             cfg.addAllowedHeader("*");
             cfg.addAllowedHeader("*");

+ 83 - 0
web/src/test/java/cn/seecoder/web/infrastructure/config/WebSecurityConfigTest.java

@@ -0,0 +1,83 @@
+package cn.seecoder.web.infrastructure.config;
+
+import cn.seecoder.web.controller.APITest.APITestController;
+import cn.seecoder.web.model.enums.UserIdentity;
+import cn.seecoder.web.model.po.user.UserPO;
+import cn.seecoder.web.model.vo.APITest.APITestInfoVO;
+import cn.seecoder.web.model.vo.Response;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+import java.util.*;
+
+import static org.mockito.BDDMockito.given;
+
+// JUnit 5 does not need @RunWith anymore
+//@AutoConfigureMockMvc
+//@ExtendWith(MockitoExtension.class)
+//@SpringBootTest
+class WebSecurityConfigTest {
+    // This test aims to test if security is working properly
+
+//    @Mock
+//    private AuthTools authTools;
+//    @Mock
+//    private APITestController apiTestController;
+//    @Autowired
+//    private MockMvc mockMvc;
+//    private final Map<String, Object> userInfo = new HashMap<String, Object>() {{
+//        put("id", 114514);
+//        put("name", "yajyuu");
+//        put("email", "1919810@gmail.com");
+//        put("phone", "13911451919");
+//        put("role", "ROLE_STUDENT");
+//    }};
+//
+//    @BeforeEach
+//    void setUp() {
+//        SecurityContext emptyContext = SecurityContextHolder.createEmptyContext();
+//        UserPO userPO = UserPO.builder()
+//                .id((Integer) userInfo.get("id"))
+//                .username((String) userInfo.get("name"))
+//                .email((String) userInfo.get("email"))
+//                .phone((String) userInfo.get("phone"))
+//                .role(UserIdentity.valueOf((String) userInfo.get("role")))
+//                .build();
+//        Collection<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>() {{
+//            add(new SimpleGrantedAuthority("ROLE_STUDENT"));
+//        }};
+//        emptyContext.setAuthentication(new UsernamePasswordAuthenticationToken(userPO, null, authorities));
+//    }
+//
+//    @Test
+//    void test() {
+//        System.out.println("Test");
+//    }
+//
+//    @Test
+//    @Disabled
+//    void apiTestControllerTestList () throws Exception {
+//        Integer projectId = 142857;
+//        given(authTools.checkProjOwnership(projectId)).willReturn(true);
+//        given(apiTestController.getAPITestInfosByProjectId(projectId)).willReturn(Response.buildSuccess(null));
+//        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/api/test/list/" + projectId))
+//                .andExpect(MockMvcResultMatchers.status().is2xxSuccessful())
+//                .andReturn();
+//    }
+
+}