فهرست منبع

Merge branch 'integration' into wph

370774330@qq.com 5 سال پیش
والد
کامیت
b003846f8a
56فایلهای تغییر یافته به همراه1424 افزوده شده و 280 حذف شده
  1. 0 5
      common/src/main/java/seecoder/devcloud/common/util/JwtTokenUtil.java
  2. 12 3
      web/pom.xml
  3. 16 0
      web/src/main/java/seecoder/devcloud/web/aop/TreeLogging.java
  4. 74 0
      web/src/main/java/seecoder/devcloud/web/aspect/TreeLoggingAspect.java
  5. 0 26
      web/src/main/java/seecoder/devcloud/web/controller/TreeNodesController.java
  6. 3 1
      web/src/main/java/seecoder/devcloud/web/controller/gitlab/HookController.java
  7. 5 9
      web/src/main/java/seecoder/devcloud/web/controller/pipeline/DeploymentController.java
  8. 11 11
      web/src/main/java/seecoder/devcloud/web/controller/pipeline/PipelineController.java
  9. 63 0
      web/src/main/java/seecoder/devcloud/web/controller/project/ProjectController.java
  10. 76 0
      web/src/main/java/seecoder/devcloud/web/controller/tree/TreeNodesController.java
  11. 6 2
      web/src/main/java/seecoder/devcloud/web/controller/user/UserController.java
  12. 0 29
      web/src/main/java/seecoder/devcloud/web/dao/impl/UserMapperImpl.java
  13. 44 0
      web/src/main/java/seecoder/devcloud/web/dao/project/ProjectMapper.java
  14. 5 3
      web/src/main/java/seecoder/devcloud/web/dao/provider/TreeNodeProvider.java
  15. 29 0
      web/src/main/java/seecoder/devcloud/web/dao/tree/TreeLogMapper.java
  16. 29 11
      web/src/main/java/seecoder/devcloud/web/dao/tree/TreeNodeMapper.java
  17. 0 22
      web/src/main/java/seecoder/devcloud/web/dao/user/UserMapper.java
  18. 11 2
      web/src/main/java/seecoder/devcloud/web/infrastructure/GlobalExceptionHandler.java
  19. 5 9
      web/src/main/java/seecoder/devcloud/web/infrastructure/config/SwaggerConfig.java
  20. 19 1
      web/src/main/java/seecoder/devcloud/web/infrastructure/config/WebSecurityConfig.java
  21. 10 8
      web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java
  22. 20 0
      web/src/main/java/seecoder/devcloud/web/infrastructure/security/TokenExpiredException.java
  23. 3 2
      web/src/main/java/seecoder/devcloud/web/model/enums/NodeStateEnum.java
  24. 22 0
      web/src/main/java/seecoder/devcloud/web/model/enums/OperationEnum.java
  25. 1 0
      web/src/main/java/seecoder/devcloud/web/model/enums/ResponseEnums.java
  26. 21 0
      web/src/main/java/seecoder/devcloud/web/model/po/project/Project.java
  27. 40 0
      web/src/main/java/seecoder/devcloud/web/model/po/tree/TreeLog.java
  28. 11 10
      web/src/main/java/seecoder/devcloud/web/model/po/tree/TreeNodePO.java
  29. 2 0
      web/src/main/java/seecoder/devcloud/web/model/po/user/Group.java
  30. 2 0
      web/src/main/java/seecoder/devcloud/web/model/vo/GitWebHookVO.java
  31. 57 0
      web/src/main/java/seecoder/devcloud/web/model/vo/TreeNodeVO.java
  32. 35 0
      web/src/main/java/seecoder/devcloud/web/model/vo/project/ProjectVO.java
  33. 8 4
      web/src/main/java/seecoder/devcloud/web/model/vo/user/UserVO.java
  34. 0 11
      web/src/main/java/seecoder/devcloud/web/service/TreeNodeService.java
  35. 3 5
      web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java
  36. 55 0
      web/src/main/java/seecoder/devcloud/web/service/impl/project/ProjectServiceImpl.java
  37. 99 4
      web/src/main/java/seecoder/devcloud/web/service/impl/tree/TreeNodeServiceImpl.java
  38. 5 5
      web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java
  39. 4 12
      web/src/main/java/seecoder/devcloud/web/service/impl/user/UserServiceImpl.java
  40. 39 0
      web/src/main/java/seecoder/devcloud/web/service/project/ProjectService.java
  41. 48 0
      web/src/main/java/seecoder/devcloud/web/service/tree/TreeNodeService.java
  42. 8 1
      web/src/main/java/seecoder/devcloud/web/service/user/UserService.java
  43. 15 0
      web/src/main/java/seecoder/devcloud/web/utils/TimeUtils.java
  44. 39 0
      web/src/main/resources/SQLScripts/project.sql
  45. 38 0
      web/src/main/resources/SQLScripts/tree_log.sql
  46. 25 9
      web/src/main/resources/SQLScripts/trees.sql
  47. 59 0
      web/src/main/resources/application-cyz.yml
  48. 1 3
      web/src/main/resources/application-wph.yml
  49. 58 0
      web/src/main/resources/application-xzh.yml
  50. 1 1
      web/src/main/resources/application.yml
  51. 78 0
      web/src/test/java/seecoder/devcloud/web/dao/project/ProjectMapperTest.java
  52. 43 0
      web/src/test/java/seecoder/devcloud/web/dao/tree/TreeLogMapperTest.java
  53. 71 0
      web/src/test/java/seecoder/devcloud/web/dao/tree/TreeNodeMapperTest.java
  54. 0 71
      web/src/test/java/seecoder/devcloud/web/dataMapper/TreeNodeMapperTest.java
  55. 40 0
      web/src/test/java/seecoder/devcloud/web/service/TreeNodeServiceTest.java
  56. 55 0
      web/src/test/java/seecoder/devcloud/web/service/project/ProjectServiceTest.java

+ 0 - 5
common/src/main/java/seecoder/devcloud/common/util/JwtTokenUtil.java

@@ -39,11 +39,6 @@ public class JwtTokenUtil {
 
 
     private String secret;
     private String secret;
 
 
-    private Long expiration;
-
-    /**
-     * 使用自己方法判断超时是为了后端可以在 小于等于门户过期时间的范围内,自由调控过期时间
-     */
     public Boolean isTokenExpired(String token) {
     public Boolean isTokenExpired(String token) {
         try {
         try {
             Claims claims = getClaimsFromToken(token);
             Claims claims = getClaimsFromToken(token);

+ 12 - 3
web/pom.xml

@@ -24,12 +24,21 @@
     <dependencies>
     <dependencies>
         <!-- Swagger -->
         <!-- Swagger -->
         <!-- https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter -->
         <!-- https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter -->
+<!--        <dependency>-->
+<!--            <groupId>io.springfox</groupId>-->
+<!--            <artifactId>springfox-boot-starter</artifactId>-->
+<!--            <version>3.0.0</version>-->
+<!--        </dependency>-->
         <dependency>
         <dependency>
             <groupId>io.springfox</groupId>
             <groupId>io.springfox</groupId>
-            <artifactId>springfox-boot-starter</artifactId>
-            <version>3.0.0</version>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.5.0</version>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>2.5.0</version>
         </dependency>
         </dependency>
-
         <!-- END Swagger -->
         <!-- END Swagger -->
         <dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <groupId>org.springframework.boot</groupId>

+ 16 - 0
web/src/main/java/seecoder/devcloud/web/aop/TreeLogging.java

@@ -0,0 +1,16 @@
+package seecoder.devcloud.web.aop;
+
+import seecoder.devcloud.web.model.enums.OperationEnum;
+
+import java.lang.annotation.*;
+
+/**
+ * 以注解方式标记日志插入
+ * 要求:参数里带有TreeNodeVO
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface TreeLogging {
+    public OperationEnum value();
+}

+ 74 - 0
web/src/main/java/seecoder/devcloud/web/aspect/TreeLoggingAspect.java

@@ -0,0 +1,74 @@
+package seecoder.devcloud.web.aspect;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import seecoder.devcloud.web.aop.TreeLogging;
+import seecoder.devcloud.web.dao.tree.TreeLogMapper;
+
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.po.tree.TreeLog;
+
+import seecoder.devcloud.web.model.vo.TreeNodeVO;
+
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 树操作日志类切面,关联@TreeLogging注解
+ */
+@Aspect
+@Component
+public class TreeLoggingAspect {
+    @Autowired
+    TreeLogMapper treeLogMapper;
+
+    @Pointcut("@annotation(seecoder.devcloud.web.aop.TreeLogging)")
+    public void logPointCut() {
+
+    }
+
+    @AfterReturning(pointcut = "logPointCut()", returning = "result")
+    public void doAfterReturning(JoinPoint joinPoint, Response result) {
+        // 只处理成功的情况
+        if (result.getCode().equals(200)) {
+            TreeLog log = new TreeLog();
+            //从切面织入点处通过反射机制获取织入点处的方法
+            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+            //获取切入点所在的方法
+            Method method = signature.getMethod();
+            //获取注解,提取操作类型属性
+            TreeLogging logging = method.getAnnotation(TreeLogging.class);
+            if (logging != null) {
+                log.setOperation(logging.value());
+            }
+            //请求的参数
+            Object[] args = joinPoint.getArgs();
+            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            for (Object arg : args) {
+                if (arg instanceof TreeNodeVO) {
+                    TreeNodeVO node = (TreeNodeVO) arg;
+                    log.setTreeId(node.getId());
+//                    log.setUserId();
+//                    log.setUserName();
+//                    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+//                    HttpSession session = request.getSession();
+//                    读取session中的用户
+//                    User user = (User) session.getAttribute("user");
+//                    请求的IP
+//                    String ip = request.getRemoteAddr();
+//                    TODO:从session中获取userId和userName
+                    log.setTime(sf.format(new Date()));
+                    System.out.println(log);
+                    treeLogMapper.insertTreeLog(log);
+                    break;
+                }
+            }
+        }
+    }
+}

+ 0 - 26
web/src/main/java/seecoder/devcloud/web/controller/TreeNodesController.java

@@ -1,26 +0,0 @@
-package seecoder.devcloud.web.controller;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-import seecoder.devcloud.web.model.po.TreeNode;
-import seecoder.devcloud.web.service.TreeNodeService;
-
-import java.util.List;
-
-@RestController
-public class TreeNodesController {
-    @Autowired
-    private TreeNodeService treeNodeService;
-    //注意 这里混用po和vo了
-    @GetMapping("/all")
-    public List<TreeNode> getAllNodes(){
-        return treeNodeService.getAllNodes();
-    }
-    @GetMapping("/")
-    public String test(){
-        return "123";
-    }
-
-}

+ 3 - 1
web/src/main/java/seecoder/devcloud/web/controller/gitlab/HookController.java

@@ -1,6 +1,7 @@
 package seecoder.devcloud.web.controller.gitlab;
 package seecoder.devcloud.web.controller.gitlab;
 
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -23,8 +24,9 @@ public class HookController {
      * @date 2021/2/4
      * @date 2021/2/4
      * @description: 此接口挂载在webhooks的push回调中
      * @description: 此接口挂载在webhooks的push回调中
      */
      */
-    @ApiOperation("push回调接口")
+    @ApiOperation(value = "push回调接口", httpMethod = "POST")
     @PostMapping("/push")
     @PostMapping("/push")
+    @ApiImplicitParam(value = "gitWebHookVO",dataType = "object", paramType = "body")
     public void pushHook(@RequestBody GitWebHookVO gitWebHookVO)
     public void pushHook(@RequestBody GitWebHookVO gitWebHookVO)
     {
     {
         System.out.println(gitWebHookVO);
         System.out.println(gitWebHookVO);

+ 5 - 9
web/src/main/java/seecoder/devcloud/web/controller/pipeline/DeploymentController.java

@@ -30,7 +30,7 @@ public class DeploymentController {
     }
     }
 
 
     @ApiOperation(value = "获取项目所有部署的实例信息", httpMethod = "GET")
     @ApiOperation(value = "获取项目所有部署的实例信息", httpMethod = "GET")
-    @ApiImplicitParam(name = "projectId", dataType = "int")
+    @ApiImplicitParam(name = "projectId", dataType ="int", paramType = "query")
     @GetMapping("/list")
     @GetMapping("/list")
     public Response<List<DeploymentInfoVO>> retrieveDeploymentInfos(@RequestParam("projectId")Integer projectId){
     public Response<List<DeploymentInfoVO>> retrieveDeploymentInfos(@RequestParam("projectId")Integer projectId){
         return Response.buildSuccess(deploymentService.retrieveDeploymentInfos(projectId));
         return Response.buildSuccess(deploymentService.retrieveDeploymentInfos(projectId));
@@ -39,8 +39,8 @@ public class DeploymentController {
 
 
     @ApiOperation(value = "执行流水线构建实例", httpMethod = "POST")
     @ApiOperation(value = "执行流水线构建实例", httpMethod = "POST")
     @ApiImplicitParams({
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "projectId", dataType = "int"),
-            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+            @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query"),
+            @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query")
     })
     })
     @PostMapping
     @PostMapping
     public Response deploy(@RequestParam("projectId")Integer projectId,
     public Response deploy(@RequestParam("projectId")Integer projectId,
@@ -49,14 +49,10 @@ public class DeploymentController {
         return Response.buildSuccess();
         return Response.buildSuccess();
     }
     }
 
 
-    /**
-     * 执行一条pipepine
-     * todo 异步/异步异常捕获刷新result
-     */
     @ApiOperation(value = "删除一个部署的实例", httpMethod = "DELETE")
     @ApiOperation(value = "删除一个部署的实例", httpMethod = "DELETE")
     @ApiImplicitParams({
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "projectId", dataType = "int"),
-            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+            @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query"),
+            @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query")
     })
     })
     @DeleteMapping
     @DeleteMapping
     public Response delete(@RequestParam("projectId")Integer projectId,
     public Response delete(@RequestParam("projectId")Integer projectId,

+ 11 - 11
web/src/main/java/seecoder/devcloud/web/controller/pipeline/PipelineController.java

@@ -39,7 +39,7 @@ public class PipelineController {
 
 
     @GetMapping("/list")
     @GetMapping("/list")
     @ApiOperation(value = "获取指定项目的所有流水线基本信息", httpMethod = "GET")
     @ApiOperation(value = "获取指定项目的所有流水线基本信息", httpMethod = "GET")
-    @ApiImplicitParam(name = "projectId", dataType = "int")
+    @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query")
     public Response<List<PipelineInfoVO>> retrievePipelineInfos(@RequestParam("projectId") Integer projectId){
     public Response<List<PipelineInfoVO>> retrievePipelineInfos(@RequestParam("projectId") Integer projectId){
         return Response.buildSuccess(pipelineService.retrievePipelineInfos(projectId));
         return Response.buildSuccess(pipelineService.retrievePipelineInfos(projectId));
     }
     }
@@ -47,8 +47,8 @@ public class PipelineController {
     @GetMapping
     @GetMapping
     @ApiOperation(value = "获取指定一条流水线的配置json信息", httpMethod = "GET")
     @ApiOperation(value = "获取指定一条流水线的配置json信息", httpMethod = "GET")
     @ApiImplicitParams({
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "projectId", dataType = "int"),
-            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+            @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query"),
+            @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query")
     })
     })
     public Response<PipelineConfigVO> retrievePipelineConfig(@RequestParam("projectId")Integer projectId,
     public Response<PipelineConfigVO> retrievePipelineConfig(@RequestParam("projectId")Integer projectId,
                                                              @RequestParam("pipelineId")Integer pipelineId){
                                                              @RequestParam("pipelineId")Integer pipelineId){
@@ -59,8 +59,8 @@ public class PipelineController {
     @GetMapping("/history/list")
     @GetMapping("/history/list")
     @ApiOperation(value = "获取指定一条流水线的历史构建信息列表", httpMethod = "GET")
     @ApiOperation(value = "获取指定一条流水线的历史构建信息列表", httpMethod = "GET")
     @ApiImplicitParams({
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "projectId", dataType = "int"),
-            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+            @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query"),
+            @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query")
     })
     })
     public Response<List<PipelineHistoryVO>> retrievePipelineHistory(@RequestParam("projectId")Integer projectId,
     public Response<List<PipelineHistoryVO>> retrievePipelineHistory(@RequestParam("projectId")Integer projectId,
                                                                      @RequestParam("pipelineId")Integer pipelineId){
                                                                      @RequestParam("pipelineId")Integer pipelineId){
@@ -69,7 +69,7 @@ public class PipelineController {
 
 
 
 
     @ApiOperation(value = "依据模板创建一个流水线配置", httpMethod = "POST")
     @ApiOperation(value = "依据模板创建一个流水线配置", httpMethod = "POST")
-    @ApiImplicitParam(name = "pipelineCreateVO", value = "流水线创建配置信息",dataType = "PipelineCreateVO")
+    @ApiImplicitParam(name = "pipelineCreateVO", value = "流水线创建配置信息",dataType = "object",paramType = "body")
     @PostMapping
     @PostMapping
     public Response createPipelineConfig(@RequestBody PipelineCreateVO pipelineCreateVO){
     public Response createPipelineConfig(@RequestBody PipelineCreateVO pipelineCreateVO){
         pipelineService.createPipelineConfig(pipelineCreateVO);
         pipelineService.createPipelineConfig(pipelineCreateVO);
@@ -79,9 +79,9 @@ public class PipelineController {
     @PutMapping("/config")
     @PutMapping("/config")
     @ApiOperation(value = "保存修改一条流水线的json配置信息", httpMethod = "PUT")
     @ApiOperation(value = "保存修改一条流水线的json配置信息", httpMethod = "PUT")
     @ApiImplicitParams({
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "projectId", dataType = "int"),
-            @ApiImplicitParam(name = "pipelineId", dataType = "int"),
-            @ApiImplicitParam(name = "configJson", dataType = "String")
+            @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query"),
+            @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query"),
+            @ApiImplicitParam(name = "configJson", dataType = "string",paramType = "query")
     })
     })
     public Response savePipelineConfig(@RequestParam("projectId")Integer projectId,
     public Response savePipelineConfig(@RequestParam("projectId")Integer projectId,
                                        @RequestParam("pipelineId")Integer pipelineId,
                                        @RequestParam("pipelineId")Integer pipelineId,
@@ -93,8 +93,8 @@ public class PipelineController {
 
 
     @ApiOperation(value = "删除一条流水线", httpMethod = "DELETE")
     @ApiOperation(value = "删除一条流水线", httpMethod = "DELETE")
     @ApiImplicitParams({
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "projectId", dataType = "int"),
-            @ApiImplicitParam(name = "pipelineId", dataType = "int"),
+            @ApiImplicitParam(name = "projectId", dataType ="int",paramType = "query"),
+            @ApiImplicitParam(name = "pipelineId", dataType ="int",paramType = "query"),
     })
     })
     @DeleteMapping
     @DeleteMapping
     public Response deletePipelineInfo(Integer projectId,Integer pipelineId){
     public Response deletePipelineInfo(Integer projectId,Integer pipelineId){

+ 63 - 0
web/src/main/java/seecoder/devcloud/web/controller/project/ProjectController.java

@@ -0,0 +1,63 @@
+package seecoder.devcloud.web.controller.project;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.web.model.po.project.Project;
+import seecoder.devcloud.web.service.project.ProjectService;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.project.ProjectVO;
+
+import java.util.List;
+
+/**
+ * @author Chenyz
+ * @date 2021/3/10
+ * @description: 项目接口
+ */
+@Api(tags = "项目相关 API")
+@RestController
+@RequestMapping("/project")
+public class ProjectController {
+    @Autowired
+    ProjectService projectService;
+
+
+    @ApiOperation(value = "根据group获取Project列表", httpMethod = "GET")
+    @GetMapping("/listByGroup/{groupId}")
+    @ApiImplicitParam(value = "groupId",dataType ="int", paramType = "path")
+    public Response<List<ProjectVO>> listProjectsByGroupId(@PathVariable("groupId")int groupId){
+        return Response.buildSuccess(projectService.listProjectsByGroupId(groupId));
+    }
+
+    @ApiOperation(value = "根据user获取Project列表", httpMethod = "GET")
+    @GetMapping("/listByUser/{userId}")
+    @ApiImplicitParam(value = "userId",dataType ="int", paramType = "path")
+    public Response<List<ProjectVO>> listProjectsByUserId(@PathVariable("userId")int userId){
+        return Response.buildSuccess(projectService.listProjectsByUserId(userId));
+    }
+
+    @ApiOperation(value = "根据projectId获取Project", httpMethod = "GET")
+    @GetMapping("/{projectId}")
+    @ApiImplicitParam(value = "projectId",dataType ="int", paramType = "path")
+    public Response<ProjectVO> getProjectById(@PathVariable("projectId")int projectId){
+        return Response.buildSuccess(projectService.getProjectById(projectId));
+    }
+
+    @ApiOperation(value = "创建项目,传入的参数中不必带有效的projectId字段,返回一个创建后的结果,注入id", httpMethod = "POST")
+    @PostMapping("/create")
+    @ApiImplicitParam(value = "project",dataType = "object", paramType = "body")
+    public Response<ProjectVO> createProject(@RequestBody ProjectVO project){
+        return Response.buildSuccess(projectService.createProject(project));
+    }
+
+    @ApiOperation(value = "根据projectId删除项目", httpMethod = "DELETE")
+    @DeleteMapping("/delete/{projectId}")
+    @ApiImplicitParam(value = "projectId",dataType ="int", paramType = "path")
+    public Response deleteProject(@PathVariable("projectId")int projectId){
+        projectService.deleteProject(projectId);
+        return Response.buildSuccess();
+    }
+}

+ 76 - 0
web/src/main/java/seecoder/devcloud/web/controller/tree/TreeNodesController.java

@@ -0,0 +1,76 @@
+package seecoder.devcloud.web.controller.tree;
+
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.web.model.po.tree.TreeNodePO;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.TreeNodeVO;
+import seecoder.devcloud.web.service.tree.TreeNodeService;
+
+
+
+import java.util.List;
+
+/**
+ * @Author cyz,xzh
+ * @Description 需求树相关操作
+ */
+@Api(tags = "需求相关API")
+@RestController
+@RequestMapping("/tree")
+public class TreeNodesController {
+    @Autowired
+    private TreeNodeService treeNodeService;
+    //注意 这里混用po和vo了
+    @ApiOperation("获取所有nodes")
+    @GetMapping("/all")
+    public Response<List<TreeNodeVO>> getAllNodes(){
+        return Response.buildSuccess(treeNodeService.getAllNodes());
+    }
+
+    /**
+     * 获取某个项目所有需求情况
+     * @param projectId
+     * @return
+     */
+    @ApiOperation(value = "获取project_id对应的所有nodes",httpMethod = "GET")
+    @GetMapping("/{projectId}")
+    @ApiImplicitParam(value = "projectId", dataType ="int", paramType = "path")
+    public Response<List<TreeNodeVO>> listTreeNodesByProjectId(@PathVariable("projectId") int projectId){
+        return Response.buildSuccess(treeNodeService.listTreeNodesByProjectId(projectId));
+    }
+
+    @ApiOperation(value = "插入节点", httpMethod = "POST")
+    @ApiImplicitParam(value = "treeNodeVO",dataType ="object", paramType = "body")
+    @PostMapping("/node")
+    public Response insertTreeNode(@RequestBody TreeNodeVO treeNodeVO){
+        treeNodeService.insertTreeNode(treeNodeVO);
+        return Response.buildSuccess();
+    }
+
+    @ApiOperation(value = "根据nodeId删除节点", httpMethod = "DELETE")
+    @DeleteMapping("/node/{nodeId}")
+    @ApiImplicitParam(value = "nodeId",dataType ="int", paramType = "path")
+    public Response deleteTreeNode(@PathVariable("nodeId") int nodeId) {
+        treeNodeService.deleteTreeNode(nodeId);
+        return Response.buildSuccess();
+    }
+    @ApiOperation(value = "根据父节点fatherId创建一个子节点并返回", httpMethod = "POST")
+    @PostMapping("/subNode/{fatherId}")
+    @ApiImplicitParam(value = "fatherId",dataType ="int", paramType = "path")
+    public Response insertTreeNodeByFatherNode(@PathVariable("fatherId") int fatherId){
+        return Response.buildSuccess(treeNodeService.insertTreeNodeByFatherNode(fatherId));
+    }
+
+    @ApiOperation(value = "修改节点属性", httpMethod = "PUT")
+    @PutMapping("/node")
+    @ApiImplicitParam(value = "treeNodeVO",dataType = "object", paramType = "body")
+    public Response updateTreeNode(@RequestBody TreeNodeVO treeNodeVO){
+        treeNodeService.updateTreeNode(treeNodeVO);
+        return Response.buildSuccess();
+    }
+}

+ 6 - 2
web/src/main/java/seecoder/devcloud/web/controller/user/UserController.java

@@ -1,5 +1,7 @@
 package seecoder.devcloud.web.controller.user;
 package seecoder.devcloud.web.controller.user;
 
 
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.po.user.User;
@@ -14,6 +16,7 @@ import seecoder.devcloud.web.service.user.UserService;
  */
  */
 @RestController
 @RestController
 @RequestMapping("/users")
 @RequestMapping("/users")
+@Api(tags = "用户 api")
 public class UserController {
 public class UserController {
 
 
     private final UserService userService;
     private final UserService userService;
@@ -23,8 +26,9 @@ public class UserController {
         this.userService = userService;
         this.userService = userService;
     }
     }
 
 
-    @GetMapping
-    public Response getLoginUser(){
+    @ApiOperation(value = "获取当前登陆的用户信息", httpMethod = "GET")
+    @GetMapping("/self")
+    public Response<UserVO> getLoginUser(){
         return Response.buildSuccess(userService.getLoginUser());
         return Response.buildSuccess(userService.getLoginUser());
     }
     }
 
 

+ 0 - 29
web/src/main/java/seecoder/devcloud/web/dao/impl/UserMapperImpl.java

@@ -1,29 +0,0 @@
-package seecoder.devcloud.web.dao.impl;
-
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-import seecoder.devcloud.web.dao.user.UserMapper;
-import seecoder.devcloud.web.model.po.user.User;
-
-/**
- * @author PuHong Weng
- * @date 2021/3/11
- * @description:
- */
-@Component
-public class UserMapperImpl implements UserMapper {
-
-
-    @Override
-    public User findLoginUser() {
-        User loginUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
-        return loginUser;
-    }
-
-    @Override
-    public User findUserByUsername(String username) {
-        //todo 从门户获取
-        return null;
-    }
-}

+ 44 - 0
web/src/main/java/seecoder/devcloud/web/dao/project/ProjectMapper.java

@@ -0,0 +1,44 @@
+package seecoder.devcloud.web.dao.project;
+
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
+import seecoder.devcloud.web.model.po.project.Project;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface ProjectMapper {
+
+
+    @Select("select * from project")
+    @Results(id="projectMap",value = {
+            @Result(column = "git_remote_url", property = "gitRemoteUrl"),
+            @Result(column = "group_id", property = "groupId")
+    })
+    List<Project> listAll();
+
+    /**
+     * 插入,自增ID
+     */
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    @Options(useGeneratedKeys = true, keyProperty = "param1.id")
+    int insertProject(Project project, String... ignoredCols);
+
+    @UpdateProvider(type= GeneralInsertUpdateSqlProvider.class, method="updateById")
+    int updateProject(Project project);
+
+    @Select("select * from project where group_id=#{groupId}")
+    @ResultMap(value = "projectMap")
+    List<Project> listProjectsByGroupId(int groupId);
+
+    @Select("select * from project where group_id in(select unique group_id from group_member where user_id=#{userId}")
+    @ResultMap(value = "projectMap")
+    List<Project> listProjectsByUserId(int userId);
+
+    @Select("select * from project where id=#{projectId}")
+    @ResultMap(value = "projectMap")
+    Project getProjectById(int projectId);
+
+}

+ 5 - 3
web/src/main/java/seecoder/devcloud/web/dao/provider/TreeNodeProvider.java

@@ -1,10 +1,10 @@
 package seecoder.devcloud.web.dao.provider;
 package seecoder.devcloud.web.dao.provider;
 
 
 import org.apache.ibatis.jdbc.SQL;
 import org.apache.ibatis.jdbc.SQL;
-import seecoder.devcloud.web.model.po.TreeNode;
+import seecoder.devcloud.web.model.po.tree.TreeNodePO;
 
 
 public class TreeNodeProvider {
 public class TreeNodeProvider {
-    public String updateTreeNode(TreeNode treeNode){
+    public String updateTreeNode(TreeNodePO TreeNodePO){
         return new SQL() {
         return new SQL() {
             {
             {
                 UPDATE("tree_nodes");
                 UPDATE("tree_nodes");
@@ -13,12 +13,14 @@ public class TreeNodeProvider {
                 SET("type=#{type}");
                 SET("type=#{type}");
                 SET("priority=#{priority}");
                 SET("priority=#{priority}");
                 SET("state=#{state}");
                 SET("state=#{state}");
-                SET("processor=#{processor}");
                 SET("time_to_take=#{timeToTake}");
                 SET("time_to_take=#{timeToTake}");
                 SET("start_time=#{startTime}");
                 SET("start_time=#{startTime}");
                 SET("end_time=#{endTime}");
                 SET("end_time=#{endTime}");
                 SET("is_leaf=#{leaf}");
                 SET("is_leaf=#{leaf}");
                 SET("group_id=#{groupId}");
                 SET("group_id=#{groupId}");
+                SET("project_id=#{projectId}");
+                SET("parent_id=#{parentId}");
+                SET("deep=#{deep}");
                 WHERE("id=#{id}");
                 WHERE("id=#{id}");
             }
             }
         }.toString();
         }.toString();

+ 29 - 0
web/src/main/java/seecoder/devcloud/web/dao/tree/TreeLogMapper.java

@@ -0,0 +1,29 @@
+package seecoder.devcloud.web.dao.tree;
+
+
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
+import seecoder.devcloud.web.model.po.tree.TreeLog;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface TreeLogMapper {
+
+    /**
+     * 插入,自增ID
+     */
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    @Options(useGeneratedKeys = true, keyProperty = "param1.id")
+    int insertTreeLog(TreeLog project, String... ignoredCols);
+
+    @Select("select * from tree_log where tree_id=#{treeId}")
+    @Results(id="treeLogMap",value = {
+            @Result(column = "user_name", property = "userName"),
+            @Result(column = "tree_id", property = "treeId"),
+            @Result(column = "user_id", property = "userId")
+    })
+    List<TreeLog> listTreeLogsByTreeId(int treeId);
+}

+ 29 - 11
web/src/main/java/seecoder/devcloud/web/dao/tree/TreeNodeMapper.java

@@ -3,8 +3,8 @@ package seecoder.devcloud.web.dao.tree;
 
 
 import org.apache.ibatis.annotations.*;
 import org.apache.ibatis.annotations.*;
 import org.springframework.stereotype.Repository;
 import org.springframework.stereotype.Repository;
+import seecoder.devcloud.web.model.po.tree.TreeNodePO;
 import seecoder.devcloud.web.dao.provider.TreeNodeProvider;
 import seecoder.devcloud.web.dao.provider.TreeNodeProvider;
-import seecoder.devcloud.web.model.po.TreeNode;
 
 
 import java.util.List;
 import java.util.List;
 
 
@@ -23,10 +23,12 @@ public interface TreeNodeMapper {
             @Result(column = "start_time", property = "startTime"),
             @Result(column = "start_time", property = "startTime"),
             @Result(column = "end_time", property = "endTime"),
             @Result(column = "end_time", property = "endTime"),
             @Result(column = "group_id", property = "groupId"),
             @Result(column = "group_id", property = "groupId"),
+            @Result(column = "project_id", property = "projectId"),
+            @Result(column = "parent_id", property = "parentId"),
             @Result(column = "state",property = "state"),
             @Result(column = "state",property = "state"),
             @Result(column = "type",property = "type")
             @Result(column = "type",property = "type")
     })
     })
-    List<TreeNode> listAllTreeNodes();
+    List<TreeNodePO> listAllTreeNodes();
 
 
     /**
     /**
      * 根据id获取TreeNode
      * 根据id获取TreeNode
@@ -35,33 +37,49 @@ public interface TreeNodeMapper {
      */
      */
     @Select({"select * from tree_nodes where id = #{id}"})
     @Select({"select * from tree_nodes where id = #{id}"})
     @ResultMap(value = "treeNodeMap")
     @ResultMap(value = "treeNodeMap")
-    TreeNode getTreeNodeById(@Param("id") int id);
+    TreeNodePO getTreeNodeById(@Param("id") int id);
 
 
     /**
     /**
      * 根据GroupId获取TreeNode
      * 根据GroupId获取TreeNode
-     * @param id
+     * @param groupId
      * @return
      * @return
      */
      */
     @Select({"select * from tree_nodes where group_id = #{groupId}"})
     @Select({"select * from tree_nodes where group_id = #{groupId}"})
     @ResultMap(value = "treeNodeMap")
     @ResultMap(value = "treeNodeMap")
-    List<TreeNode> listTreeNodesByGroupId(@Param("groupId") int id);
+    List<TreeNodePO> listTreeNodesByGroupId(@Param("groupId") int groupId);
+
+    /**
+     * 根据projectId获取TreeNode
+     * @param projectId
+     * @return
+     */
+    @Select({"select * from tree_nodes where project_id = #{projectId}"})
+    @ResultMap(value = "treeNodeMap")
+    List<TreeNodePO> listTreeNodesByProjectId(@Param("projectId") int projectId);
 
 
     /**
     /**
      * 插入treeNode
      * 插入treeNode
-     * @param treeNode
+     * @param TreeNodePO
      * @return treeNode的自增主键
      * @return treeNode的自增主键
      */
      */
-    @Insert({"insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) " +
-            "VALUES (#{title}, #{description}, #{type}, #{priority}, #{state}, #{processor}, #{timeToTake}, #{startTime}, #{endTime}, #{leaf}, #{groupId})"})
+    @Insert({"insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id,project_id,deep,parent_id) " +
+            "VALUES (#{title}, #{description}, #{type}, #{priority}, #{state}, #{timeToTake}, #{startTime}, #{endTime}, #{leaf}, #{groupId},#{projectId},#{deep},#{parentId})"})
     @Options(useGeneratedKeys = true, keyProperty = "id")
     @Options(useGeneratedKeys = true, keyProperty = "id")
-    int insertTreeNode(TreeNode treeNode);
+    int insertTreeNode(TreeNodePO TreeNodePO);
 
 
     /**
     /**
      * 更新TreeNode
      * 更新TreeNode
-     * @param treeNode
+     * @param TreeNodePO
      * @return
      * @return
      */
      */
     @UpdateProvider(type = TreeNodeProvider.class,method = "updateTreeNode")
     @UpdateProvider(type = TreeNodeProvider.class,method = "updateTreeNode")
-    int updateTreeNode(TreeNode treeNode);
+    int updateTreeNode(TreeNodePO TreeNodePO);
+
+    @Delete("delete from tree_nodes where id = #{nodeId}")
+    int deleteTreeNode(@Param("nodeId") int nodeId);
+    @Update("update tree_nodes set ")
+    int updateTreeNodeById(@Param("nodeId") int nodeId);
 
 
+//    @Delete("delete from group_member where group_id = #{groupId} and user_id = #{userId}")
+//    int delete(@Param("groupId") int groupId,@Param("userId")  int userId);
 }
 }

+ 0 - 22
web/src/main/java/seecoder/devcloud/web/dao/user/UserMapper.java

@@ -1,22 +0,0 @@
-package seecoder.devcloud.web.dao.user;
-
-import seecoder.devcloud.web.model.po.user.User;
-
-/**
- * 准确来说已经不是mybatis的mapper了
- * 因为集成了门户系统,用户数据需要从那取
- * 这里写成这种形式是为了不破坏三层结构
- */
-public interface UserMapper {
-
-	/**
-	 * 返回当前自己的用户信息
-	 * 由于集成了门户系统而且使用了jwt作为安全认证机制,自己的用户信息存放在 SecurityContextHolder中
-	 * 见 JwtAuthenticationTokenFilter.class
-	 * 注意:SecurityContextHolder采用的是ThreadLocal实现的
-	 *     如果要新开子线程,且子线程需要用到用户信息,务必在父线程把用户信息取出
-	 */
-	User findLoginUser();
-
-	User findUserByUsername(String username);
-}

+ 11 - 2
web/src/main/java/seecoder/devcloud/web/infrastructure/GlobalExceptionHandler.java

@@ -4,9 +4,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
 import seecoder.devcloud.common.exceptions.AccessDeniedException;
 import seecoder.devcloud.common.exceptions.AccessDeniedException;
 import seecoder.devcloud.common.exceptions.ConflictException;
 import seecoder.devcloud.common.exceptions.ConflictException;
 import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.common.exceptions.ServiceException;
+import seecoder.devcloud.web.infrastructure.security.TokenExpiredException;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.Response;
 
 
 /**
 /**
@@ -14,7 +16,7 @@ import seecoder.devcloud.web.model.vo.Response;
  * @date 2021/3/5
  * @date 2021/3/5
  * @description: 统一异常返回处理
  * @description: 统一异常返回处理
  */
  */
-@ControllerAdvice
+@RestControllerAdvice
 @Slf4j
 @Slf4j
 public class GlobalExceptionHandler {
 public class GlobalExceptionHandler {
 
 
@@ -27,8 +29,15 @@ public class GlobalExceptionHandler {
 
 
     @ExceptionHandler(Exception.class)
     @ExceptionHandler(Exception.class)
     @ResponseBody
     @ResponseBody
-    public Response serviceExceptionHandler(Exception e){
+    public Response exceptionHandler(Exception e){
         log.error("Error: ",e);
         log.error("Error: ",e);
         return Response.buildFailure(503,e.getMessage());
         return Response.buildFailure(503,e.getMessage());
     }
     }
+
+    @ExceptionHandler(TokenExpiredException.class)
+    @ResponseBody
+    public Response tokenExpiredExceptionHandler(TokenExpiredException e){
+        log.error("Error: ",e);
+        return Response.buildFailure(e.getCode(), e.getMessage());
+    }
 }
 }

+ 5 - 9
web/src/main/java/seecoder/devcloud/web/infrastructure/config/SwaggerConfig.java

@@ -1,19 +1,15 @@
 package seecoder.devcloud.web.infrastructure.config;
 package seecoder.devcloud.web.infrastructure.config;
 
 
-import org.glassfish.jersey.internal.guava.Predicates;
-import org.springframework.beans.factory.annotation.Value;
+
 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.http.ResponseEntity;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import springfox.boot.starter.autoconfigure.SpringfoxConfigurationProperties;
 import springfox.documentation.builders.ApiInfoBuilder;
 import springfox.documentation.builders.ApiInfoBuilder;
 import springfox.documentation.builders.PathSelectors;
 import springfox.documentation.builders.PathSelectors;
 import springfox.documentation.builders.RequestHandlerSelectors;
 import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.oas.annotations.EnableOpenApi;
 import springfox.documentation.service.ApiInfo;
 import springfox.documentation.service.ApiInfo;
 import springfox.documentation.spi.DocumentationType;
 import springfox.documentation.spi.DocumentationType;
 import springfox.documentation.spring.web.plugins.Docket;
 import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
 
 
 /**
 /**
  * @author PuHong Weng
  * @author PuHong Weng
@@ -21,7 +17,7 @@ import springfox.documentation.spring.web.plugins.Docket;
  * @description:
  * @description:
  */
  */
 @Configuration
 @Configuration
-@EnableOpenApi
+@EnableSwagger2
 public class SwaggerConfig{
 public class SwaggerConfig{
 
 
 
 
@@ -42,13 +38,13 @@ public class SwaggerConfig{
 
 
     @Bean
     @Bean
     public Docket restfulApi() {
     public Docket restfulApi() {
-        return new Docket(DocumentationType.OAS_30)
+        return new Docket(DocumentationType.SWAGGER_2)
                 .apiInfo(initApiInfo())
                 .apiInfo(initApiInfo())
                 .select()
                 .select()
                 //.paths(doFilteringRules())
                 //.paths(doFilteringRules())
                 //不显示错误的接口地址
                 //不显示错误的接口地址
                 .apis(RequestHandlerSelectors.basePackage("seecoder.devcloud.web.controller"))
                 .apis(RequestHandlerSelectors.basePackage("seecoder.devcloud.web.controller"))
-                .paths(Predicates.not(PathSelectors.regex("/error.*")))
+                //.paths(Predicates.not(PathSelectors.regex("/error.*")))
                 .paths(PathSelectors.any())
                 .paths(PathSelectors.any())
                 .build();
                 .build();
 
 

+ 19 - 1
web/src/main/java/seecoder/devcloud/web/infrastructure/config/WebSecurityConfig.java

@@ -20,6 +20,8 @@ import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
 import org.springframework.web.cors.CorsUtils;
 import org.springframework.web.cors.CorsUtils;
 import seecoder.devcloud.web.infrastructure.security.JwtAuthenticationTokenFilter;
 import seecoder.devcloud.web.infrastructure.security.JwtAuthenticationTokenFilter;
 import seecoder.devcloud.web.infrastructure.security.WebSecurityConstants;
 import seecoder.devcloud.web.infrastructure.security.WebSecurityConstants;
@@ -45,6 +47,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
 
     private final JwtAuthenticationTokenFilter filter;
     private final JwtAuthenticationTokenFilter filter;
 
 
+
+
     @Autowired
     @Autowired
     public WebSecurityConfig(JwtAuthenticationTokenFilter filter) {
     public WebSecurityConfig(JwtAuthenticationTokenFilter filter) {
         super();
         super();
@@ -89,6 +93,20 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
         return super.authenticationManagerBean() ;
         return super.authenticationManagerBean() ;
     }
     }
 
 
-
+    /**
+     * 本地测试时的跨域设置
+     */
+    @Bean
+    CorsConfigurationSource corsConfigurationSource(){
+        return httpServletRequest -> {
+            CorsConfiguration cfg = new CorsConfiguration();
+            cfg.addAllowedHeader("*");
+            cfg.addAllowedMethod("*");
+            cfg.addAllowedOrigin("http://localhost:3000");
+            cfg.setAllowCredentials(true);
+            cfg.checkOrigin("http://localhost:3000");
+            return cfg;
+        };
+    }
 
 
 }
 }

+ 10 - 8
web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.PrintWriter;
+import java.util.LinkedHashMap;
 
 
 
 
 /**
 /**
@@ -51,16 +52,16 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
             // 有token,验证正确性,签名不正确,会抛异常
             // 有token,验证正确性,签名不正确,会抛异常
             Claims claims = jwtTokenUtil.getClaimsFromToken(authHeader);
             Claims claims = jwtTokenUtil.getClaimsFromToken(authHeader);
             if (claims != null){
             if (claims != null){
+                LinkedHashMap<String,Object> userInfo = claims.get("user_info", LinkedHashMap.class);
                 UserDetails userDetails = User.builder()
                 UserDetails userDetails = User.builder()
-                        .id(claims.get("id",Integer.class))
-                        .username(claims.get("name",String.class))
-                        .email(claims.get("email",String.class))
-                        .phone(claims.get("phone",String.class))
-                        //todo 验证是否和门户身份一致
-                        .role(UserIdentity.valueOf(claims.get("role",String.class)))
+                        .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();
                         .build();
                 // 验证token是否过期
                 // 验证token是否过期
-                if (jwtTokenUtil.isTokenExpired(authHeader)) {
+                if (!jwtTokenUtil.isTokenExpired(authHeader)) {
                     //加载用户、角色、权限信息,Spring Security根据这些信息判断接口的访问权限
                     //加载用户、角色、权限信息,Spring Security根据这些信息判断接口的访问权限
                     UsernamePasswordAuthenticationToken authentication
                     UsernamePasswordAuthenticationToken authentication
                             = new UsernamePasswordAuthenticationToken(userDetails, null,
                             = new UsernamePasswordAuthenticationToken(userDetails, null,
@@ -72,15 +73,16 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
                     PrintWriter out = null ;
                     PrintWriter out = null ;
                     try{
                     try{
                         httpServletResponse.setCharacterEncoding("UTF-8");
                         httpServletResponse.setCharacterEncoding("UTF-8");
+                        httpServletResponse.setStatus(10010);
                         httpServletResponse.setContentType("application/json; charset=utf-8");
                         httpServletResponse.setContentType("application/json; charset=utf-8");
                         out = httpServletResponse.getWriter();
                         out = httpServletResponse.getWriter();
                         out.append(Response.buildFailure(10110,"Jwt token 过期").toString());
                         out.append(Response.buildFailure(10110,"Jwt token 过期").toString());
-                        return;
                     }
                     }
                     catch (Exception e){
                     catch (Exception e){
                         e.printStackTrace();
                         e.printStackTrace();
                         httpServletResponse.sendError(500);
                         httpServletResponse.sendError(500);
                     }
                     }
+                    return;
                 }
                 }
             }
             }
 
 

+ 20 - 0
web/src/main/java/seecoder/devcloud/web/infrastructure/security/TokenExpiredException.java

@@ -0,0 +1,20 @@
+package seecoder.devcloud.web.infrastructure.security;
+
+import lombok.Data;
+import org.springframework.http.HttpStatus;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/14
+ * @description:
+ */
+@Data
+public class TokenExpiredException extends Exception{
+
+    private int code = 10010;
+
+    public TokenExpiredException() {
+        super("JWT Token 已过期");
+
+    }
+}

+ 3 - 2
web/src/main/java/seecoder/devcloud/web/model/enums/NodeStateEnum.java

@@ -1,8 +1,9 @@
 package seecoder.devcloud.web.model.enums;
 package seecoder.devcloud.web.model.enums;
 
 
 public enum NodeStateEnum {
 public enum NodeStateEnum {
-    PROCESSING("0:进行中"),
-    FINISHED("1:已结束");
+    CREATED("0:已创建"),
+    PROCESSING("1:进行中"),
+    FINISHED("2:已结束");
 
 
     private String value;
     private String value;
 
 

+ 22 - 0
web/src/main/java/seecoder/devcloud/web/model/enums/OperationEnum.java

@@ -0,0 +1,22 @@
+package seecoder.devcloud.web.model.enums;
+
+/**
+ * TreeNode操作类型
+ */
+public enum  OperationEnum {
+    START("开启"),
+    RESTART("重新开启"),
+    UPDATE("更新"),
+    FINISH("结束");
+
+    private String value;
+
+    OperationEnum(String value){
+        this.value=value;
+    }
+
+    @Override
+    public String toString(){
+        return value;
+    }
+}

+ 1 - 0
web/src/main/java/seecoder/devcloud/web/model/enums/ResponseEnums.java

@@ -5,6 +5,7 @@ package seecoder.devcloud.web.model.enums;
  * @date 2021/2/1
  * @date 2021/2/1
  * @description:
  * @description:
  */
  */
+@Deprecated
 public enum ResponseEnums {
 public enum ResponseEnums {
 
 
     OK("200", "Ok"),
     OK("200", "Ok"),

+ 21 - 0
web/src/main/java/seecoder/devcloud/web/model/po/project/Project.java

@@ -0,0 +1,21 @@
+package seecoder.devcloud.web.model.po.project;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Chenyz
+ * @date 2021/3/10
+ * @description:
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Project {
+    private Integer id;
+    private String name;
+    private String gitRemoteUrl;
+    private String description;
+    private Integer groupId;
+}

+ 40 - 0
web/src/main/java/seecoder/devcloud/web/model/po/tree/TreeLog.java

@@ -0,0 +1,40 @@
+package seecoder.devcloud.web.model.po.tree;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import seecoder.devcloud.web.model.enums.OperationEnum;
+
+/**
+ * 树操作的日志类,用于后序进行数据分析
+ */
+@Data
+@NoArgsConstructor
+public class TreeLog {
+
+    private Integer id;
+
+    /**
+     * 操作时间
+     */
+    private String time;
+
+    /**
+     * 操作类型
+     */
+    private OperationEnum operation;
+
+    /**
+     * 树节点
+     */
+    private Integer treeId;
+
+    /**
+     * 操作人
+     */
+    private Integer userId;
+
+    /**
+     * 操作名
+     */
+    private String userName;
+}

+ 11 - 10
web/src/main/java/seecoder/devcloud/web/model/po/TreeNode.java → web/src/main/java/seecoder/devcloud/web/model/po/tree/TreeNodePO.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.model.po;
+package seecoder.devcloud.web.model.po.tree;
 
 
 
 
 
 
@@ -13,18 +13,19 @@ import seecoder.devcloud.web.model.enums.NodeTypeEnum;
 @AllArgsConstructor
 @AllArgsConstructor
 @NoArgsConstructor
 @NoArgsConstructor
 @EqualsAndHashCode
 @EqualsAndHashCode
-public class TreeNode {
+public class TreeNodePO {
     private int id;
     private int id;
-    private String title;
-    private String description;
-    private NodeTypeEnum type;
-    private int priority;
-    private NodeStateEnum state;
-    private String processor;
-    private int timeToTake;
+    private String title = "title";
+    private String description = "description";
+    private NodeTypeEnum type = NodeTypeEnum.TASK;
+    private int priority = 3;
+    private NodeStateEnum state = NodeStateEnum.PROCESSING;
+    private int timeToTake = 10;
     private String startTime;
     private String startTime;
     private String endTime;
     private String endTime;
     private boolean leaf;
     private boolean leaf;
     private int groupId;
     private int groupId;
-
+    private int projectId;
+    private int parentId;
+    private int deep;
 }
 }

+ 2 - 0
web/src/main/java/seecoder/devcloud/web/model/po/user/Group.java

@@ -1,6 +1,8 @@
 package seecoder.devcloud.web.model.po.user;
 package seecoder.devcloud.web.model.po.user;
 
 
 
 
+import lombok.Builder;
+import lombok.Data;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Builder;
 import lombok.Data;
 import lombok.Data;

+ 2 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/GitWebHookVO.java

@@ -1,5 +1,6 @@
 package seecoder.devcloud.web.model.vo;
 package seecoder.devcloud.web.model.vo;
 
 
+import io.swagger.annotations.ApiModel;
 import lombok.Data;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
 import lombok.ToString;
 import lombok.ToString;
@@ -8,6 +9,7 @@ import java.util.List;
 
 
 @Data
 @Data
 @ToString
 @ToString
+@ApiModel("git webhook设置")
 public class GitWebHookVO {
 public class GitWebHookVO {
     private String object_kind;
     private String object_kind;
     private String before;
     private String before;

+ 57 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/TreeNodeVO.java

@@ -0,0 +1,57 @@
+package seecoder.devcloud.web.model.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import seecoder.devcloud.web.model.enums.NodeStateEnum;
+import seecoder.devcloud.web.model.enums.NodeTypeEnum;
+import seecoder.devcloud.web.model.po.tree.TreeNodePO;
+
+
+@NoArgsConstructor
+@Data
+@AllArgsConstructor
+@ApiModel("树节点")
+public class TreeNodeVO {
+
+    @ApiModelProperty("树节点id")
+    private int id;
+
+    @ApiModelProperty("用户id")
+    private int userId; /*操作用户的ID*/
+
+    @ApiModelProperty("节点名称")
+    private String title;
+    @ApiModelProperty("节点描述")
+    private String description;
+
+    @ApiModelProperty("节点类型,有效值为 “0:需求”, “1:任务”")
+    private NodeTypeEnum type;
+    @ApiModelProperty("节点优先级")
+    private int priority;
+    @ApiModelProperty("节点状态类型,有效值为 “0:已创建”, “1:进行中”, “2:已结束”")
+    private NodeStateEnum state;
+    @ApiModelProperty("预计完成时间")
+    private int timeToTake;
+    @ApiModelProperty("起始时间")
+    private String startTime;
+    @ApiModelProperty("结束时间")
+    private String endTime;
+    @ApiModelProperty("是否为叶节点")
+    private boolean leaf;
+    @ApiModelProperty("所属组id")
+    private int groupId;
+    @ApiModelProperty("所属项目id")
+    private int projectId;
+    @ApiModelProperty("父节点id")
+    private int parentId;
+    @ApiModelProperty("节点深度")
+    private int deep;
+
+    public TreeNodeVO(TreeNodePO po){
+        BeanUtils.copyProperties(po,this);
+    }
+}

+ 35 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/project/ProjectVO.java

@@ -0,0 +1,35 @@
+package seecoder.devcloud.web.model.vo.project;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import seecoder.devcloud.web.model.po.project.Project;
+
+/**
+ * @author Chenyz
+ * @date 2021/3/10
+ * @description:
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel("项目信息")
+public class ProjectVO {
+    @ApiModelProperty("项目id")
+    private Integer id;
+    @ApiModelProperty("项目名称")
+    private String name;
+    @ApiModelProperty("项目gitlab url")
+    private String gitRemoteUrl;
+    @ApiModelProperty("项目描述")
+    private String description;
+    @ApiModelProperty("项目所属组id")
+    private Integer groupId;
+
+    public ProjectVO(Project project){
+        BeanUtils.copyProperties(project,this);
+    }
+}

+ 8 - 4
web/src/main/java/seecoder/devcloud/web/model/vo/user/UserVO.java

@@ -1,6 +1,8 @@
 package seecoder.devcloud.web.model.vo.user;
 package seecoder.devcloud.web.model.vo.user;
 
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
@@ -13,15 +15,17 @@ import java.sql.Timestamp;
 @Data
 @Data
 @NoArgsConstructor
 @NoArgsConstructor
 @AllArgsConstructor
 @AllArgsConstructor
+@ApiModel("用户")
 public class UserVO {
 public class UserVO {
+    @ApiModelProperty("用户id")
     private Integer id;
     private Integer id;
-
+    @ApiModelProperty("用户名")
     private String username;
     private String username;
-
+    @ApiModelProperty("手机")
     private String phone;
     private String phone;
-
+    @ApiModelProperty("邮箱")
     private String email;
     private String email;
-
+    @ApiModelProperty("角色")
     private UserIdentity role;
     private UserIdentity role;
 
 
     public UserVO(User user) {
     public UserVO(User user) {

+ 0 - 11
web/src/main/java/seecoder/devcloud/web/service/TreeNodeService.java

@@ -1,11 +0,0 @@
-package seecoder.devcloud.web.service;
-
-
-
-import seecoder.devcloud.web.model.po.TreeNode;
-
-import java.util.List;
-
-public interface TreeNodeService {
-    public List<TreeNode> getAllNodes();
-}

+ 3 - 5
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java

@@ -4,7 +4,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import seecoder.devcloud.web.dao.pipeline.PipelineHistoryMapper;
 import seecoder.devcloud.web.dao.pipeline.PipelineHistoryMapper;
 import seecoder.devcloud.web.dao.pipeline.PipelineMapper;
 import seecoder.devcloud.web.dao.pipeline.PipelineMapper;
-import seecoder.devcloud.web.dao.user.UserMapper;
 import seecoder.devcloud.web.model.po.pipeline.Pipeline;
 import seecoder.devcloud.web.model.po.pipeline.Pipeline;
 import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
 import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
 import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.po.user.User;
@@ -13,6 +12,7 @@ import seecoder.devcloud.web.model.vo.pipeline.PipelineCreateVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineInfoVO;
 import seecoder.devcloud.web.model.vo.pipeline.PipelineInfoVO;
 import seecoder.devcloud.web.service.pipeline.PipelineService;
 import seecoder.devcloud.web.service.pipeline.PipelineService;
+import seecoder.devcloud.web.service.user.UserService;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
@@ -30,14 +30,12 @@ public class PipelineServiceImpl implements PipelineService {
 
 
     private final PipelineMapper pipelineMapper;
     private final PipelineMapper pipelineMapper;
 
 
-    private final UserMapper userMapper;
 
 
 
 
     @Autowired
     @Autowired
-    public PipelineServiceImpl(PipelineHistoryMapper pipelineHistoryMapper, PipelineMapper pipelineMapper, UserMapper userMapper) {
+    public PipelineServiceImpl(PipelineHistoryMapper pipelineHistoryMapper, PipelineMapper pipelineMapper) {
         this.pipelineHistoryMapper = pipelineHistoryMapper;
         this.pipelineHistoryMapper = pipelineHistoryMapper;
         this.pipelineMapper = pipelineMapper;
         this.pipelineMapper = pipelineMapper;
-        this.userMapper = userMapper;
     }
     }
 
 
 
 
@@ -95,7 +93,7 @@ public class PipelineServiceImpl implements PipelineService {
      * 防止用户修改提交的参数从而修改其他组的流水线
      * 防止用户修改提交的参数从而修改其他组的流水线
      */
      */
     private void projectAuthentication(Integer projectId){
     private void projectAuthentication(Integer projectId){
-        User user = userMapper.findLoginUser();
+        User user = UserService.loginUser();
         //todo 鉴权
         //todo 鉴权
 
 
     }
     }

+ 55 - 0
web/src/main/java/seecoder/devcloud/web/service/impl/project/ProjectServiceImpl.java

@@ -0,0 +1,55 @@
+package seecoder.devcloud.web.service.impl.project;
+
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import seecoder.devcloud.web.dao.project.ProjectMapper;
+import seecoder.devcloud.web.model.po.project.Project;
+import seecoder.devcloud.web.service.project.ProjectService;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.project.ProjectVO;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class ProjectServiceImpl implements ProjectService {
+    @Autowired
+    ProjectMapper projectMapper;
+
+
+    @Override
+    public List<ProjectVO> listProjectsByGroupId(int groupId) {
+        List<Project> projects = projectMapper.listProjectsByGroupId(groupId);
+        return projects.stream().map(ProjectVO::new).collect(Collectors.toList());
+    }
+
+    @Override
+    // TODO:该方法待测试
+    public List<ProjectVO> listProjectsByUserId(int userId) {
+        List<Project> projects = projectMapper.listProjectsByUserId(userId);
+        return projects.stream().map(ProjectVO::new).collect(Collectors.toList());
+    }
+
+    @Override
+    public ProjectVO getProjectById(int projectId) {
+        Project project = projectMapper.getProjectById(projectId);
+        return new ProjectVO(project);
+    }
+
+    @Override
+    public ProjectVO createProject(ProjectVO projectVO) {
+        Project project = new Project();
+        BeanUtils.copyProperties(projectVO,project);
+
+        projectMapper.insertProject(project);
+        // TODO:在对应的gitlab仓库中注册WEBHOOK
+        return new ProjectVO(project);
+
+    }
+
+    @Override
+    public void deleteProject(int projectId) {
+        //TODO:不知道该怎么做,懒删除?还是直接删?
+    }
+}

+ 99 - 4
web/src/main/java/seecoder/devcloud/web/service/impl/tree/TreeNodeServiceImpl.java

@@ -1,20 +1,115 @@
 package seecoder.devcloud.web.service.impl.tree;
 package seecoder.devcloud.web.service.impl.tree;
 
 
 
 
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
+import seecoder.devcloud.common.exceptions.ServiceException;
+import seecoder.devcloud.web.aop.TreeLogging;
+
+import seecoder.devcloud.web.model.enums.NodeStateEnum;
+import seecoder.devcloud.web.model.enums.NodeTypeEnum;
+import seecoder.devcloud.web.model.enums.OperationEnum;
+import seecoder.devcloud.web.model.po.tree.TreeNodePO;
+import seecoder.devcloud.web.service.tree.TreeNodeService;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.TreeNodeVO;
 import seecoder.devcloud.web.dao.tree.TreeNodeMapper;
 import seecoder.devcloud.web.dao.tree.TreeNodeMapper;
-import seecoder.devcloud.web.model.po.TreeNode;
-import seecoder.devcloud.web.service.TreeNodeService;
+import seecoder.devcloud.web.utils.TimeUtils;
+
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
 
 
 import java.util.List;
 import java.util.List;
+import java.util.stream.Collectors;
 
 
 @Service
 @Service
 public class TreeNodeServiceImpl implements TreeNodeService {
 public class TreeNodeServiceImpl implements TreeNodeService {
     @Autowired
     @Autowired
     private TreeNodeMapper treeNodeMapper;
     private TreeNodeMapper treeNodeMapper;
     @Override
     @Override
-    public List<TreeNode> getAllNodes() {
-        return null;
+    public List<TreeNodeVO> getAllNodes() {
+        List<TreeNodePO> nodes = treeNodeMapper.listAllTreeNodes();
+        return nodes.stream().map(TreeNodeVO::new).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<TreeNodeVO> listTreeNodesByProjectId(int projectId) {
+        List<TreeNodePO> nodes = treeNodeMapper.listTreeNodesByProjectId(projectId);
+        return nodes.stream().map(TreeNodeVO::new).collect(Collectors.toList());
+    }
+
+    @Override
+    @TreeLogging(OperationEnum.START)
+    public void insertTreeNode(TreeNodeVO treeNodeVO) {
+        TreeNodePO treeNodePO = new TreeNodePO();
+        BeanUtils.copyProperties(treeNodeVO,treeNodePO);
+        int res = treeNodeMapper.insertTreeNode(treeNodePO);
+        // TODO:safety check
+        if (res <= 0) {
+            throw new ServiceException(503,"Insert failed!");
+        }
+    }
+
+    @Override
+    @TreeLogging(OperationEnum.UPDATE)
+    public void updateTreeNode(TreeNodeVO treeNodeVO) {
+        TreeNodePO treeNodePO = new TreeNodePO();
+        BeanUtils.copyProperties(treeNodeVO,treeNodePO);
+        int res = treeNodeMapper.updateTreeNode(treeNodePO);
+        // TODO:safety check
     }
     }
+
+    @Override
+    public void deleteTreeNode(int nodeId) {
+        treeNodeMapper.deleteTreeNode(nodeId);
+        // TODO:safety check
+    }
+
+    /**
+     * 根据父节点id插入一个新的子节点
+     * @param fatherId
+     * @return
+     */
+    @Override
+    @TreeLogging(OperationEnum.START)
+    public Integer insertTreeNodeByFatherNode(int fatherId) {
+        TreeNodePO treeNodePO = getDefaultTreeNodePO();
+        treeNodePO.setParentId(fatherId);
+        int res = treeNodeMapper.insertTreeNode(treeNodePO);
+        // TODO:safety check
+        if (res <= 0) {
+            throw new ServiceException(503,"Insert failed!");
+        }
+        return treeNodePO.getId();
+    }
+
+
+
+    /**
+     * 创建一个default的节点
+     * @param
+     * @return
+     */
+    private TreeNodePO getDefaultTreeNodePO() {
+        SimpleDateFormat format = TimeUtils.getSimpleDateFormat();
+
+        TreeNodePO treeNodePO = new TreeNodePO();
+        treeNodePO.setTitle("title");
+        treeNodePO.setDescription("description");
+        treeNodePO.setType(NodeTypeEnum.TASK);
+        treeNodePO.setPriority(3);
+        treeNodePO.setState(NodeStateEnum.CREATED);
+        treeNodePO.setTimeToTake(10);
+        treeNodePO.setStartTime(format.format(new Date()));
+        treeNodePO.setEndTime(format.format(new Date()));
+        treeNodePO.setLeaf(true);
+        treeNodePO.setGroupId(-1);
+        treeNodePO.setProjectId(-1);
+        treeNodePO.setDeep(-1);
+        treeNodePO.setId(1);
+        return treeNodePO;
+    }
+
 }
 }

+ 5 - 5
web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java

@@ -4,6 +4,8 @@ package seecoder.devcloud.web.service.impl.user;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.gitlab4j.api.GitLabApiException;
 import org.gitlab4j.api.GitLabApiException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 import seecoder.devcloud.api.gitlab.GitlabApi;
 import seecoder.devcloud.api.gitlab.GitlabApi;
@@ -12,12 +14,12 @@ import seecoder.devcloud.common.exceptions.EntityNotFoundException;
 import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.common.exceptions.ServiceException;
 import seecoder.devcloud.web.dao.user.GroupMapper;
 import seecoder.devcloud.web.dao.user.GroupMapper;
 import seecoder.devcloud.web.dao.user.GroupMemberMapper;
 import seecoder.devcloud.web.dao.user.GroupMemberMapper;
-import seecoder.devcloud.web.dao.user.UserMapper;
 import seecoder.devcloud.web.model.enums.GroupType;
 import seecoder.devcloud.web.model.enums.GroupType;
 import seecoder.devcloud.web.model.po.user.Group;
 import seecoder.devcloud.web.model.po.user.Group;
 import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.service.user.GroupService;
 import seecoder.devcloud.web.service.user.GroupService;
 import seecoder.devcloud.web.model.vo.user.GroupVO;
 import seecoder.devcloud.web.model.vo.user.GroupVO;
+import seecoder.devcloud.web.service.user.UserService;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
@@ -30,14 +32,12 @@ public class GroupServiceImpl implements GroupService {
     private final GroupMapper groupMapper;
     private final GroupMapper groupMapper;
     private final GroupMemberMapper groupMemberMapper;
     private final GroupMemberMapper groupMemberMapper;
     private final GitlabApi gitlabApi;
     private final GitlabApi gitlabApi;
-    private final UserMapper userMapper;
 
 
     @Autowired
     @Autowired
-    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, GitlabApi gitlabApi, UserMapper userMapper) {
+    public GroupServiceImpl(GroupMapper groupMapper, GroupMemberMapper groupMemberMapper, GitlabApi gitlabApi) {
         this.groupMapper = groupMapper;
         this.groupMapper = groupMapper;
         this.groupMemberMapper = groupMemberMapper;
         this.groupMemberMapper = groupMemberMapper;
         this.gitlabApi = gitlabApi;
         this.gitlabApi = gitlabApi;
-        this.userMapper = userMapper;
     }
     }
 
 
     @Override
     @Override
@@ -46,7 +46,7 @@ public class GroupServiceImpl implements GroupService {
         if (groupMapper.findGroupByName(name) != null){
         if (groupMapper.findGroupByName(name) != null){
             throw new ServiceException("您创建的小组名字已被使用!");
             throw new ServiceException("您创建的小组名字已被使用!");
         }
         }
-        User user = userMapper.findLoginUser();
+        User user = UserService.loginUser();
         List<User> members = new ArrayList<>();
         List<User> members = new ArrayList<>();
         members.add(user);
         members.add(user);
         GitlabGroup gitGroup;
         GitlabGroup gitGroup;

+ 4 - 12
web/src/main/java/seecoder/devcloud/web/service/impl/user/UserServiceImpl.java

@@ -2,13 +2,13 @@ package seecoder.devcloud.web.service.impl.user;
 
 
 
 
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
-import seecoder.devcloud.web.dao.user.UserMapper;
+import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.user.UserService;
 import seecoder.devcloud.web.service.user.UserService;
 
 
@@ -16,18 +16,10 @@ import seecoder.devcloud.web.service.user.UserService;
 @Slf4j
 @Slf4j
 public class UserServiceImpl implements UserService, UserDetailsService {
 public class UserServiceImpl implements UserService, UserDetailsService {
 
 
-
-
-	private final UserMapper userMapper;
-
-	@Autowired
-	public UserServiceImpl(UserMapper userMapper) {
-		this.userMapper = userMapper;
-	}
-
 	@Override
 	@Override
 	public UserVO getLoginUser(){
 	public UserVO getLoginUser(){
-		return new UserVO(userMapper.findLoginUser());
+		User loginUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+		return new UserVO(loginUser);
 	}
 	}
 
 
 
 

+ 39 - 0
web/src/main/java/seecoder/devcloud/web/service/project/ProjectService.java

@@ -0,0 +1,39 @@
+package seecoder.devcloud.web.service.project;
+
+import seecoder.devcloud.web.model.vo.project.ProjectVO;
+
+import java.util.List;
+
+public interface ProjectService {
+    /**
+     * 根据group找projects
+     * @return
+     */
+    List<ProjectVO> listProjectsByGroupId(int groupId);
+
+    /**
+     * 根据user找Project
+     * @return
+     */
+    List<ProjectVO> listProjectsByUserId(int userId);
+
+    /**
+     * 获取project
+     * @param projectId
+     * @return
+     */
+    ProjectVO getProjectById(int projectId);
+
+    /**
+     * 创建项目
+     * @param project 不包含id
+     * @return 注入id后返回
+     */
+    ProjectVO createProject(ProjectVO project);
+
+    /**
+     * 删除项目,懒删除
+     */
+    void deleteProject(int projectId);
+
+}

+ 48 - 0
web/src/main/java/seecoder/devcloud/web/service/tree/TreeNodeService.java

@@ -0,0 +1,48 @@
+package seecoder.devcloud.web.service.tree;
+
+
+
+
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.TreeNodeVO;
+
+import java.util.List;
+
+public interface TreeNodeService {
+
+    List<TreeNodeVO> getAllNodes();
+
+    /**
+     * 根据项目id获取该项目下的treeNode
+     * @param projectId
+     * @return
+     */
+    List<TreeNodeVO> listTreeNodesByProjectId(int projectId);
+
+    /**
+     * 新增一条需求
+     * @param treeNodeVO
+     */
+    void insertTreeNode(TreeNodeVO treeNodeVO);
+
+    /**
+     * 更新一条需求
+     * @param treeNodeVO
+     */
+    void updateTreeNode(TreeNodeVO treeNodeVO);
+
+    /**
+     * 删除一条需求,级联删除消息
+     * @param nodeId
+     */
+    void deleteTreeNode(int nodeId);
+
+    /**
+     * 根据父节点创建子节点
+     * @param fatherId
+     * @return
+     */
+    Integer insertTreeNodeByFatherNode(int fatherId);
+
+
+}

+ 8 - 1
web/src/main/java/seecoder/devcloud/web/service/user/UserService.java

@@ -1,11 +1,18 @@
 package seecoder.devcloud.web.service.user;
 package seecoder.devcloud.web.service.user;
 
 
 
 
+import org.springframework.security.core.context.SecurityContextHolder;
+import seecoder.devcloud.web.model.po.user.User;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.model.vo.user.UserVO;
 
 
 public interface UserService {
 public interface UserService {
 
 
     UserVO getLoginUser();
     UserVO getLoginUser();
 
 
-
+    /**
+     * 用于内部获取登🦌用户PO
+     */
+    static User loginUser(){
+        return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+    }
 }
 }

+ 15 - 0
web/src/main/java/seecoder/devcloud/web/utils/TimeUtils.java

@@ -0,0 +1,15 @@
+package seecoder.devcloud.web.utils;
+
+import java.text.SimpleDateFormat;
+
+/**
+ * @program: parent
+ * @description: 时间工具
+ * @author: xzh
+ * @date: 2021-03-10
+ **/
+public class TimeUtils {
+    public static SimpleDateFormat getSimpleDateFormat(){
+        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    }
+}

+ 39 - 0
web/src/main/resources/SQLScripts/project.sql

@@ -0,0 +1,39 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : localhost_3306
+ Source Server Type    : MySQL
+ Source Server Version : 80018
+ Source Host           : localhost:3306
+ Source Schema         : seecoder
+
+ Target Server Type    : MySQL
+ Target Server Version : 80018
+ File Encoding         : 65001
+
+ Date: 10/03/2021 23:54:40
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for project
+-- ----------------------------
+DROP TABLE IF EXISTS `project`;
+CREATE TABLE `project`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `description` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `git_remote_url` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+  `group_id` int(11) NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of project
+-- ----------------------------
+INSERT INTO `project` VALUES (1, '前端', 'DevCloud前端', 'http://gogs.seecoder.cn/HuangKaiSheng/seecoder-devcloud-frontend/src/master', 1);
+INSERT INTO `project` VALUES (2, '后端开发', '后端测试测试测试测试测试', 'http://gogs.seecoder.cn/WengPuHong/seecoder-devcloud', 1);
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 38 - 0
web/src/main/resources/SQLScripts/tree_log.sql

@@ -0,0 +1,38 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : localhost_3306
+ Source Server Type    : MySQL
+ Source Server Version : 80018
+ Source Host           : localhost:3306
+ Source Schema         : seecoder
+
+ Target Server Type    : MySQL
+ Target Server Version : 80018
+ File Encoding         : 65001
+
+ Date: 11/03/2021 09:46:42
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for tree_log
+-- ----------------------------
+DROP TABLE IF EXISTS `tree_log`;
+CREATE TABLE `tree_log`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `time` datetime(0) NULL DEFAULT NULL,
+  `operation` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `user_id` int(11) NULL DEFAULT NULL,
+  `tree_id` int(11) NULL DEFAULT NULL,
+  `user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of tree_log
+-- ----------------------------
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 25 - 9
web/src/main/resources/SQLScripts/trees.sql

@@ -1,4 +1,17 @@
 SET foreign_key_checks = 0;
 SET foreign_key_checks = 0;
+# 需求执行者
+drop table if exists treenode_processor;
+create table treenode_processor
+(
+    id           int auto_increment,
+    PRIMARY KEY (id),
+    tree_node_id int not null ,
+    processor_id int not null,
+    processor_name varchar(64) not null
+);
+insert into treenode_processor(tree_node_id, processor_id, processor_name) VALUES (1,1,"qinliu");
+
+# 需求节点
 drop table if exists tree_nodes;
 drop table if exists tree_nodes;
 create table tree_nodes
 create table tree_nodes
 (
 (
@@ -8,37 +21,40 @@ create table tree_nodes
     type         varchar(32)      default 0                 not null,
     type         varchar(32)      default 0                 not null,
     priority     int      default 0                 null,
     priority     int      default 0                 null,
     state        varchar(32)      default 0                 not null,
     state        varchar(32)      default 0                 not null,
-    processor    varchar(64)                        not null,
     time_to_take int      default 0                 not null,
     time_to_take int      default 0                 not null,
     start_time   datetime default CURRENT_TIMESTAMP null,
     start_time   datetime default CURRENT_TIMESTAMP null,
     end_time     datetime                           null,
     end_time     datetime                           null,
     is_leaf      int      default 0                 null,
     is_leaf      int      default 0                 null,
     group_id     int                                null,
     group_id     int                                null,
+    project_id   int                                null,
+    deep         int                                null,
+    parent_id     int                                null,
     constraint tree_nodes_id_uindex
     constraint tree_nodes_id_uindex
         unique (id)
         unique (id)
 );
 );
 
 
 alter table tree_nodes
 alter table tree_nodes
     add primary key (id);
     add primary key (id);
-insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) values ("test1","test1","REQUIREMENT",0,"PROCESSING","qinliu",10,"2021-1-1","2021-2-13",1,1);
-insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) values ("test2","test2","REQUIREMENT",0,"PROCESSING","qinliu",10,"2021-1-2","2021-2-13",1,1);
-insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) values ("test3","test3","REQUIREMENT",0,"PROCESSING","qinliu",10,"2021-1-3","2021-2-13",1,1);
+insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id, project_id, deep,parent_id) values ("test1","test1","REQUIREMENT",0,"PROCESSING",10,"2021-1-1","2021-2-13",1,1,1,1,1);
+insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id, project_id, deep,parent_id) values ("test2","test2","REQUIREMENT",0,"PROCESSING",10,"2021-1-2","2021-2-13",1,1,1,1,1);
+insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id, project_id, deep,parent_id) values ("test3","test3","REQUIREMENT",0,"PROCESSING",10,"2021-1-3","2021-2-13",1,1,1,1,1);
 
 
+# 信息 留言
 drop table if exists messages;
 drop table if exists messages;
-create table messages
+drop table if exists tree_messages;
+create table tree_messages
 (
 (
     message_id   int auto_increment,
     message_id   int auto_increment,
     creator      varchar(64)  not null,
     creator      varchar(64)  not null,
     tree_node_id int          null,
     tree_node_id int          null,
     detail       varchar(512) null,
     detail       varchar(512) null,
-    constraint messages_message_id_uindex
+    constraint tree_messages_message_id_uindex
         unique (message_id),
         unique (message_id),
     constraint tree_node_fk
     constraint tree_node_fk
         foreign key (tree_node_id) references tree_nodes (id)
         foreign key (tree_node_id) references tree_nodes (id)
             on update cascade on delete cascade
             on update cascade on delete cascade
 );
 );
-
-alter table messages
+alter table tree_messages
     add primary key (message_id);
     add primary key (message_id);
 
 
 drop table if exists tree_sides;
 drop table if exists tree_sides;
@@ -56,7 +72,7 @@ create table tree_sides
         foreign key (parent_id) references tree_nodes (id)
         foreign key (parent_id) references tree_nodes (id)
             on update cascade on delete cascade
             on update cascade on delete cascade
 );
 );
-
+# 树边,暂时用不到了
 alter table tree_sides
 alter table tree_sides
     add primary key (side_id);
     add primary key (side_id);
 
 

+ 59 - 0
web/src/main/resources/application-cyz.yml

@@ -0,0 +1,59 @@
+spring:
+  datasource:
+    url: jdbc:mysql://localhost:3306/seecoder?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
+    username: root
+    password: 123456
+
+  mail:
+    host: smtp.qq.com
+    username: 370774330@qq.com
+    password: qkoecnzivukvbibi
+    port: 465
+    protocol: smtp
+    properties:
+      mail:
+        smtp:
+          ssl:
+            enable: true
+          socketFactory.class: javax.net.ssl.SSLSocketFactory
+        debug: true
+server:
+  port: 8080
+
+mybatis:
+  configuration:
+    map-underscore-to-camel-case: true
+
+seecoder:
+  k8s:
+    api-server: https://192.168.99.105:8443
+    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmSXc4RlRjNUpBYVpGYWc4QzRDY1MzUWJad1JMdFhKcDI1cngzWGtiRlkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZjbG91ZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNicXY4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NmIxNzU1ZS0zZjE3LTQ1ZTctODFmYi01MTRhODA3NDRhMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGV2Y2xvdWQ6ZGVmYXVsdCJ9.W0Y1lR6LBi1ZjylBx35YeqYuq2u2AqH-ayK4FD-LDfC26E89DanOwSv9XLrRMnnDBZFS_ZCRBumbnDeMiS5vw2x7-QnrDqj1M5u9FB2fIJsz2LyUkOhATZZmTzj_Uhewvvg09aDKh16ttj6ZX27m-KVk_6MP-VfiuvZnCVxDbqRkRjK-zsor4ty1CEATPyKK-tvugAwS0RFNHUL94DamfZAq_t1PSnH5ZtEHq0uEMZxY2c7j6u9d_aD9lphm_ZpCy_C8OCHfanM21CQPDHlcJTW_aiOO6bAp8qdc1egPO5uIamHl6Zm0N3RkcsRp4DGOHrltTV9y_cGZHXSWmRHfxw
+    debugging: true
+  gitlab:
+    host: http://gitlab.192.168.99.105.nip.io
+    webHookProxy: http://localhost:3000
+    token: wXDeETv2Kmt-JhiApJ9H
+  mail:
+    from: 370774330@qq.com
+
+
+  jenkins:
+    host: http://192.168.68.79:8082
+    username: root
+    token: 11d7b9e4c1acac481904c25813e2ec1f0a
+  docker:
+    registry: 192.168.68.79:18082
+
+
+
+  registry:
+    host: 192.168.68.79:18082
+    username: admin
+    password: admin123
+    nexus-server: 192.168.68.79:18081
+    repo-name: sec-repo
+    clean-up-task: 83bb8249-71e8-4367-83b3-50c6f7518860
+
+  git:
+    password: mock
+    username: mock

+ 1 - 3
web/src/main/resources/application-wph.yml

@@ -26,9 +26,7 @@ mybatis:
 
 
 seecoder:
 seecoder:
   jwt:
   jwt:
-    secret: SEEC-1919810-OIDC-114514
-    expiration: 3600000
-
+    secret: U0VFQy0xOTE5ODEwLU9JREMtMTE0NTE0
   k8s:
   k8s:
     api-server: https://192.168.99.105:8443
     api-server: https://192.168.99.105:8443
     token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmSXc4RlRjNUpBYVpGYWc4QzRDY1MzUWJad1JMdFhKcDI1cngzWGtiRlkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZjbG91ZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNicXY4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NmIxNzU1ZS0zZjE3LTQ1ZTctODFmYi01MTRhODA3NDRhMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGV2Y2xvdWQ6ZGVmYXVsdCJ9.W0Y1lR6LBi1ZjylBx35YeqYuq2u2AqH-ayK4FD-LDfC26E89DanOwSv9XLrRMnnDBZFS_ZCRBumbnDeMiS5vw2x7-QnrDqj1M5u9FB2fIJsz2LyUkOhATZZmTzj_Uhewvvg09aDKh16ttj6ZX27m-KVk_6MP-VfiuvZnCVxDbqRkRjK-zsor4ty1CEATPyKK-tvugAwS0RFNHUL94DamfZAq_t1PSnH5ZtEHq0uEMZxY2c7j6u9d_aD9lphm_ZpCy_C8OCHfanM21CQPDHlcJTW_aiOO6bAp8qdc1egPO5uIamHl6Zm0N3RkcsRp4DGOHrltTV9y_cGZHXSWmRHfxw
     token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmSXc4RlRjNUpBYVpGYWc4QzRDY1MzUWJad1JMdFhKcDI1cngzWGtiRlkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZjbG91ZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNicXY4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NmIxNzU1ZS0zZjE3LTQ1ZTctODFmYi01MTRhODA3NDRhMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGV2Y2xvdWQ6ZGVmYXVsdCJ9.W0Y1lR6LBi1ZjylBx35YeqYuq2u2AqH-ayK4FD-LDfC26E89DanOwSv9XLrRMnnDBZFS_ZCRBumbnDeMiS5vw2x7-QnrDqj1M5u9FB2fIJsz2LyUkOhATZZmTzj_Uhewvvg09aDKh16ttj6ZX27m-KVk_6MP-VfiuvZnCVxDbqRkRjK-zsor4ty1CEATPyKK-tvugAwS0RFNHUL94DamfZAq_t1PSnH5ZtEHq0uEMZxY2c7j6u9d_aD9lphm_ZpCy_C8OCHfanM21CQPDHlcJTW_aiOO6bAp8qdc1egPO5uIamHl6Zm0N3RkcsRp4DGOHrltTV9y_cGZHXSWmRHfxw

+ 58 - 0
web/src/main/resources/application-xzh.yml

@@ -0,0 +1,58 @@
+spring:
+  datasource:
+    url: jdbc:mysql://localhost:3306/devcloud?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
+    username: root
+    password: xizhiheng921
+
+  mail:
+    host: smtp.qq.com
+    username: 370774330@qq.com
+    password: qkoecnzivukvbibi
+    port: 465
+    protocol: smtp
+    properties:
+      mail:
+        smtp:
+          ssl:
+            enable: true
+          socketFactory.class: javax.net.ssl.SSLSocketFactory
+        debug: true
+server:
+  port: 8080
+
+mybatis:
+  configuration:
+    map-underscore-to-camel-case: true
+
+seecoder:
+  k8s:
+    api-server: https://192.168.99.105:8443
+    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmSXc4RlRjNUpBYVpGYWc4QzRDY1MzUWJad1JMdFhKcDI1cngzWGtiRlkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZjbG91ZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNicXY4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NmIxNzU1ZS0zZjE3LTQ1ZTctODFmYi01MTRhODA3NDRhMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGV2Y2xvdWQ6ZGVmYXVsdCJ9.W0Y1lR6LBi1ZjylBx35YeqYuq2u2AqH-ayK4FD-LDfC26E89DanOwSv9XLrRMnnDBZFS_ZCRBumbnDeMiS5vw2x7-QnrDqj1M5u9FB2fIJsz2LyUkOhATZZmTzj_Uhewvvg09aDKh16ttj6ZX27m-KVk_6MP-VfiuvZnCVxDbqRkRjK-zsor4ty1CEATPyKK-tvugAwS0RFNHUL94DamfZAq_t1PSnH5ZtEHq0uEMZxY2c7j6u9d_aD9lphm_ZpCy_C8OCHfanM21CQPDHlcJTW_aiOO6bAp8qdc1egPO5uIamHl6Zm0N3RkcsRp4DGOHrltTV9y_cGZHXSWmRHfxw
+    debugging: true
+  gitlab:
+    host: http://gitlab.192.168.99.105.nip.io
+    webHookProxy: http://localhost:3000
+    token: wXDeETv2Kmt-JhiApJ9H
+  mail:
+    from: 370774330@qq.com
+
+
+  jenkins:
+    host: http://192.168.68.79:8082
+    username: root
+    token: 11d7b9e4c1acac481904c25813e2ec1f0a
+  docker:
+    registry: 192.168.68.79:18082
+
+
+
+  registry:
+    host: 192.168.68.79:18082
+    username: admin
+    password: admin123
+    nexus-server: 192.168.68.79:18081
+    repo-name: sec-repo
+    clean-up-task: 83bb8249-71e8-4367-83b3-50c6f7518860
+  git:
+    password: mock
+    username: mock

+ 1 - 1
web/src/main/resources/application.yml

@@ -1,3 +1,3 @@
 spring:
 spring:
   profiles:
   profiles:
-    active: wph
+    active: xzh

+ 78 - 0
web/src/test/java/seecoder/devcloud/web/dao/project/ProjectMapperTest.java

@@ -0,0 +1,78 @@
+package seecoder.devcloud.web.dao.project;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.web.dao.user.GroupMemberMapper;
+import seecoder.devcloud.web.model.po.project.Project;
+
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@MybatisTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+public class ProjectMapperTest {
+    @Autowired
+    ProjectMapper projectMapper;
+    @Autowired
+    GroupMemberMapper groupMemberMapper;
+
+    @Test
+    public void testInsert(){
+        Project project = new Project(null,"TEST","JUST A TEST","seecoder.cn",2);
+        projectMapper.insertProject(project);
+        Project project2 = projectMapper.getProjectById(project.getId());
+        assert project.equals(project2);
+    }
+
+    @Test
+    public void testUpdate(){
+        Project project2 = projectMapper.getProjectById(1);
+        project2.setName("modify");
+        project2.setDescription("modify description");
+        project2.setGitRemoteUrl("www.google.com");
+        project2.setGroupId(7);
+        projectMapper.updateProject(project2);
+        Project project = projectMapper.getProjectById(1);
+        System.out.println(project);
+        assert project2.equals(project);
+    }
+
+    @Test
+    public void testListProjectsByGroupId(){
+        List<Project> projects = projectMapper.listProjectsByGroupId(1);
+        boolean res = true;
+        for (Project project:projects){
+            if(project.getGroupId()!=1){
+                res = false;
+                break;
+            }
+        }
+        assert res;
+    }
+
+    /**
+     * 这个因为groupMemberMapper有外键,不好测
+     */
+//    @Test
+    public void testListProjectsByUserId(){
+        Project project = new Project(0,"test","seecoder.cn","decription",2);
+        projectMapper.insertProject(project);
+        // TODO:插入如下两条数据
+//        groupMemberMapper.insert(2,1);
+//        groupMemberMapper.insert(1,1);
+        List<Project> projects = projectMapper.listProjectsByUserId(1);
+        boolean res = true;
+        for (Project project1:projects){
+            System.out.println(project1);
+            if(project1.getGroupId()!=1||project1.getGroupId()!=2){
+                res = false;
+                break;
+            }
+        }
+        assert res;
+    }
+}

+ 43 - 0
web/src/test/java/seecoder/devcloud/web/dao/tree/TreeLogMapperTest.java

@@ -0,0 +1,43 @@
+package seecoder.devcloud.web.dao.tree;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.web.model.enums.OperationEnum;
+import seecoder.devcloud.web.model.po.tree.TreeLog;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@MybatisTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+public class TreeLogMapperTest {
+    @Autowired
+    TreeLogMapper treeLogMapper;
+
+    @Test
+    public void testInsertAndSelect(){
+        TreeLog treeLog = new TreeLog();
+        treeLog.setTreeId(1);
+        treeLog.setUserId(1);
+        treeLog.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+        treeLog.setUserName("test");
+        treeLog.setOperation(OperationEnum.START);
+        treeLogMapper.insertTreeLog(treeLog);
+        List<TreeLog> logList = treeLogMapper.listTreeLogsByTreeId(1);
+        boolean res = false;
+        for(TreeLog log:logList){
+            if(log.equals(treeLog)){
+                res = true;
+                System.out.println(log);
+                break;
+            }
+        }
+        assert res;
+    }
+}

+ 71 - 0
web/src/test/java/seecoder/devcloud/web/dao/tree/TreeNodeMapperTest.java

@@ -0,0 +1,71 @@
+package seecoder.devcloud.web.dao.tree;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.web.model.enums.NodeStateEnum;
+import seecoder.devcloud.web.model.enums.NodeTypeEnum;
+import seecoder.devcloud.web.model.po.tree.TreeNodePO;
+
+
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@MybatisTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+public class TreeNodeMapperTest {
+    @Autowired
+    TreeNodeMapper treeNodeMapper;
+
+    @Test
+    public void listAllTreeNodesTest(){
+        List<TreeNodePO> treeNodes =  treeNodeMapper.listAllTreeNodes();
+        for (TreeNodePO TreeNodePO:treeNodes){
+            System.out.println(TreeNodePO);
+        }
+        assert treeNodes.size()!=0;
+    }
+    
+    @Test
+    public void getTreeNodeByIdTest(){
+        TreeNodePO node = treeNodeMapper.getTreeNodeById(1);
+        System.out.println(node);
+        TreeNodePO node1 = new TreeNodePO(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,1,1);
+        assert node.equals(node1);
+    }
+    
+    @Test
+    public void listTreeNodesByGroupIdTest(){
+        List<TreeNodePO> treeNodes = treeNodeMapper.listTreeNodesByGroupId(1);
+        TreeNodePO node1 = new TreeNodePO(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,1,1);
+        for(TreeNodePO TreeNodePO:treeNodes){
+            if (TreeNodePO.getId()==1){
+                assert TreeNodePO.equals(node1);
+            }
+        }
+    }
+    
+    @Test
+    public void insertTreeNodeTest(){
+        TreeNodePO node1 = new TreeNodePO(0,"testInsert","testInsert", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,1,1);
+        int res = treeNodeMapper.insertTreeNode(node1);
+        TreeNodePO node = treeNodeMapper.getTreeNodeById(node1.getId());
+        System.out.println(node);
+        System.out.println(node1);
+        assert res==1;
+        assert node.equals(node1);
+    }
+    
+    @Test
+    public void updateTreeNodeTest(){
+        TreeNodePO node1 = new TreeNodePO(1,"update","update", NodeTypeEnum.TASK,1, NodeStateEnum.FINISHED,20,"2021-01-10 00:00:00","2021-02-15 00:00:00",false,2,1,1,1);
+        treeNodeMapper.updateTreeNode(node1);
+        TreeNodePO node = treeNodeMapper.getTreeNodeById(1);
+        System.out.println(node);
+        assert node.equals(node1);
+    }
+
+}

+ 0 - 71
web/src/test/java/seecoder/devcloud/web/dataMapper/TreeNodeMapperTest.java

@@ -1,71 +0,0 @@
-package seecoder.devcloud.web.dataMapper;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
-import org.springframework.test.context.junit4.SpringRunner;
-import seecoder.devcloud.web.dao.tree.TreeNodeMapper;
-import seecoder.devcloud.web.model.enums.NodeStateEnum;
-import seecoder.devcloud.web.model.enums.NodeTypeEnum;
-import seecoder.devcloud.web.model.po.TreeNode;
-
-import java.util.List;
-
-@RunWith(SpringRunner.class)
-@MybatisTest
-@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
-public class TreeNodeMapperTest {
-    @Autowired
-    TreeNodeMapper treeNodeMapper;
-
-    @Test
-    public void listAllTreeNodesTest(){
-        List<TreeNode> treeNodes =  treeNodeMapper.listAllTreeNodes();
-        for (TreeNode treeNode:treeNodes){
-            System.out.println(treeNode);
-        }
-        assert treeNodes.size()!=0;
-    }
-
-    @Test
-    public void getTreeNodeByIdTest(){
-        TreeNode node = treeNodeMapper.getTreeNodeById(1);
-        System.out.println(node);
-        TreeNode node1 = new TreeNode(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,"qinliu",10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1);
-        assert node.equals(node1);
-    }
-
-    @Test
-    public void listTreeNodesByGroupIdTest(){
-        List<TreeNode> treeNodes = treeNodeMapper.listTreeNodesByGroupId(1);
-        TreeNode node1 = new TreeNode(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,"qinliu",10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1);
-        for(TreeNode treeNode:treeNodes){
-            if (treeNode.getId()==1){
-                assert treeNode.equals(node1);
-            }
-        }
-    }
-
-    @Test
-    public void insertTreeNodeTest(){
-        TreeNode node1 = new TreeNode(0,"testInsert","testInsert", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,"qinliu",10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1);
-        int res = treeNodeMapper.insertTreeNode(node1);
-        TreeNode node = treeNodeMapper.getTreeNodeById(node1.getId());
-        System.out.println(node);
-        System.out.println(node1);
-        assert res==1;
-        assert node.equals(node1);
-    }
-
-    @Test
-    public void updateTreeNodeTest(){
-        TreeNode node1 = new TreeNode(1,"update","update", NodeTypeEnum.TASK,1, NodeStateEnum.FINISHED,"qinliu667",20,"2021-01-10 00:00:00","2021-02-15 00:00:00",false,2);
-        treeNodeMapper.updateTreeNode(node1);
-        TreeNode node = treeNodeMapper.getTreeNodeById(1);
-        System.out.println(node);
-        assert node.equals(node1);
-    }
-
-}

+ 40 - 0
web/src/test/java/seecoder/devcloud/web/service/TreeNodeServiceTest.java

@@ -0,0 +1,40 @@
+//package seecoder.devcloud.web.service;
+//
+//import org.junit.Before;
+//import org.junit.Test;
+//import org.junit.runner.RunWith;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.test.context.SpringBootTest;
+//import org.springframework.test.context.junit4.SpringRunner;
+//import org.springframework.transaction.annotation.Transactional;
+//import seecoder.devcloud.web.DevcloudWebApplication;
+//import seecoder.devcloud.web.model.enums.NodeStateEnum;
+//import seecoder.devcloud.web.model.enums.NodeTypeEnum;
+//import seecoder.devcloud.web.model.po.tree.TreeNodePO;
+//import seecoder.devcloud.web.service.tree.TreeNodeService;
+//import seecoder.devcloud.web.model.vo.TreeNodeVO;
+//
+//import java.util.List;
+//
+//@RunWith(SpringRunner.class)
+//@SpringBootTest(classes = DevcloudWebApplication.class)
+//@Transactional
+//public class TreeNodeServiceTest {
+//    @Autowired
+//    TreeNodeService treeNodeService;
+//    TreeNodeVO treeNodeVO;
+//
+//    @Before
+//    public void initTreeNodeVO(){
+//        treeNodeVO = new TreeNodeVO(1,1,"test5","test5", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,-1,0);
+//    }
+//
+//    @Test
+//    public void testInsert(){
+//        treeNodeService.insertTreeNode(treeNodeVO);
+//        List<TreeNodePO> treeNodePOList = treeNodeService.getAllNodes();
+//        for (TreeNodePO treeNode:treeNodePOList) {
+//            System.out.println(treeNode);
+//        }
+//    }
+//}

+ 55 - 0
web/src/test/java/seecoder/devcloud/web/service/project/ProjectServiceTest.java

@@ -0,0 +1,55 @@
+//package seecoder.devcloud.web.service.project;
+//
+//import io.swagger.annotations.Api;
+//import org.junit.Before;
+//import org.junit.Test;
+//import org.junit.runner.RunWith;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.test.context.SpringBootTest;
+//import org.springframework.test.context.junit4.SpringRunner;
+//import org.springframework.transaction.annotation.Transactional;
+//import seecoder.devcloud.web.DevcloudWebApplication;
+//import seecoder.devcloud.web.model.po.project.Project;
+//import seecoder.devcloud.web.model.vo.Response;
+//import seecoder.devcloud.web.model.vo.project.ProjectVO;
+//
+//import java.util.List;
+//
+//
+//@Api(tags = "GitLab Hook API")
+//@RunWith(SpringRunner.class)
+//@SpringBootTest(classes = DevcloudWebApplication.class)
+//@Transactional
+//public class ProjectServiceTest {
+//    @Autowired
+//    ProjectService projectService;
+//    ProjectVO projectVO;
+//
+//    @Before
+//    public void initProjectVO(){
+//        projectVO  = new ProjectVO(null,"TEST","JUST A TEST","seecoder.cn",2);
+//    }
+//
+//    @Test
+//    public void testInsert(){
+//        Response<Project> projectResponse = projectService.createProject(projectVO);
+//        assert projectResponse.getCode().equals(200);
+//        Project project = projectResponse.getData();
+//        System.out.println(project);
+//        assert project.getName().equals(projectVO.getName());
+//        assert project.getGitRemoteUrl().equals(projectVO.getGitRemoteUrl());
+//        assert project.getDescription().equals(projectVO.getDescription());
+//        assert project.getGroupId().equals(projectVO.getGroupId());
+//    }
+//
+//    @Test
+//    public void testListProjectsByGroupId(){
+//        Response<List<Project>>  listResponse = projectService.listProjectsByGroupId(1);
+//        assert listResponse.getCode().equals(200);
+//        for(Project project:listResponse.getData()){
+//            assert project.getGroupId()==1;
+//        }
+//    }
+//
+//
+//}