Explorar o código

Merge branch 'wph' into integration

370774330@qq.com %!s(int64=5) %!d(string=hai) anos
pai
achega
2185f444ba
Modificáronse 100 ficheiros con 1857 adicións e 1111 borrados
  1. 14 0
      api/pom.xml
  2. 12 1
      api/src/main/java/seecoder/devcloud/api/ApplicationProperties.java
  3. 9 0
      api/src/main/java/seecoder/devcloud/api/DevcloudApiAutoConfiguration.java
  4. 8 0
      api/src/main/java/seecoder/devcloud/api/git/GitApi.java
  5. 33 0
      api/src/main/java/seecoder/devcloud/api/git/impl/GitApiImpl.java
  6. 24 0
      common/pom.xml
  7. 6 0
      common/src/main/java/seecoder/devcloud/common/CommonAutoConfiguration.java
  8. 0 47
      common/src/main/java/seecoder/devcloud/common/constant/Constants.java
  9. 0 9
      common/src/main/java/seecoder/devcloud/common/exceptions/AlreadyInExaminationException.java
  10. 0 11
      common/src/main/java/seecoder/devcloud/common/exceptions/MalformedProblemException.java
  11. 2 2
      common/src/main/java/seecoder/devcloud/common/exceptions/ServiceException.java
  12. 0 13
      common/src/main/java/seecoder/devcloud/common/serializer/CustomLocalDateTimeDeserializer.java
  13. 0 13
      common/src/main/java/seecoder/devcloud/common/serializer/CustomLocalDateTimeSerializer.java
  14. 0 32
      common/src/main/java/seecoder/devcloud/common/serializer/TimestampLocalDateDeserializer.java
  15. 0 29
      common/src/main/java/seecoder/devcloud/common/serializer/TimestampLocalDateTimeSerializer.java
  16. 67 0
      common/src/main/java/seecoder/devcloud/common/util/JwtTokenUtil.java
  17. 0 41
      common/src/main/java/seecoder/devcloud/common/validate/FieldCompare.java
  18. 0 39
      common/src/main/java/seecoder/devcloud/common/validate/FieldEquals.java
  19. 0 38
      common/src/main/java/seecoder/devcloud/common/validate/validator/FieldCompareValidator.java
  20. 0 30
      common/src/main/java/seecoder/devcloud/common/validate/validator/FieldEqualsValidator.java
  21. 9 4
      core/src/main/java/seecoder/devcloud/core/pipeline/Context.java
  22. 3 0
      core/src/main/java/seecoder/devcloud/core/pipeline/Handler.java
  23. 11 2
      core/src/main/java/seecoder/devcloud/core/pipeline/Pipeline.java
  24. 0 15
      core/src/main/java/seecoder/devcloud/core/pipeline/PipelineConfig.java
  25. 10 0
      core/src/main/java/seecoder/devcloud/core/pipeline/PipelineException.java
  26. 76 0
      core/src/main/java/seecoder/devcloud/core/pipeline/PipelineFactory.java
  27. 31 0
      core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfig.java
  28. 39 0
      core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfigTable.java
  29. 29 0
      core/src/main/java/seecoder/devcloud/core/pipeline/config/PipelineConfig.java
  30. 7 5
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/AbstractHandler.java
  31. 165 45
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/DockerImageBuildHandler.java
  32. 2 5
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sDeploymentHandler.java
  33. 5 9
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sNamespaceHandler.java
  34. 12 0
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sPVCHandler.java
  35. 1 8
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sServiceHandler.java
  36. 0 9
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/MavenPackageHandler.java
  37. 0 9
      core/src/main/java/seecoder/devcloud/core/pipeline/handler/MavenTestHandler.java
  38. 38 0
      core/src/main/java/seecoder/devcloud/core/pipeline/pipeline/PipelineImpl.java
  39. 1 8
      core/src/test/java/seecoder/devcloud/core/CoreApplicationTests.java
  40. 13 2
      web/pom.xml
  41. 1 1
      web/src/main/java/seecoder/devcloud/web/controller/gitlab/HookController.java
  42. 67 0
      web/src/main/java/seecoder/devcloud/web/controller/pipeline/DeploymentController.java
  43. 103 0
      web/src/main/java/seecoder/devcloud/web/controller/pipeline/PipelineController.java
  44. 8 34
      web/src/main/java/seecoder/devcloud/web/controller/user/UserController.java
  45. 29 0
      web/src/main/java/seecoder/devcloud/web/dao/impl/UserMapperImpl.java
  46. 34 0
      web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineHistoryMapper.java
  47. 39 0
      web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineMapper.java
  48. 3 3
      web/src/main/java/seecoder/devcloud/web/dao/provider/GeneralInsertUpdateSqlProvider.java
  49. 1 1
      web/src/main/java/seecoder/devcloud/web/dao/provider/TreeNodeProvider.java
  50. 1 1
      web/src/main/java/seecoder/devcloud/web/dao/tree/TreeNodeMapper.java
  51. 2 2
      web/src/main/java/seecoder/devcloud/web/dao/user/GroupMapper.java
  52. 2 5
      web/src/main/java/seecoder/devcloud/web/dao/user/GroupMemberMapper.java
  53. 13 26
      web/src/main/java/seecoder/devcloud/web/dao/user/UserMapper.java
  54. 11 4
      web/src/main/java/seecoder/devcloud/web/infrastructure/GlobalExceptionHandler.java
  55. 5 0
      web/src/main/java/seecoder/devcloud/web/infrastructure/config/SwaggerConfig.java
  56. 94 0
      web/src/main/java/seecoder/devcloud/web/infrastructure/config/WebSecurityConfig.java
  57. 94 0
      web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java
  58. 0 81
      web/src/main/java/seecoder/devcloud/web/infrastructure/security/WebSecurityConfiguration.java
  59. 38 16
      web/src/main/java/seecoder/devcloud/web/infrastructure/security/WebSecurityConstants.java
  60. 1 1
      web/src/main/java/seecoder/devcloud/web/model/enums/GroupType.java
  61. 1 1
      web/src/main/java/seecoder/devcloud/web/model/enums/NodeStateEnum.java
  62. 1 1
      web/src/main/java/seecoder/devcloud/web/model/enums/NodeTypeEnum.java
  63. 1 5
      web/src/main/java/seecoder/devcloud/web/model/enums/ResponseEnums.java
  64. 7 2
      web/src/main/java/seecoder/devcloud/web/model/enums/UserIdentity.java
  65. 3 5
      web/src/main/java/seecoder/devcloud/web/model/po/TreeNodePO.java
  66. 33 0
      web/src/main/java/seecoder/devcloud/web/model/po/pipeline/Deployment.java
  67. 30 0
      web/src/main/java/seecoder/devcloud/web/model/po/pipeline/Pipeline.java
  68. 45 0
      web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelineHistory.java
  69. 0 0
      web/src/main/java/seecoder/devcloud/web/model/po/project/Project.java
  70. 0 0
      web/src/main/java/seecoder/devcloud/web/model/po/tree/TreeLog.java
  71. 2 2
      web/src/main/java/seecoder/devcloud/web/model/po/user/Group.java
  72. 67 0
      web/src/main/java/seecoder/devcloud/web/model/po/user/User.java
  73. 1 1
      web/src/main/java/seecoder/devcloud/web/model/vo/GitWebHookVO.java
  74. 43 0
      web/src/main/java/seecoder/devcloud/web/model/vo/Response.java
  75. 0 0
      web/src/main/java/seecoder/devcloud/web/model/vo/TreeNodeVO.java
  76. 35 0
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/DeploymentInfoVO.java
  77. 28 0
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineConfigVO.java
  78. 24 0
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineCreateVO.java
  79. 45 0
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineHistoryVO.java
  80. 52 0
      web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineInfoVO.java
  81. 0 0
      web/src/main/java/seecoder/devcloud/web/model/vo/project/ProjectVO.java
  82. 2 2
      web/src/main/java/seecoder/devcloud/web/model/vo/user/GroupVO.java
  83. 1 1
      web/src/main/java/seecoder/devcloud/web/model/vo/user/RegisterVO.java
  84. 9 11
      web/src/main/java/seecoder/devcloud/web/model/vo/user/UserVO.java
  85. 0 53
      web/src/main/java/seecoder/devcloud/web/po/user/User.java
  86. 31 0
      web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/DeploymentServiceImpl.java
  87. 102 0
      web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java
  88. 6 7
      web/src/main/java/seecoder/devcloud/web/service/impl/tree/TreeNodeServiceImpl.java
  89. 8 9
      web/src/main/java/seecoder/devcloud/web/service/impl/user/GroupServiceImpl.java
  90. 16 128
      web/src/main/java/seecoder/devcloud/web/service/impl/user/UserServiceImpl.java
  91. 31 0
      web/src/main/java/seecoder/devcloud/web/service/pipeline/DeploymentService.java
  92. 57 0
      web/src/main/java/seecoder/devcloud/web/service/pipeline/PipelineService.java
  93. 1 4
      web/src/main/java/seecoder/devcloud/web/service/user/GroupService.java
  94. 2 19
      web/src/main/java/seecoder/devcloud/web/service/user/UserService.java
  95. 0 70
      web/src/main/java/seecoder/devcloud/web/vo/Response.java
  96. 0 25
      web/src/main/java/seecoder/devcloud/web/vo/user/ChangePasswordVO.java
  97. 0 85
      web/src/main/java/seecoder/devcloud/web/vo/user/CustomUserDetails.java
  98. 0 24
      web/src/main/java/seecoder/devcloud/web/vo/user/GroupDTO.java
  99. 0 31
      web/src/main/java/seecoder/devcloud/web/vo/user/InnerGroupVO.java
  100. 0 24
      web/src/main/java/seecoder/devcloud/web/vo/user/UserDTO.java

+ 14 - 0
api/pom.xml

@@ -25,6 +25,12 @@
 
 
     <dependencies>
+        <!-- https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit -->
+        <dependency>
+            <groupId>org.eclipse.jgit</groupId>
+            <artifactId>org.eclipse.jgit</artifactId>
+            <version>5.9.0.202009080501-r</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-jpa</artifactId>
@@ -145,6 +151,14 @@
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
                 <version>2.3.7.RELEASE</version>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.springframework.boot</groupId>
+                            <artifactId>spring-boot-configuration-processor</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
                 <executions>
                     <execution>
                         <id>repackage</id>

+ 12 - 1
api/src/main/java/seecoder/devcloud/api/ApplicationProperties.java

@@ -33,7 +33,8 @@ public class ApplicationProperties {
 	private K8s k8s = new K8s();
 	@Valid
 	private Registry registry = new Registry();
-
+	@Valid
+	private Git git = new Git();
 
 	@Data
 	public static class Gitlab {
@@ -128,4 +129,14 @@ public class ApplicationProperties {
 		private String cleanUpTask = "4da7e1e1-2b28-46b5-a080-9d834cc96019";
 	}
 
+	@Data
+	public static class Git {
+		@NotEmpty
+		private String username;
+		@NotEmpty
+		private String password;
+	}
+
+
+
 }

+ 9 - 0
api/src/main/java/seecoder/devcloud/api/DevcloudApiAutoConfiguration.java

@@ -1,10 +1,13 @@
 package seecoder.devcloud.api;
 
+import org.eclipse.jgit.api.Git;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import seecoder.devcloud.api.docker.DockerApi;
 import seecoder.devcloud.api.docker.impl.DockerApiImpl;
+import seecoder.devcloud.api.git.GitApi;
+import seecoder.devcloud.api.git.impl.GitApiImpl;
 import seecoder.devcloud.api.gitlab.GitlabApi;
 import seecoder.devcloud.api.gitlab.impl.GitlabApiImpl;
 import seecoder.devcloud.api.jenkins.JenkinsApi;
@@ -33,6 +36,12 @@ public class DevcloudApiAutoConfiguration {
         return new GitlabApiImpl(applicationProperties());
     }
 
+    @Bean
+    @ConditionalOnBean(ApplicationProperties.class)
+    public GitApi gitApi(){
+        return new GitApiImpl(applicationProperties());
+    }
+
     @Bean
     @ConditionalOnBean(ApplicationProperties.class)
     public K8sApiConfiguration k8sApiConfiguration(){

+ 8 - 0
api/src/main/java/seecoder/devcloud/api/git/GitApi.java

@@ -0,0 +1,8 @@
+package seecoder.devcloud.api.git;
+
+import org.eclipse.jgit.api.Git;
+
+public interface GitApi {
+
+    Git clone(String repoUrl, String directory) throws Exception;
+}

+ 33 - 0
api/src/main/java/seecoder/devcloud/api/git/impl/GitApiImpl.java

@@ -0,0 +1,33 @@
+package seecoder.devcloud.api.git.impl;
+
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.transport.CredentialsProvider;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import seecoder.devcloud.api.ApplicationProperties;
+import seecoder.devcloud.api.git.GitApi;
+
+import java.io.File;
+
+@Component
+public class GitApiImpl implements GitApi {
+
+    private CredentialsProvider credentialsProvider;
+
+    @Autowired
+    public GitApiImpl(ApplicationProperties properties) {
+        ApplicationProperties.Git gitProperties = properties.getGit();
+        credentialsProvider = new UsernamePasswordCredentialsProvider(gitProperties.getUsername(), gitProperties.getPassword());
+    }
+
+    @Override
+    public Git clone(String repoUrl, String directory) throws Exception {
+        Git git = Git.cloneRepository()
+                .setCredentialsProvider(credentialsProvider)
+                .setURI(repoUrl)
+                .setDirectory(new File(directory)).call();
+        return git;
+    }
+}

+ 24 - 0
common/pom.xml

@@ -39,11 +39,27 @@
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <optional>true</optional>
         </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.0</version>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -96,6 +112,14 @@
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
                 <version>2.3.4.RELEASE</version>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.springframework.boot</groupId>
+                            <artifactId>spring-boot-configuration-processor</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
                 <executions>
                     <execution>
                         <id>repackage</id>

+ 6 - 0
common/src/main/java/seecoder/devcloud/common/CommonAutoConfiguration.java

@@ -1,7 +1,9 @@
 package seecoder.devcloud.common;
 
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import seecoder.devcloud.common.util.JwtTokenUtil;
 import seecoder.devcloud.common.util.SpringUtil;
 
 /**
@@ -17,4 +19,8 @@ public class CommonAutoConfiguration {
         return new SpringUtil();
     }
 
+    @Bean
+    JwtTokenUtil jwtTokenUtil(){
+        return new JwtTokenUtil();
+    }
 }

+ 0 - 47
common/src/main/java/seecoder/devcloud/common/constant/Constants.java

@@ -1,47 +0,0 @@
-package seecoder.devcloud.common.constant;
-
-public abstract class Constants {
-
-    public static final String NAME_PATTERN = "^[0-9a-zA-Z-]{8,}$";
-
-    //标签域名前缀
-    private static final String LABEL_PREFIX = "demo.seec.nju.cn";
-    //课程前缀
-    public static final String TYPE_LABEL = LABEL_PREFIX + "/type";
-    //描述
-    public static final String DESCRIPTION_LABEL = LABEL_PREFIX + "/description";
-    //应用
-    public static final String APPLICATION_LABEL = LABEL_PREFIX + "/app";
-
-    public static final String DEPLOY_ID_LABEL = LABEL_PREFIX + "/deployid";
-    // 用户namespace的label
-    public static final String USERSPACE_LABEL = LABEL_PREFIX +"/userspace";
-    // pod的label
-    public static final String SELECTOR_LABEL = LABEL_PREFIX + "/app";
-    // 非对外service的label
-    public static final String INTERNAL_LABEL = LABEL_PREFIX + "/internal";
-    // 对外service的label
-    public static final String EXTERNAL_LABEL = LABEL_PREFIX + "/external";
-    // 持久卷访问模式
-    public static final String STORAGE_ACCESS_MODE = "ReadWriteMany";
-    // 持久卷存储类型
-    public static final String STORAGE_CLASS = "glusterfs";
-
-    public static final String RESOURCE_STORAGE = "storage";
-
-    public static final String STARTS_AT_LABEL = LABEL_PREFIX + "/start";
-
-    public static final String ENDS_AT_LABEL = LABEL_PREFIX + "/end";
-
-    public static final String PRETTY_FORMAT = "true";
-
-    //cascade清除策略
-    //Deployment必须使用Foreground,否则只会删除Replica Set 不会删除底下的Pod
-    //https://github.com/kubernetes/kubeadm/issues/149#issuecomment-284766613
-    public static final String FOREGROUND_PROPAGATION_POLICY = "Foreground";
-
-    public static final String METADATA_NAME_SELECTOR = "metadata.name=";
-
-    public static final String DB_SECRET_NAME = "db-secret";
-
-}

+ 0 - 9
common/src/main/java/seecoder/devcloud/common/exceptions/AlreadyInExaminationException.java

@@ -1,9 +0,0 @@
-package seecoder.devcloud.common.exceptions;
-
-public class AlreadyInExaminationException extends ConflictException {
-	private static final String MESSAGE = "已经参加了所选考试!";
-
-	public AlreadyInExaminationException() {
-		super(MESSAGE);
-	}
-}

+ 0 - 11
common/src/main/java/seecoder/devcloud/common/exceptions/MalformedProblemException.java

@@ -1,11 +0,0 @@
-package seecoder.devcloud.common.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class MalformedProblemException extends ServiceException {
-	private static final HttpStatus HTTP_STATUS = HttpStatus.BAD_REQUEST;
-
-	public MalformedProblemException(String message) {
-		super(HTTP_STATUS.value(), message);
-	}
-}

+ 2 - 2
common/src/main/java/seecoder/devcloud/common/exceptions/ServiceException.java

@@ -7,7 +7,7 @@ import org.springframework.http.HttpStatus;
 @Getter
 @ToString
 public class ServiceException extends RuntimeException {
-	private int error;
+	private int code;
 
 	public ServiceException() {
 		this(HttpStatus.INTERNAL_SERVER_ERROR.value(), HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
@@ -23,7 +23,7 @@ public class ServiceException extends RuntimeException {
 
 	public ServiceException(int error, String message) {
 		super(message);
-		this.error = error;
+		this.code = error;
 	}
 
 	private static String message(int error) {

+ 0 - 13
common/src/main/java/seecoder/devcloud/common/serializer/CustomLocalDateTimeDeserializer.java

@@ -1,13 +0,0 @@
-package seecoder.devcloud.common.serializer;
-
-import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
-
-import java.time.format.DateTimeFormatter;
-
-public class CustomLocalDateTimeDeserializer extends LocalDateTimeDeserializer {
-	private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
-
-	public CustomLocalDateTimeDeserializer() {
-		super(FORMATTER);
-	}
-}

+ 0 - 13
common/src/main/java/seecoder/devcloud/common/serializer/CustomLocalDateTimeSerializer.java

@@ -1,13 +0,0 @@
-package seecoder.devcloud.common.serializer;
-
-import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
-
-import java.time.format.DateTimeFormatter;
-
-public class CustomLocalDateTimeSerializer extends LocalDateTimeSerializer {
-	private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
-
-	public CustomLocalDateTimeSerializer() {
-		super(FORMATTER);
-	}
-}

+ 0 - 32
common/src/main/java/seecoder/devcloud/common/serializer/TimestampLocalDateDeserializer.java

@@ -1,32 +0,0 @@
-package seecoder.devcloud.common.serializer;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-
-public class TimestampLocalDateDeserializer extends JsonDeserializer<LocalDateTime> {
-	@Override
-	public LocalDateTime deserialize(JsonParser p, DeserializationContext context) throws IOException {
-		Long epochSecond = null;
-		if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
-			epochSecond = p.getLongValue();
-		} else if (p.hasToken(JsonToken.VALUE_STRING)) {
-			String value = p.getText().trim();
-			try {
-				epochSecond = Long.valueOf(value);
-			} catch (NumberFormatException e) {
-				epochSecond = null;
-			}
-		}
-		if (epochSecond != null) {
-			return LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault());
-		}
-		return null;
-	}
-}

+ 0 - 29
common/src/main/java/seecoder/devcloud/common/serializer/TimestampLocalDateTimeSerializer.java

@@ -1,29 +0,0 @@
-package seecoder.devcloud.common.serializer;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
-import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
-
-import java.io.IOException;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
-
-public class TimestampLocalDateTimeSerializer extends LocalDateTimeSerializer {
-	@Override
-	protected LocalDateTimeSerializer withFormat(Boolean useTimestamp, DateTimeFormatter f, JsonFormat.Shape shape) {
-		return this;
-	}
-
-	@Override
-	public void serialize(LocalDateTime value, JsonGenerator g, SerializerProvider provider) throws IOException {
-		g.writeNumber(value.atZone(ZoneId.systemDefault()).toEpochSecond());
-	}
-
-	@Override
-	public void serializeWithType(LocalDateTime value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException {
-		serialize(value, g, provider);
-	}
-}

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

@@ -0,0 +1,67 @@
+package seecoder.devcloud.common.util;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Date;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ * 与门户系统对接,其返回的token如下,详细见
+ * https://www.yuque.com/gcbqv7/zp5lcv/ikf11b
+ * {
+ *   "iss": "p.seecoder.cn",
+ *   "sub": "17301xxxx67",
+ *   "aud": "seec-mooc",
+ *   "auth_time": 1606xxxx481,
+ *   "iat": 16061xxx481,
+ *   "exp": 16061xx,
+ *   "user_info": {
+ *     "phone": "17301xxxxx",
+ *     "email": "adxxx
+ *     "id": 4x9,
+ *     "name": "admin",
+ *     "role": "ADMIN"
+ *   }
+ * }
+ */
+@Data
+@ConfigurationProperties(prefix = "seecoder.jwt")
+@Configuration
+public class JwtTokenUtil {
+
+    private String secret;
+
+    private Long expiration;
+
+    /**
+     * 使用自己方法判断超时是为了后端可以在 小于等于门户过期时间的范围内,自由调控过期时间
+     */
+    public Boolean isTokenExpired(String token) {
+        try {
+            Claims claims = getClaimsFromToken(token);
+            Date expiration = claims.getExpiration();
+            return expiration.before(new Date());
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    public Claims getClaimsFromToken(String token) {
+        Claims claims;
+        try {
+            claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
+        } catch (Exception e) {
+            claims = null;
+        }
+        return claims;
+    }
+
+}

+ 0 - 41
common/src/main/java/seecoder/devcloud/common/validate/FieldCompare.java

@@ -1,41 +0,0 @@
-package seecoder.devcloud.common.validate;
-
-
-import seecoder.devcloud.common.validate.validator.FieldCompareValidator;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Repeatable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-@Target({TYPE, ANNOTATION_TYPE})
-@Retention(RUNTIME)
-@Repeatable(FieldCompare.List.class)
-@Constraint(validatedBy = FieldCompareValidator.class)
-@Documented
-public @interface FieldCompare {
-	String message() default "{com.moekr.moocoder.util.validate.FieldCompare}";
-
-	Class<?>[] groups() default {};
-
-	Class<? extends Payload>[] payload() default {};
-
-	String lessField();
-
-	String greaterField();
-
-	boolean allowEqual() default false;
-
-	@Target({TYPE, ANNOTATION_TYPE})
-	@Retention(RUNTIME)
-	@Documented
-	@interface List {
-		FieldCompare[] value();
-	}
-}

+ 0 - 39
common/src/main/java/seecoder/devcloud/common/validate/FieldEquals.java

@@ -1,39 +0,0 @@
-package seecoder.devcloud.common.validate;
-
-import seecoder.devcloud.common.validate.validator.FieldEqualsValidator;
-
-import javax.validation.Constraint;
-import javax.validation.Payload;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Repeatable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-@Target({TYPE, ANNOTATION_TYPE})
-@Retention(RUNTIME)
-@Repeatable(FieldEquals.List.class)
-@Constraint(validatedBy = FieldEqualsValidator.class)
-@Documented
-public @interface FieldEquals {
-	String message() default "{com.moekr.moocoder.util.validate.FieldEquals}";
-
-	Class<?>[] groups() default {};
-
-	Class<? extends Payload>[] payload() default {};
-
-	String firstField();
-
-	String secondField();
-
-	@Target({TYPE, ANNOTATION_TYPE})
-	@Retention(RUNTIME)
-	@Documented
-	@interface List {
-		FieldEquals[] value();
-	}
-
-}

+ 0 - 38
common/src/main/java/seecoder/devcloud/common/validate/validator/FieldCompareValidator.java

@@ -1,38 +0,0 @@
-package seecoder.devcloud.common.validate.validator;
-
-import org.springframework.beans.BeanUtils;
-import seecoder.devcloud.common.validate.FieldCompare;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-
-public class FieldCompareValidator implements ConstraintValidator<FieldCompare, Object> {
-	private String lessField;
-	private String greaterField;
-	private boolean allowEqual;
-
-
-	@Override
-	public void initialize(FieldCompare constraintAnnotation) {
-		this.lessField = constraintAnnotation.lessField();
-		this.greaterField = constraintAnnotation.greaterField();
-		this.allowEqual = constraintAnnotation.allowEqual();
-	}
-
-	@Override
-	@SuppressWarnings("unchecked")
-	public boolean isValid(Object value, ConstraintValidatorContext context) {
-		try {
-			Comparable lessObject = (Comparable) BeanUtils.getPropertyDescriptor(value.getClass(), lessField).getReadMethod().invoke(value);
-			Comparable greaterObject = (Comparable) BeanUtils.getPropertyDescriptor(value.getClass(), greaterField).getReadMethod().invoke(value);
-			int result = lessObject.compareTo(greaterObject);
-			if (allowEqual && result == 0) {
-				return true;
-			} else {
-				return result < 0;
-			}
-		} catch (Exception e) {
-			return false;
-		}
-	}
-}

+ 0 - 30
common/src/main/java/seecoder/devcloud/common/validate/validator/FieldEqualsValidator.java

@@ -1,30 +0,0 @@
-package seecoder.devcloud.common.validate.validator;
-
-import org.springframework.beans.BeanUtils;
-import seecoder.devcloud.common.validate.FieldEquals;
-
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-import java.util.Objects;
-
-public class FieldEqualsValidator implements ConstraintValidator<FieldEquals, Object> {
-	private String firstField;
-	private String secondField;
-
-	@Override
-	public void initialize(FieldEquals constraintAnnotation) {
-		this.firstField = constraintAnnotation.firstField();
-		this.secondField = constraintAnnotation.secondField();
-	}
-
-	@Override
-	public boolean isValid(Object value, ConstraintValidatorContext context) {
-		try {
-			Object firstObject = BeanUtils.getPropertyDescriptor(value.getClass(), firstField).getReadMethod().invoke(value);
-			Object secondObject = BeanUtils.getPropertyDescriptor(value.getClass(), secondField).getReadMethod().invoke(value);
-			return Objects.equals(firstObject, secondObject);
-		} catch (Exception e) {
-			return false;
-		}
-	}
-}

+ 9 - 4
core/src/main/java/seecoder/devcloud/core/pipeline/Context.java

@@ -2,9 +2,11 @@ package seecoder.devcloud.core.pipeline;
 
 import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 import seecoder.devcloud.api.ApplicationProperties;
 
 import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @author PuHong Weng
@@ -13,18 +15,20 @@ import java.util.HashMap;
  */
 @Data
 @Builder
+@NoArgsConstructor
 public class Context {
 
     private ApplicationProperties applicationProperties;
 
-    private String pipelineId;
+    private Integer pipelineId;
 
     private String pipelineName;
 
+
     /**
-     * 流水线所属小组
+     * 流水线所属namespace
      */
-    private String groupName;
+    private String namespace;
 
     /**
      * 项目名称
@@ -35,7 +39,8 @@ public class Context {
     /**
      * 用来存放一些杂项信息,根据key去取
      */
-    private HashMap<String, String> configs;
+    @Builder.Default
+    private Map<String, String> configs = new HashMap<>();
 
 
 }

+ 3 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/Handler.java

@@ -1,5 +1,7 @@
 package seecoder.devcloud.core.pipeline;
 
+import seecoder.devcloud.core.pipeline.handler.AbstractHandler;
+
 /**
  * @author PuHong Weng
  * @date 2021/1/18
@@ -13,4 +15,5 @@ public interface Handler {
 
     void invokeNext(Context context);
 
+    void setNextHandler(Handler nextHandler);
 }

+ 11 - 2
core/src/main/java/seecoder/devcloud/core/pipeline/Pipeline.java

@@ -3,11 +3,20 @@ package seecoder.devcloud.core.pipeline;
 /**
  * @author PuHong Weng
  * @date 2021/1/18
- * @description:
+ * @description: pipeline实体
  */
 public interface Pipeline {
 
-    void init(PipelineConfig config);
     void start();
+
     Context getContext();
+
+    /**
+     * 用于方便用户给pipeline中context的config添加配置
+     */
+    default Context addContextConfig(String key, String value) {
+        Context context = getContext( );
+        context.getConfigs().put(key, value);
+        return context;
+    };
 }

+ 0 - 15
core/src/main/java/seecoder/devcloud/core/pipeline/PipelineConfig.java

@@ -1,15 +0,0 @@
-package seecoder.devcloud.core.pipeline;
-
-import lombok.Data;
-
-/**
- * @author PuHong Weng
- * @date 2021/2/2
- * @description:
- */
-@Data
-public class PipelineConfig {
-
-
-    private String configJson;
-}

+ 10 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/PipelineException.java

@@ -0,0 +1,10 @@
+package seecoder.devcloud.core.pipeline;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/10
+ * @description: 流水线模块出现的异常的包装
+ */
+public class PipelineException extends RuntimeException{
+    //todo exception
+}

+ 76 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/PipelineFactory.java

@@ -0,0 +1,76 @@
+package seecoder.devcloud.core.pipeline;
+
+import seecoder.devcloud.core.pipeline.config.HandlerConfig;
+import seecoder.devcloud.core.pipeline.config.HandlerConfigTable;
+import seecoder.devcloud.core.pipeline.config.PipelineConfig;
+import seecoder.devcloud.core.pipeline.pipeline.PipelineImpl;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/10
+ * @description:
+ */
+public class PipelineFactory {
+    /**
+     * 流水线初始化
+     * @param configJson configJson 流水线配置的json字符串
+     * @param namespace 流水线所属的namespace,需要用户自己指定,例如devcloud后端使用用户所属的groupName中作为namespace
+     * @param projectName 流水线所属的project,需要用户自己指定
+     * @param pipelineId 流水线标识符,需要用户自己指定
+     * @param pipelineName 流水线名称,需要用户自己指定
+     * @return
+     */
+    public static Pipeline init(String configJson, String namespace, String projectName, Integer pipelineId, String pipelineName) {
+
+        PipelineConfig pipelineConfig = PipelineConfig.init(configJson);
+
+        //初始化context
+        Context context = Context.builder()
+                .projectName(projectName)
+                .namespace(namespace)
+                .pipelineId(pipelineId)
+                .pipelineName(pipelineName)
+                .build();
+
+        Handler firstHandler = initHandlerChainAndContext(pipelineConfig,context.getConfigs());
+
+        return new PipelineImpl(firstHandler, context);
+    }
+
+    /**
+     * 根据 handlerConfig 构筑 Handler 的流水线,以及将配置属性统一放入 Context
+     * @param pipelineConfig 流水线配置
+     * @param configs 将此handler配置的所有config加入context中的config中
+     *                (所以这一步要避免配置的覆盖,即不要用相同名字的key)
+     * @return
+     */
+    private static Handler initHandlerChainAndContext(PipelineConfig pipelineConfig, Map<String,String> configs){
+        Handler firstHandler = null;
+        Handler currentHandler = null;
+
+        //转换成对应的Handler实例
+        List<HandlerConfig> handlerConfigs = pipelineConfig.getHandlerConfigs();
+
+
+        HandlerConfig firstHandlerConfig = handlerConfigs.get(0);
+        //todo 相同名字的key可能导致覆盖 这里应该抛出warning
+        configs.putAll(firstHandlerConfig.getConfigs());
+        firstHandler = HandlerConfigTable.transToHandler(firstHandlerConfig);
+        currentHandler = firstHandler;
+
+
+        for (int i = 1; i < handlerConfigs.size(); i++){
+            HandlerConfig nextHandlerConfig = handlerConfigs.get(i);
+            //todo 相同名字的key可能导致覆盖 这里应该抛出warning
+            configs.putAll(nextHandlerConfig.getConfigs());
+            Handler nextHandler = HandlerConfigTable.transToHandler(nextHandlerConfig);
+            currentHandler.setNextHandler(nextHandler);
+            currentHandler = nextHandler;
+        }
+
+        return firstHandler;
+    }
+}

+ 31 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfig.java

@@ -0,0 +1,31 @@
+package seecoder.devcloud.core.pipeline.config;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/10
+ * @description:
+ */
+
+import lombok.Builder;
+import lombok.Data;
+import seecoder.devcloud.core.pipeline.Handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 代表着pipeline的一个handler配置实体
+ */
+@Data
+@Builder
+public class HandlerConfig{
+
+    private String name;
+
+    /**
+     * 对应Handler的配置
+     */
+    @Builder.Default
+    private Map<String,String> configs = new HashMap<>();
+
+}

+ 39 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/config/HandlerConfigTable.java

@@ -0,0 +1,39 @@
+package seecoder.devcloud.core.pipeline.config;
+
+import lombok.extern.slf4j.Slf4j;
+import seecoder.devcloud.core.pipeline.Handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/10
+ * @description: 表驱动,记录HandlerConfig到Handler的映射
+ *      todo doc config配置关系
+ */
+@Slf4j
+public class HandlerConfigTable {
+
+    private static final Map<String, Class<?>> handlerConfigMap;
+
+    /**
+     * 表驱动的设置
+     * 注意这里的对应并不是一一对应,而是多对一
+     */
+    static {
+        handlerConfigMap = new HashMap<>();
+        //todo 加入表
+    }
+
+    public static Handler transToHandler(HandlerConfig config){
+        Handler handler = null;
+        try {
+            handler = (Handler) handlerConfigMap.get(config).newInstance();
+        } catch (InstantiationException | IllegalAccessException e) {
+            log.error("流水线配置转换发生错误",e);
+            //todo throw pipeline exception
+        }
+        return handler;
+    }
+}

+ 29 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/config/PipelineConfig.java

@@ -0,0 +1,29 @@
+package seecoder.devcloud.core.pipeline.config;
+
+import lombok.Builder;
+import lombok.Data;
+import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.Handler;
+import seecoder.devcloud.core.pipeline.Pipeline;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/2/2
+ * @description: pipeline配置的实体,由对应的pipeline config json转换过来
+ */
+@Data
+public class PipelineConfig {
+
+    private List<HandlerConfig> handlerConfigs;
+
+    public static PipelineConfig init(String configJson){
+        PipelineConfig pipelineConfig = null;
+        //todo jackson转换配置实体
+        return pipelineConfig;
+    }
+
+}

+ 7 - 5
core/src/main/java/seecoder/devcloud/core/pipeline/handler/AbstractHandler.java

@@ -4,8 +4,6 @@ import lombok.Data;
 import seecoder.devcloud.core.pipeline.Context;
 import seecoder.devcloud.core.pipeline.Handler;
 
-import java.util.HashMap;
-
 /**
  * @author PuHong Weng
  * @date 2021/2/2
@@ -15,7 +13,7 @@ import java.util.HashMap;
 public abstract class AbstractHandler implements Handler {
 
 
-    public AbstractHandler nextHandler;
+    public Handler nextHandler;
 
 //    /**
 //     * 用来存放Handler的配置
@@ -24,16 +22,20 @@ public abstract class AbstractHandler implements Handler {
 
     @Override
     public void invoke(Context context) {
+        //todo 改成异步的
         process(context);
         invokeNext(context);
     }
 
     @Override
     public void invokeNext(Context context) {
-        nextHandler.invoke(context);
+        if (nextHandler != null){
+            nextHandler.invoke(context);
+        }
     }
 
-    public void setNextHandler(AbstractHandler nextHandler) {
+    @Override
+    public void setNextHandler(Handler nextHandler) {
         this.nextHandler = nextHandler;
     }
 }

+ 165 - 45
core/src/main/java/seecoder/devcloud/core/pipeline/handler/DockerImageBuildHandler.java

@@ -1,48 +1,168 @@
-package seecoder.devcloud.core.pipeline.handler;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FileUtils;
-import seecoder.devcloud.api.docker.DockerApi;
-import seecoder.devcloud.common.util.SpringUtil;
-import seecoder.devcloud.core.pipeline.Context;
-import seecoder.devcloud.core.pipeline.Handler;
-
-import java.io.*;
-import java.nio.file.Files;
-
-/**
- * @author PuHong Weng
- * @date 2021/1/18
- * @description: docker镜像构建
- */
-@Slf4j
-public class DockerImageBuildHandler extends AbstractHandler {
-
-    private static final String TEMP_PREFIX = "SEECODER-DEVCLOUD-";
-
-    public DockerApi dockerApi;
-
-    public DockerImageBuildHandler(){
-        dockerApi = SpringUtil.getBean(DockerApi.class);
-    }
-
-    @Override
-    public void process(Context context){
-//        File tempDir = null;
+//package seecoder.devcloud.core.pipeline.handler;
+//
+//import com.spotify.docker.client.ProgressHandler;
+//import com.spotify.docker.client.exceptions.DockerException;
+//import com.spotify.docker.client.messages.ProgressMessage;
+//import io.kubernetes.client.openapi.models.*;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.io.FileUtils;
+//import org.apache.commons.lang.StringUtils;
+//import org.eclipse.jgit.api.Git;
+//import org.eclipse.jgit.api.ResetCommand;
+//import org.springframework.util.CollectionUtils;
+//import seecoder.devcloud.api.ApplicationProperties;
+//import seecoder.devcloud.api.docker.DockerApi;
+//import seecoder.devcloud.api.git.GitApi;
+//import seecoder.devcloud.api.gitlab.GitlabApi;
+//import seecoder.devcloud.common.exceptions.Asserts;
+//import seecoder.devcloud.common.util.SpringUtil;
+//import seecoder.devcloud.core.pipeline.Context;
+//import seecoder.devcloud.core.pipeline.Handler;
+//
+//import java.io.*;
+//import java.nio.file.Files;
+//import java.nio.file.Path;
+//import java.nio.file.Paths;
+//import java.time.LocalDateTime;
+//import java.util.*;
+//import java.util.stream.Collectors;
+//
+///**
+// * @author PuHong Weng
+// * @date 2021/1/18
+// * @description: docker镜像构建
+// */
+//@Slf4j
+//public class DockerImageBuildHandler extends AbstractHandler {
+//
+//    private static final String TEMP_PREFIX = "SEECODER-DEVCLOUD-";
+//
+//    public DockerApi dockerApi;
+//
+//    public GitlabApi gitlabApi;
+//
+//    public GitApi gitApi;
+//
+//    public DockerImageBuildHandler() {
+//        gitlabApi = SpringUtil.getBean(GitlabApi.class);
+//        dockerApi = SpringUtil.getBean(DockerApi.class);
+//        gitApi = SpringUtil.getBean(GitApi.class);
+//    }
+//
+//    @Override
+//    public void process(Context context) {
 //        try {
-//            tempDir = Files.createTempDirectory(TEMP_PREFIX).toFile();
-//            //
-//            File dockerFile = new File(tempDir, "Dockerfile");
-//            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dockerFile)))) {
-//                writer.write(question.getQuestionType().getHelper().dockerFile(question.getName()));
+//            String imageName = context.getGroupName() + "-" + context.getProjectName();
+//            String repoUrl = context.getConfigs().get("repoUrl");
+//
+//
+//            // 1. 有git从git拿到地址进行镜像构建构建并push
+//            try {
+//                Path directory = Files.createTempDirectory("seecoder-devcloud-");
+//                Git git = gitApi.clone(repoUrl, directory.toString());
+//                if (Files.exists(Paths.get(directory.toString(), "Dockerfile"))) {
+//                    git.reset().setMode(ResetCommand.ResetType.HARD).setRef(result.getBuildTypeValue()).call();
+//                    String imageTag = String.valueOf(new Date().getTime());
+//                    StringBuilder sb = new StringBuilder();
+//                    final int DEFAULT_BUFFER_LENGTH = 200;
+//                    final long MAX_BUFFER_SIZE = 1 << 18;
+//                    dockerApi.buildAndPush(directory.toString(), "seecoder-paas-" + labelValue, imageTag, new ProgressHandler() {
+//                        @Override
+//                        public void progress(ProgressMessage message) throws DockerException {
+//                            String value = message.stream();
+//                            if (value == null) {
+//                                value = "";
+//                            }
+//                            if (!StringUtils.isEmpty(message.error())) {
+//                                value += "\n" + message.error();
+//                            }
+//                            sb.append(value);
+//                            if (sb.length() > DEFAULT_BUFFER_LENGTH) {
+//                                result.setBuildOutput(result.getBuildOutput() + sb.toString());
+//                                if (result.getBuildOutput().length() > MAX_BUFFER_SIZE) {
+//                                    result.setBuildOutput(result.getBuildOutput().substring((int) (result.getBuildOutput().length() - MAX_BUFFER_SIZE)));
+//                                }
+//                                sb.setLength(0);
+//                                environmentDAO.save(result);
+//                            }
+//                        }
+//                    });
+//                    if (sb.length() > 0) {
+//                        result.setBuildOutput(result.getBuildOutput() + sb.toString());
+//                    }
+//                    imageName = applicationProperties.getK8s().getImageRegistry() + "/seecoder-paas-" + labelValue + ":" + imageTag;
+//                    result.setBuildStatus(BuildStatus.SUCCESS);
+//                    result.setDeployStatus(DeployStatus.DEPLOYING);
+//                    result.setDeployStartTime(LocalDateTime.now());
+//                    result.setImage(imageName);
+//                    environmentDAO.save(result);
+//                } else {
+//                    result.setBuildStatus(BuildStatus.FAIL);
+//                    result.setBuildOutput("找不到构建文件Dockerfile!");
+//                    environmentDAO.save(result);
+//                    throw new ServiceException("102", "找不到构建文件Dockerfile!");
+//                }
+//            } catch (Exception e) {
+//                result.setBuildStatus(BuildStatus.FAIL);
+//                if (!e.getLocalizedMessage().contains("Could not acquire image ID or digest following build")) {
+//                    result.setBuildOutput(e.getLocalizedMessage());
+//                }
+//                environmentDAO.save(result);
+//                LoggerUtil.error(logger, e, "构建失败!gitUrl={}, branchOrCommit={}", application.getGitUrl(), result.getBuildTypeValue());
+//                return;
 //            }
-//            //dockerApi.build(tempDir.getAbsolutePath(), question.getImageName(), question.getImageTag());
-//        } catch (IOException e){
-//            e.printStackTrace();
-//            log.error("镜像构建失败, 产生IO错误, {}", e.getMessage());
-//        } finally {
-//            FileUtils.deleteDirectory(tempDir);
+//        } else if (result.getBuildType() == BuildType.FROM_IMAGE) {
+//            result.setBuildStatus(BuildStatus.SUCCESS);
+//            result.setBuildOutput("镜像构建无需部署");
+//            result.setDeployStatus(DeployStatus.DEPLOYING);
+//            result.setDeployStartTime(LocalDateTime.now());
+//            result.setImage(imageName);
+//            environmentDAO.save(result);
 //        }
-    }
-
-}
+//
+//        String[] ports = (configContent.getServicePort() == null ? "" : configContent.getServicePort()).split(",");
+//        if (!StringUtils.isEmpty(configContent.getHostPrefix())) {
+//            for (String port : ports) {
+//                // ingress
+//                List<Ingress> ingresses = ingressApi.getByCondition(K8sObjectRequest.builder()
+//                        .name(labelValue + "-" + port)
+//                        .namespace(deploymentNamespace).labels(labelsMap).build());
+//                Ingress ingress = new Ingress();
+//                ingress.setNamespace(deploymentNamespace);
+//                ingress.setName(labelValue + "-" + port);
+//                ingress.setLabels(labelsMap);
+//                if (configContent.getIngressAnnotations() != null && configContent.getIngressAnnotations().get(port) != null) {
+//                    ingress.setAnnotations(configContent.getIngressAnnotations().get(port));
+//                }
+//                String ingressHost = configContent.getHostPrefix() + "-" + port + "." + deploymentHost;
+//                if (configContent.getIngressPort() != null) {
+//                    if (port.equals(configContent.getIngressPort())) {
+//                        ingressHost = configContent.getHostPrefix() + "." + deploymentHost;
+//                    }
+//                } else {
+//                    if (ports.length == 1 || port.equals("80")) {
+//                        ingressHost = configContent.getHostPrefix() + "." + deploymentHost;
+//                    }
+//                }
+//                ingress.setAnnotation(Ingress.REWRITE_ANNOTATION, Ingress.DEFAULT_REWRITE_PATH);
+//                ingress.setHttpRules(Collections.singletonList(
+//                        Ingress.IngressRule.builder().host(ingressHost).ruleValues(
+//                                Collections.singleton(Ingress.IngressPath.builder()
+//                                        .path("/")
+//                                        .serviceName(labelValue)
+//                                        .port(Integer.parseInt(port))
+//                                        .build())
+//                        ).build()
+//                ));
+//                if (CollectionUtils.isEmpty(ingresses) || ingresses.size() != 1) {
+//                    ingressApi.create(ingress);
+//                } else {
+//                    ingressApi.update(ingress);
+//                }
+//            }
+//        }
+//
+//        return;
+//    }
+//}
+//

+ 2 - 5
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sDeploymentHandler.java

@@ -1,7 +1,6 @@
 package seecoder.devcloud.core.pipeline.handler;
 
 import lombok.extern.slf4j.Slf4j;
-import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.DeploymentApi;
 import seecoder.devcloud.api.k8s.K8sConstants;
 import seecoder.devcloud.api.k8s.SecretApi;
@@ -9,15 +8,12 @@ import seecoder.devcloud.api.k8s.exception.K8sApiException;
 import seecoder.devcloud.api.k8s.model.Container;
 import seecoder.devcloud.api.k8s.model.ContainerPort;
 import seecoder.devcloud.api.k8s.model.Deployment;
-import seecoder.devcloud.api.k8s.model.K8sObjectRequest;
 import seecoder.devcloud.api.k8s.util.SecretTypeEnum;
 import seecoder.devcloud.api.k8s.vo.SecretVO;
 import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.core.pipeline.Context;
-import seecoder.devcloud.core.pipeline.Handler;
 
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -63,13 +59,14 @@ public class K8sDeploymentHandler extends AbstractHandler {
     public void process(Context context) {
         //配置初始化
         initConfig(context);
-        String groupName = context.getGroupName();
+        String groupName = context.getNamespace();
         String projectName = context.getProjectName();
 
         //配置容器暴露端口
         ContainerPort containerPort = ContainerPort.builder()
                 .port(port)
                 .build();
+
         //配置容器
         Container container = Container.builder()
                 .image(image)

+ 5 - 9
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sNamespaceHandler.java

@@ -1,18 +1,13 @@
 package seecoder.devcloud.core.pipeline.handler;
 
-import com.sun.xml.internal.stream.events.NamespaceImpl;
 import lombok.extern.slf4j.Slf4j;
-import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.NamespaceApi;
 import seecoder.devcloud.api.k8s.SecretApi;
 import seecoder.devcloud.api.k8s.exception.K8sApiException;
-import seecoder.devcloud.api.k8s.model.K8sObjectRequest;
 import seecoder.devcloud.api.k8s.model.Namespace;
 import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.core.pipeline.Context;
 
-import javax.swing.*;
-
 /**
  * @author PuHong Weng
  * @date 2021/2/2
@@ -33,15 +28,16 @@ public class K8sNamespaceHandler extends AbstractHandler {
     @Override
     public void process(Context context) {
         Namespace namespace = new Namespace();
-        namespace.setName(context.getGroupName());
+        namespace.setName(context.getNamespace());
 
         //todo namespace在底下资源未删除时,不能轻易删除重建,只能直接通过异常查是否已创建,丑陋,待修改
         try {
             namespace = namespaceApi.create(namespace);
             log.info("Namespace创建成功, {}", namespace);
-            //为命名空间配置私有镜像仓库密钥,使得此命名空间可以访问镜像仓库来部署容器
-            ApplicationProperties.Registry registry = context.getApplicationProperties().getRegistry();
-            secretApi.createPrivateRegistrySecret(context.getGroupName(), registry.getHost(), registry.getUsername(), registry.getPassword());
+            // todo namespace 镜像secret是否改成从service account注入,待调查
+//            //为命名空间配置私有镜像仓库密钥,使得此命名空间可以访问镜像仓库来部署容器
+//            ApplicationProperties.Registry registry = context.getApplicationProperties().getRegistry();
+//            secretApi.createPrivateRegistrySecret(context.getGroupName(), registry.getHost(), registry.getUsername(), registry.getPassword());
         } catch (K8sApiException e){
             if (e.getCode() == K8sApiException.ALREADY_EXIST){
                 log.info("Namespace已经存在, 无需新建");

+ 12 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sPVCHandler.java

@@ -0,0 +1,12 @@
+package seecoder.devcloud.core.pipeline.handler;
+
+import lombok.Data;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/10
+ * @description: 创建K8s 持久卷声明
+ */
+@Data
+public class K8sPVCHandler {
+}

+ 1 - 8
core/src/main/java/seecoder/devcloud/core/pipeline/handler/K8sServiceHandler.java

@@ -4,19 +4,12 @@ import lombok.extern.slf4j.Slf4j;
 import seecoder.devcloud.api.k8s.K8sConstants;
 import seecoder.devcloud.api.k8s.ServiceApi;
 import seecoder.devcloud.api.k8s.exception.K8sApiException;
-import seecoder.devcloud.api.k8s.model.K8sObject;
-import seecoder.devcloud.api.k8s.model.K8sObjectRequest;
 import seecoder.devcloud.api.k8s.model.Service;
 import seecoder.devcloud.api.k8s.model.ServicePort;
 import seecoder.devcloud.common.util.SpringUtil;
 import seecoder.devcloud.core.pipeline.Context;
-import seecoder.devcloud.core.pipeline.Handler;
 
-import java.util.Collection;
 import java.util.Collections;
-import java.util.stream.Collectors;
-
-import static seecoder.devcloud.api.k8s.K8sConstants.APPLICATION_LABEL;
 
 /**
  * @author PuHong Weng
@@ -44,7 +37,7 @@ public class K8sServiceHandler extends AbstractHandler {
 
         //配置K8s的service
         Service service = new Service();
-        service.setNamespace(context.getGroupName());
+        service.setNamespace(context.getNamespace());
         service.setName(context.getProjectName()+ K8sConstants.SERVICE_SUFFIX);
         //标签选择器选择 此项目对应的deployment的name
         service.setSelectors(Collections.singletonMap(K8sConstants.APPLICATION_LABEL, context.getProjectName()));

+ 0 - 9
core/src/main/java/seecoder/devcloud/core/pipeline/handler/MavenPackageHandler.java

@@ -1,9 +0,0 @@
-package seecoder.devcloud.core.pipeline.handler;
-
-/**
- * @author PuHong Weng
- * @date 2021/1/19
- * @description:
- */
-public class MavenPackageHandler {
-}

+ 0 - 9
core/src/main/java/seecoder/devcloud/core/pipeline/handler/MavenTestHandler.java

@@ -1,9 +0,0 @@
-package seecoder.devcloud.core.pipeline.handler;
-
-/**
- * @author PuHong Weng
- * @date 2021/1/19
- * @description:
- */
-public class MavenTestHandler {
-}

+ 38 - 0
core/src/main/java/seecoder/devcloud/core/pipeline/pipeline/PipelineImpl.java

@@ -0,0 +1,38 @@
+package seecoder.devcloud.core.pipeline.pipeline;
+
+import seecoder.devcloud.core.pipeline.Context;
+import seecoder.devcloud.core.pipeline.Handler;
+import seecoder.devcloud.core.pipeline.Pipeline;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/10
+ * @description:
+ */
+
+public class PipelineImpl implements Pipeline {
+
+    private Handler firstHandler;
+
+    public PipelineImpl(Handler firstHandler, Context context) {
+        this.firstHandler = firstHandler;
+        this.context = context;
+    }
+
+    private Context context;
+
+
+
+    @Override
+    public void start() {
+        //todo 流水线开始事件监听
+        firstHandler.invoke(context);
+        //todo 流水线开始事件监听
+    }
+
+    @Override
+    public Context getContext() {
+        return context;
+    }
+
+}

+ 1 - 8
core/src/test/java/seecoder/devcloud/core/CoreApplicationTests.java

@@ -1,23 +1,16 @@
 package seecoder.devcloud.core;
 
-import org.junit.Before;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.xml.NamespaceHandler;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 import seecoder.devcloud.api.ApplicationProperties;
 import seecoder.devcloud.api.k8s.DeploymentApi;
 import seecoder.devcloud.core.pipeline.Context;
-import seecoder.devcloud.core.pipeline.handler.K8sDeploymentHandler;
-import seecoder.devcloud.core.pipeline.Pipeline;
 import seecoder.devcloud.core.pipeline.handler.K8sNamespaceHandler;
 
-import java.util.Collection;
-
 @RunWith(SpringRunner.class)
 @SpringBootTest
 class CoreApplicationTests {
@@ -53,7 +46,7 @@ class CoreApplicationTests {
 
     private void mockContext(){
         this.context = Context.builder()
-                .groupName("test-group")
+                .namespace("test-group")
                 .projectName("test-project")
                 .applicationProperties(applicationProperties)
                 .configs(null).build();

+ 13 - 2
web/pom.xml

@@ -84,6 +84,11 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-security</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -101,7 +106,14 @@
             </dependency>
         </dependencies>
     </dependencyManagement>
-
+    <repositories>
+        <!-- ... possibly other repository elements ... -->
+        <repository>
+            <id>spring-snapshot</id>
+            <name>Spring Snapshot Repository</name>
+            <url>https://repo.spring.io/snapshot</url>
+        </repository>
+    </repositories>
     <build>
         <plugins>
             <plugin>
@@ -120,7 +132,6 @@
                 <version>2.3.4.RELEASE</version>
                 <configuration>
                     <mainClass>seecoder.devcloud.web.devcloudWebApplication</mainClass>
-                    <!--  todo 打包时需排除一些无法回滚的测试类  -->
                 </configuration>
                 <executions>
                     <execution>

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

@@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import seecoder.devcloud.web.vo.GitWebHookVO;
+import seecoder.devcloud.web.model.vo.GitWebHookVO;
 
 /**
  * @author chenyz

+ 67 - 0
web/src/main/java/seecoder/devcloud/web/controller/pipeline/DeploymentController.java

@@ -0,0 +1,67 @@
+package seecoder.devcloud.web.controller.pipeline;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
+import seecoder.devcloud.web.service.pipeline.DeploymentService;
+
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/12
+ * @description:
+ */
+@Api(tags = "流水线部署的实例 API")
+@RestController
+@RequestMapping("/deployments")
+public class DeploymentController {
+
+    private final DeploymentService deploymentService;
+
+    @Autowired
+    public DeploymentController(DeploymentService deploymentService) {
+        this.deploymentService = deploymentService;
+    }
+
+    @ApiOperation(value = "获取项目所有部署的实例信息", httpMethod = "GET")
+    @ApiImplicitParam(name = "projectId", dataType = "int")
+    @GetMapping("/list")
+    public Response<List<DeploymentInfoVO>> retrieveDeploymentInfos(@RequestParam("projectId")Integer projectId){
+        return Response.buildSuccess(deploymentService.retrieveDeploymentInfos(projectId));
+    }
+
+
+    @ApiOperation(value = "执行流水线构建实例", httpMethod = "POST")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", dataType = "int"),
+            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+    })
+    @PostMapping
+    public Response deploy(@RequestParam("projectId")Integer projectId,
+                           @RequestParam("pipelineId")Integer pipelineId){
+        deploymentService.deploy(projectId,pipelineId);
+        return Response.buildSuccess();
+    }
+
+    /**
+     * 执行一条pipepine
+     * todo 异步/异步异常捕获刷新result
+     */
+    @ApiOperation(value = "删除一个部署的实例", httpMethod = "DELETE")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", dataType = "int"),
+            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+    })
+    @DeleteMapping
+    public Response delete(@RequestParam("projectId")Integer projectId,
+                @RequestParam("pipelineId")Integer pipelineId){
+        deploymentService.deploy(projectId,pipelineId);
+        return Response.buildSuccess();
+    }
+}

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

@@ -0,0 +1,103 @@
+package seecoder.devcloud.web.controller.pipeline;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.apache.ibatis.annotations.Delete;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineConfigVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineCreateVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineInfoVO;
+import seecoder.devcloud.web.service.pipeline.PipelineService;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ */
+@RestController
+@RequestMapping("/pipelines")
+@Api(tags = "流水线配置 API")
+public class PipelineController {
+
+    private final PipelineService pipelineService;
+
+    @Autowired
+    public PipelineController(PipelineService pipelineService) {
+        this.pipelineService = pipelineService;
+    }
+
+    @GetMapping("/list")
+    @ApiOperation(value = "获取指定项目的所有流水线基本信息", httpMethod = "GET")
+    @ApiImplicitParam(name = "projectId", dataType = "int")
+    public Response<List<PipelineInfoVO>> retrievePipelineInfos(@RequestParam("projectId") Integer projectId){
+        return Response.buildSuccess(pipelineService.retrievePipelineInfos(projectId));
+    }
+
+    @GetMapping
+    @ApiOperation(value = "获取指定一条流水线的配置json信息", httpMethod = "GET")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", dataType = "int"),
+            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+    })
+    public Response<PipelineConfigVO> retrievePipelineConfig(@RequestParam("projectId")Integer projectId,
+                                                             @RequestParam("pipelineId")Integer pipelineId){
+
+        return Response.buildSuccess(pipelineService.retrievePipelineConfig(projectId, pipelineId));
+    }
+
+    @GetMapping("/history/list")
+    @ApiOperation(value = "获取指定一条流水线的历史构建信息列表", httpMethod = "GET")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", dataType = "int"),
+            @ApiImplicitParam(name = "pipelineId", dataType = "int")
+    })
+    public Response<List<PipelineHistoryVO>> retrievePipelineHistory(@RequestParam("projectId")Integer projectId,
+                                                                     @RequestParam("pipelineId")Integer pipelineId){
+        return Response.buildSuccess(pipelineService.retrievePipelineHistory(projectId,pipelineId));
+    }
+
+
+    @ApiOperation(value = "依据模板创建一个流水线配置", httpMethod = "POST")
+    @ApiImplicitParam(name = "pipelineCreateVO", value = "流水线创建配置信息",dataType = "PipelineCreateVO")
+    @PostMapping
+    public Response createPipelineConfig(@RequestBody PipelineCreateVO pipelineCreateVO){
+        pipelineService.createPipelineConfig(pipelineCreateVO);
+        return Response.buildSuccess();
+    }
+
+    @PutMapping("/config")
+    @ApiOperation(value = "保存修改一条流水线的json配置信息", httpMethod = "PUT")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", dataType = "int"),
+            @ApiImplicitParam(name = "pipelineId", dataType = "int"),
+            @ApiImplicitParam(name = "configJson", dataType = "String")
+    })
+    public Response savePipelineConfig(@RequestParam("projectId")Integer projectId,
+                                       @RequestParam("pipelineId")Integer pipelineId,
+                                       @RequestParam("configJson")String configJson){
+        //todo 验证configJson有效性
+        pipelineService.savePipelineConfig(projectId,pipelineId, configJson);
+        return Response.buildSuccess();
+    }
+
+    @ApiOperation(value = "删除一条流水线", httpMethod = "DELETE")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", dataType = "int"),
+            @ApiImplicitParam(name = "pipelineId", dataType = "int"),
+    })
+    @DeleteMapping
+    public Response deletePipelineInfo(Integer projectId,Integer pipelineId){
+        pipelineService.deletePipelineConfig(projectId, pipelineId);
+        return Response.buildSuccess();
+    }
+
+}

+ 8 - 34
web/src/main/java/seecoder/devcloud/web/controller/user/UserController.java

@@ -1,24 +1,19 @@
 package seecoder.devcloud.web.controller.user;
 
-import jnr.ffi.annotations.In;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.user.UserService;
-import seecoder.devcloud.web.vo.Response;
-import seecoder.devcloud.web.vo.user.ChangePasswordVO;
-import seecoder.devcloud.web.vo.user.RegisterVO;
-import seecoder.devcloud.web.vo.user.UserVO;
-
-import javax.validation.Validation;
-import javax.validation.constraints.Pattern;
 
 /**
  * @author PuHong Weng
  * @date 2021/3/5
  * @description:
  */
-@RestController("/user")
-@ResponseBody
+@RestController
+@RequestMapping("/users")
 public class UserController {
 
     private final UserService userService;
@@ -28,30 +23,9 @@ public class UserController {
         this.userService = userService;
     }
 
-    @PostMapping("/register")
-    public Response<UserVO> register(@RequestBody RegisterVO registerVO){
-        return Response.ok(userService.register(registerVO)) ;
-    }
-
-    @PutMapping("/password")
-    public Response changePassword(@RequestBody ChangePasswordVO vo){
-        userService.changePassword(vo);
-        return Response.ok();
-    }
-
-    @PutMapping("nickname")
-    public Response<UserVO> changeUserInfo(
-            @RequestParam("userId") Integer userid,
-            @RequestParam("nickname")
-            @Pattern(regexp = "^\\w+${4,23}", message = "昵称只能包含大小写字母、数字和下划线,且必须为4-23位!")
-                    String nickName) {
-        return Response.ok(userService.changeUserInfo(userid, nickName));
-    }
-
-    @GetMapping("/id")
-    public Response<UserVO> findUserById(
-            @RequestParam("userId") Integer userId){
-        return Response.ok(userService.getUserById(userId));
+    @GetMapping
+    public Response getLoginUser(){
+        return Response.buildSuccess(userService.getLoginUser());
     }
 
 }

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

@@ -0,0 +1,29 @@
+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;
+    }
+}

+ 34 - 0
web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineHistoryMapper.java

@@ -0,0 +1,34 @@
+package seecoder.devcloud.web.dao.pipeline;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Select;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
+
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/12
+ * @description:
+ */
+@Mapper
+public interface PipelineHistoryMapper {
+
+    @Select("select * from pipeline_history where pipeline_id = #{pipelineId}")
+    List<PipelineHistory> selectByPipelineId(Integer pipelineId);
+
+
+    /**
+     * 获取一个项目里所有流水线配置的最新构建历史
+     */
+    @Select("SELECT *" +
+            "FROM   pipeline_history" +
+            "WHERE  startTime=" +
+            "(  SELECT MAX(startTime) " +
+            "   FROM pipeline_history" +
+            "   WHERE pipeline_id in" +
+            "   <foreach collection='pipelineIds' open='(' item='pipelineId' separator=',' close=')'> #{pipelineId}</foreach>" +
+            "   )")
+    List<PipelineHistory> selectRecentlyHistoryBy(List<Integer> pipelineIds);
+
+}

+ 39 - 0
web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineMapper.java

@@ -0,0 +1,39 @@
+package seecoder.devcloud.web.dao.pipeline;
+
+import org.apache.ibatis.annotations.*;
+import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
+import seecoder.devcloud.web.model.po.pipeline.Pipeline;
+import seecoder.devcloud.web.model.po.user.Group;
+
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/12
+ * @description:
+ */
+@Mapper
+public interface PipelineMapper {
+
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
+    boolean insert(Pipeline pipeline, String... ignoredCols);
+
+    @Select("select * from pipeline where id = #{id}")
+    Pipeline selectById(Integer id);
+
+    @Select("select * from pipeline where project_id = #{id}")
+    List<Pipeline> selectByProjectId(Integer id);
+
+    /**
+     * 不级联删除历史构建信息以留档
+     */
+    @Delete("delete from pipeline where id = #{id}")
+    boolean delete(Integer id);
+
+    @Update("update pipeline set config_json = #{configJson} where id = #{id}")
+    boolean updateConfigJson(@Param("id") Integer id,@Param("configJson") String configJson);
+
+
+
+}

+ 3 - 3
web/src/main/java/seecoder/devcloud/web/dao/GeneralInsertUpdateSqlProvider.java → web/src/main/java/seecoder/devcloud/web/dao/provider/GeneralInsertUpdateSqlProvider.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.dao;
+package seecoder.devcloud.web.dao.provider;
 
 import org.apache.ibatis.jdbc.SQL;
 
@@ -10,8 +10,8 @@ import java.util.stream.Collectors;
 /**
  * @author PuHong Weng
  * @date 2021/3/1
- * @description: 避免写繁琐的插入和更新的方法的,注意 pojo类的字段要和数据库表对应, 用法示例见 UserMapper.class
- * 插入单个参数(除了ignoredCols以外的参数)时,mapper写方法就行,实例见 UserMapper.insert
+ * @description: 避免写繁琐的插入和更新的方法的,注意 pojo类的字段要和数据库表对应, 用法示例见 UserMapperImpl.class
+ * 插入单个参数(除了ignoredCols以外的参数)时,mapper写方法就行,实例见 UserMapperImpl.insert
  * 插入多个参数(除了ignoredCols以外的参数)时,mapper方法参数要加@Param说明,实例见 GroupMemberMapper.insert
  */
 public class GeneralInsertUpdateSqlProvider {

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

@@ -1,7 +1,7 @@
 package seecoder.devcloud.web.dao.provider;
 
 import org.apache.ibatis.jdbc.SQL;
-import seecoder.devcloud.web.po.TreeNodePO;
+import seecoder.devcloud.web.model.po.TreeNodePO;
 
 public class TreeNodeProvider {
     public String updateTreeNode(TreeNodePO TreeNodePO){

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

@@ -3,7 +3,7 @@ package seecoder.devcloud.web.dao.tree;
 
 import org.apache.ibatis.annotations.*;
 import org.springframework.stereotype.Repository;
-import seecoder.devcloud.web.po.TreeNodePO;
+import seecoder.devcloud.web.model.po.TreeNodePO;
 import seecoder.devcloud.web.dao.provider.TreeNodeProvider;
 
 import java.util.List;

+ 2 - 2
web/src/main/java/seecoder/devcloud/web/dao/user/GroupMapper.java

@@ -3,8 +3,8 @@ package seecoder.devcloud.web.dao.user;
 
 
 import org.apache.ibatis.annotations.*;
-import seecoder.devcloud.web.dao.GeneralInsertUpdateSqlProvider;
-import seecoder.devcloud.web.po.user.Group;
+import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
+import seecoder.devcloud.web.model.po.user.Group;
 
 /**
  * @author PuHong Weng

+ 2 - 5
web/src/main/java/seecoder/devcloud/web/dao/user/GroupMemberMapper.java

@@ -1,10 +1,8 @@
 package seecoder.devcloud.web.dao.user;
 
-import jnr.ffi.annotations.In;
 import org.apache.ibatis.annotations.*;
-import org.springframework.stereotype.Repository;
-import seecoder.devcloud.web.po.user.Group;
-import seecoder.devcloud.web.po.user.User;
+import seecoder.devcloud.web.model.po.user.Group;
+import seecoder.devcloud.web.model.po.user.User;
 
 import java.util.List;
 
@@ -14,7 +12,6 @@ import java.util.List;
  * @description:
  */
 @Mapper
-@Repository
 public interface GroupMemberMapper {
 
     @Insert("insert into group_member (group_id,user_id) values (#{groupId}, #{userId}) ")

+ 13 - 26
web/src/main/java/seecoder/devcloud/web/dao/user/UserMapper.java

@@ -1,35 +1,22 @@
 package seecoder.devcloud.web.dao.user;
 
+import seecoder.devcloud.web.model.po.user.User;
 
-import org.apache.ibatis.annotations.*;
-import seecoder.devcloud.web.dao.GeneralInsertUpdateSqlProvider;
-import seecoder.devcloud.web.po.user.User;
-
-
-@Mapper
+/**
+ * 准确来说已经不是mybatis的mapper了
+ * 因为集成了门户系统,用户数据需要从那取
+ * 这里写成这种形式是为了不破坏三层结构
+ */
 public interface UserMapper {
 
 	/**
-	 * 这里的id是取自gitlab的用户id,所以不需要自增和回填
+	 * 返回当前自己的用户信息
+	 * 由于集成了门户系统而且使用了jwt作为安全认证机制,自己的用户信息存放在 SecurityContextHolder中
+	 * 见 JwtAuthenticationTokenFilter.class
+	 * 注意:SecurityContextHolder采用的是ThreadLocal实现的
+	 *     如果要新开子线程,且子线程需要用到用户信息,务必在父线程把用户信息取出
 	 */
-	@InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
-	int insert(User user,String... ignoredCols);
-
-	@UpdateProvider(type= GeneralInsertUpdateSqlProvider.class, method="updateById")
-	int updateById(User user);
-
-	@Delete("delete from user where id = #{id}")
-	int delete(User user);
-
-
-	@Select("select * from user where id = #{id}")
-	User findById(int id);
-
-	@Select("select * from user where username = #{username}")
-	User findByUsername(String username);
-
-	@Select("select * from user where email = #{email}")
-	User findByEmail(String email);
-
+	User findLoginUser();
 
+	User findUserByUsername(String username);
 }

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

@@ -4,14 +4,15 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
+import seecoder.devcloud.common.exceptions.AccessDeniedException;
+import seecoder.devcloud.common.exceptions.ConflictException;
 import seecoder.devcloud.common.exceptions.ServiceException;
-import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.model.vo.Response;
 
 /**
  * @author PuHong Weng
  * @date 2021/3/5
  * @description: 统一异常返回处理
- * todo 应为整个系统使用了学长的老API,是否有没捕捉的异常,待进一步验证
  */
 @ControllerAdvice
 @Slf4j
@@ -20,8 +21,14 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(ServiceException.class)
     @ResponseBody
     public Response serviceExceptionHandler(ServiceException e){
-        log.error(e.getMessage(),e);
-        return Response.serverInternalError(e.getMessage());
+        log.error("Error: ",e);
+        return Response.buildFailure(e.getCode(),e.getMessage());
     }
 
+    @ExceptionHandler(Exception.class)
+    @ResponseBody
+    public Response serviceExceptionHandler(Exception e){
+        log.error("Error: ",e);
+        return Response.buildFailure(503,e.getMessage());
+    }
 }

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

@@ -1,5 +1,6 @@
 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.Configuration;
@@ -8,6 +9,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 import springfox.boot.starter.autoconfigure.SpringfoxConfigurationProperties;
 import springfox.documentation.builders.ApiInfoBuilder;
 import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
 import springfox.documentation.oas.annotations.EnableOpenApi;
 import springfox.documentation.service.ApiInfo;
 import springfox.documentation.spi.DocumentationType;
@@ -44,6 +46,9 @@ public class SwaggerConfig{
                 .apiInfo(initApiInfo())
                 .select()
                 //.paths(doFilteringRules())
+                //不显示错误的接口地址
+                .apis(RequestHandlerSelectors.basePackage("seecoder.devcloud.web.controller"))
+                .paths(Predicates.not(PathSelectors.regex("/error.*")))
                 .paths(PathSelectors.any())
                 .build();
 

+ 94 - 0
web/src/main/java/seecoder/devcloud/web/infrastructure/config/WebSecurityConfig.java

@@ -0,0 +1,94 @@
+package seecoder.devcloud.web.infrastructure.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsUtils;
+import seecoder.devcloud.web.infrastructure.security.JwtAuthenticationTokenFilter;
+import seecoder.devcloud.web.infrastructure.security.WebSecurityConstants;
+import seecoder.devcloud.web.service.impl.user.UserServiceImpl;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.swing.*;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/5
+ * @description:
+ */
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)  //  启用方法级别的权限认证
+@DependsOn("userServiceImpl")
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+
+    private final JwtAuthenticationTokenFilter filter;
+
+    @Autowired
+    public WebSecurityConfig(JwtAuthenticationTokenFilter filter) {
+        super();
+        this.filter = filter;
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        //访问控制
+        http
+                //访问swagger
+                .anonymous()
+                .authorities("ROLE_ANONYMOUS").and()
+                .authorizeRequests()
+                .antMatchers("/**/*swagger*/**").permitAll()
+                .antMatchers("/**/*api-docs*/**").permitAll()
+                .and()
+                .authorizeRequests()
+                //跨域的Options请求进行放行
+                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
+                //todo 具体角色权限配置等开发完成之后再配, 这里先配为默认所有权限
+                .antMatchers("/**").hasAnyRole(WebSecurityConstants.STUDENT_ROLE, WebSecurityConstants.ADMIN_ROLE)
+                //其他所有接口都要在登陆认证状态下请求
+                .anyRequest().authenticated();
+
+
+
+
+        //开启跨域
+        http.cors();
+
+        //改用jwt无状态认证方式,将原来基于session的认证方式关闭
+        http.csrf().disable();
+        http.sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+                .and()
+                .addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager() throws Exception {
+        return super.authenticationManagerBean() ;
+    }
+
+
+
+}

+ 94 - 0
web/src/main/java/seecoder/devcloud/web/infrastructure/security/JwtAuthenticationTokenFilter.java

@@ -0,0 +1,94 @@
+package seecoder.devcloud.web.infrastructure.security;
+
+import io.jsonwebtoken.Claims;
+import net.minidev.json.JSONObject;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import seecoder.devcloud.common.util.JwtTokenUtil;
+import seecoder.devcloud.web.model.enums.UserIdentity;
+import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.vo.Response;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ * 登陆是集成了门户系统的登陆,后端只用作token校验
+ */
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
+
+    private final UserDetailsService userDetailsService;
+
+    private final JwtTokenUtil jwtTokenUtil;
+
+    @Autowired
+    public JwtAuthenticationTokenFilter(JwtTokenUtil jwtTokenUtil, @Qualifier("userServiceImpl") UserDetailsService userDetailsService) {
+        this.jwtTokenUtil = jwtTokenUtil;
+        this.userDetailsService = userDetailsService;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
+        String authHeader = httpServletRequest.getHeader("Authorization");
+        if (StringUtils.isNotEmpty(authHeader)) {
+            // 有token,验证正确性,签名不正确,会抛异常
+            Claims claims = jwtTokenUtil.getClaimsFromToken(authHeader);
+            if (claims != null){
+                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)))
+                        .build();
+                // 验证token是否过期
+                if (jwtTokenUtil.isTokenExpired(authHeader)) {
+                    //加载用户、角色、权限信息,Spring Security根据这些信息判断接口的访问权限
+                    UsernamePasswordAuthenticationToken authentication
+                            = new UsernamePasswordAuthenticationToken(userDetails, null,
+                            userDetails.getAuthorities());
+                    authentication.setDetails(new WebAuthenticationDetailsSource()
+                            .buildDetails(httpServletRequest));
+                    SecurityContextHolder.getContext().setAuthentication(authentication);
+                } else {
+                    //todo test token
+                    PrintWriter out = null ;
+                    try{
+                        httpServletResponse.setCharacterEncoding("UTF-8");
+                        httpServletResponse.setContentType("application/json; charset=utf-8");
+                        out = httpServletResponse.getWriter();
+                        out.append(Response.buildFailure(10110,"Jwt token 过期").toString());
+                        return;
+                    }
+                    catch (Exception e){
+                        e.printStackTrace();
+                        httpServletResponse.sendError(500);
+                    }
+                }
+            }
+
+
+
+
+        }
+        filterChain.doFilter(httpServletRequest, httpServletResponse);
+    }
+}

+ 0 - 81
web/src/main/java/seecoder/devcloud/web/infrastructure/security/WebSecurityConfiguration.java

@@ -1,81 +0,0 @@
-//package seecoder.devcloud.web.infrastructure.security;
-//
-//
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-//import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-//import org.springframework.security.config.annotation.web.builders.WebSecurity;
-//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
-//import org.springframework.security.core.userdetails.UserDetailsService;
-//import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-//import seecoder.devcloud.api.ApplicationProperties;
-//import seecoder.devcloud.web.dao.user.UserMapper;
-//import seecoder.devcloud.web.service.user.UserService;
-//
-//
-//@EnableWebSecurity
-//@EnableGlobalMethodSecurity(jsr250Enabled = true)
-//public class WebSecurityConfiguration {
-////	@Configuration
-////	@Order(Ordered.LOWEST_PRECEDENCE)
-////	public static class ApiWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
-////		@Override
-////		protected void configure(HttpSecurity http) throws Exception {
-////			http.antMatcher("/api/**")
-////					.authorizeRequests()
-////					.anyRequest().authenticated()
-////					.and()
-////					.httpBasic()
-////					.and()
-////					.csrf().disable()
-////					.cors();
-////		}
-////	}
-//
-//	@Configuration
-//	public static class DefaultWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
-//		private final UserDetailsService userDetailsService;
-//		private final LoginRedirectHandler loginRedirectHandler;
-//		@Autowired
-//		private UserMapper userMapper;
-//		@Autowired
-//		private ApplicationProperties applicationProperties;
-//		@Autowired
-//		private UserService userService;
-//
-//		@Autowired
-//		public DefaultWebSecurityConfiguration(UserDetailsServiceImpl userDetailsService, LoginRedirectHandler loginRedirectHandler) {
-//			this.userDetailsService = userDetailsService;
-//			this.loginRedirectHandler = loginRedirectHandler;
-//		}
-//		@Override
-//		protected void configure(HttpSecurity http) throws Exception {
-//			JwtAuthenticationFilter jwtAuthenticationFilter =
-//					new JwtAuthenticationFilter(authenticationManager(),
-//							userDetailsService, new RestAuthorEntry(),
-//							new AntPathRequestMatcher("/api/auth/receive", "GET"),
-//							applicationProperties,
-//							userMapper,
-//							userService);
-//			http
-//					.authorizeRequests()
-//						.antMatchers("/api/auth/register","/test" ,"/internal/**").permitAll()
-//			 			.antMatchers("/file/**").hasAnyAuthority(TEACHER_AUTHORITY.getAuthority(), ADMIN_AUTHORITY.getAuthority())
-//						.anyRequest().authenticated()
-//						.and()
-//						.addFilter(jwtAuthenticationFilter)
-//						.cors()
-//						.and()
-//						.csrf().disable();
-//		}
-//
-//		@Override
-//		public void configure(WebSecurity web) throws Exception {
-//			web
-//					.ignoring()
-//					.antMatchers("/api/auth/register","/test" ,"/internal/**");
-//		}
-//	}
-//}

+ 38 - 16
web/src/main/java/seecoder/devcloud/web/infrastructure/security/WebSecurityConstants.java

@@ -1,16 +1,38 @@
-//package seecoder.devcloud.web.infrastructure.security;
-//
-//import org.springframework.security.core.GrantedAuthority;
-//import org.springframework.security.core.authority.SimpleGrantedAuthority;
-//
-//public abstract class WebSecurityConstants {
-//	private static final String ROLE_PREFIX = "ROLE_";
-//
-//	public static final String STUDENT_ROLE = "STUDENT";
-//	public static final String TEACHER_ROLE = "TEACHER";
-//	public static final String ADMIN_ROLE = "ADMIN";
-//
-//	public static final GrantedAuthority STUDENT_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + STUDENT_ROLE);
-//	public static final GrantedAuthority TEACHER_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + TEACHER_ROLE);
-//	public static final GrantedAuthority ADMIN_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + ADMIN_ROLE);
-//}
+package seecoder.devcloud.web.infrastructure.security;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import seecoder.devcloud.web.model.enums.UserIdentity;
+
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * @author PuHong Weng
+ * @date 2021/3/8
+ * @description:
+ */
+public abstract class WebSecurityConstants {
+	private static final String ROLE_PREFIX = "ROLE_";
+
+	public static final String STUDENT_ROLE = "STUDENT";
+	public static final String TEACHER_ROLE = "TEACHER";
+	public static final String ADMIN_ROLE = "ADMIN";
+	
+	public static final GrantedAuthority STUDENT_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + STUDENT_ROLE);
+	public static final GrantedAuthority TEACHER_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + TEACHER_ROLE);
+	public static final GrantedAuthority ADMIN_AUTHORITY = new SimpleGrantedAuthority(ROLE_PREFIX + ADMIN_ROLE);
+
+
+
+	private static final Map<UserIdentity,GrantedAuthority> authorityTable= new HashMap<>();
+	
+	static {
+		authorityTable.put(UserIdentity.STUDENT, STUDENT_AUTHORITY);
+		authorityTable.put(UserIdentity.TEACHER, TEACHER_AUTHORITY);
+		authorityTable.put(UserIdentity.ADMIN, ADMIN_AUTHORITY);
+	}
+	
+	public static GrantedAuthority getAuthority(UserIdentity identity){
+		return authorityTable.get(identity);
+	}
+}

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/enums/GroupType.java → web/src/main/java/seecoder/devcloud/web/model/enums/GroupType.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.enums;
+package seecoder.devcloud.web.model.enums;
 
 /**
  * Description:

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/enums/NodeStateEnum.java → web/src/main/java/seecoder/devcloud/web/model/enums/NodeStateEnum.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.enums;
+package seecoder.devcloud.web.model.enums;
 
 public enum NodeStateEnum {
     PROCESSING("0:进行中"),

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/enums/NodeTypeEnum.java → web/src/main/java/seecoder/devcloud/web/model/enums/NodeTypeEnum.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.enums;
+package seecoder.devcloud.web.model.enums;
 
 public enum NodeTypeEnum {
     REQUIREMENT("0:需求"),

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

@@ -1,8 +1,4 @@
-package seecoder.devcloud.web.enums;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.Setter;
+package seecoder.devcloud.web.model.enums;
 
 /**
  * @author PuHong Weng

+ 7 - 2
web/src/main/java/seecoder/devcloud/web/enums/UserIdentity.java → web/src/main/java/seecoder/devcloud/web/model/enums/UserIdentity.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.enums;
+package seecoder.devcloud.web.model.enums;
 
 public enum UserIdentity {
 	/**
@@ -8,7 +8,12 @@ public enum UserIdentity {
 	/**
 	 * 教师角色
 	 */
-	TEACHER("教师");
+	TEACHER("教师"),
+
+	/**
+	 * 管理员角色
+	 */
+	ADMIN("管理员");
 
 	private final String name;
 

+ 3 - 5
web/src/main/java/seecoder/devcloud/web/po/TreeNodePO.java → web/src/main/java/seecoder/devcloud/web/model/po/TreeNodePO.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.po;
+package seecoder.devcloud.web.model.po;
 
 
 
@@ -6,10 +6,8 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NoArgsConstructor;
-import seecoder.devcloud.web.enums.NodeStateEnum;
-import seecoder.devcloud.web.enums.NodeTypeEnum;
-
-import java.util.Date;
+import seecoder.devcloud.web.model.enums.NodeStateEnum;
+import seecoder.devcloud.web.model.enums.NodeTypeEnum;
 
 @Data
 @AllArgsConstructor

+ 33 - 0
web/src/main/java/seecoder/devcloud/web/model/po/pipeline/Deployment.java

@@ -0,0 +1,33 @@
+package seecoder.devcloud.web.model.po.pipeline;
+
+import java.sql.Timestamp;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description: 已部署的软件实例
+ */
+public class Deployment {
+
+    Integer id;
+
+    /**
+     * 对应关联的流水线 todo sql外键
+     */
+    Integer pipelineId;
+
+    /**
+     * 部署的项目名称
+     */
+    String name;
+
+    /**
+     * 最新一次部署时间
+     */
+    Timestamp deployedTime;
+
+    /**
+     * 访问的url地址
+     */
+    String accessUrl;
+}

+ 30 - 0
web/src/main/java/seecoder/devcloud/web/model/po/pipeline/Pipeline.java

@@ -0,0 +1,30 @@
+package seecoder.devcloud.web.model.po.pipeline;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ */
+@Data
+@Builder
+public class Pipeline {
+
+
+
+    Integer id;
+
+    /**
+     * 所属的项目id todo sql外键
+     */
+    Integer projectId;
+
+    String name;
+
+    /**
+     * 此pipeline的配置,格式未json
+     */
+    String configJson;
+}

+ 45 - 0
web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelineHistory.java

@@ -0,0 +1,45 @@
+package seecoder.devcloud.web.model.po.pipeline;
+
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ */
+@Data
+public class PipelineHistory {
+
+    /**
+     * pipeline id
+     */
+    Integer id;
+
+    /**
+     * pipeline id
+     */
+    Integer pipelineId;
+
+    /**
+     * 执行开始的时间
+     */
+    Timestamp startTime;
+
+    /**
+     * 发起执行流水线的人
+     */
+    String username;
+
+    /**
+     * 执行结果
+     */
+    String result;
+
+    /**
+     * 执行结果具体信息
+     */
+    String details;
+
+}

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


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


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

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.po.user;
+package seecoder.devcloud.web.model.po.user;
 
 
 import lombok.Builder;
@@ -7,7 +7,7 @@ import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import seecoder.devcloud.web.enums.GroupType;
+import seecoder.devcloud.web.model.enums.GroupType;
 
 import java.util.List;
 

+ 67 - 0
web/src/main/java/seecoder/devcloud/web/model/po/user/User.java

@@ -0,0 +1,67 @@
+package seecoder.devcloud.web.model.po.user;
+
+
+import lombok.Builder;
+import lombok.Data;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import seecoder.devcloud.web.model.enums.UserIdentity;
+import seecoder.devcloud.web.infrastructure.security.WebSecurityConstants;
+
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.Collections;
+
+
+@Data
+@Builder
+public class User implements UserDetails {
+
+	/**
+	 * 注意用户id并非由此后端数据库生成,而是gitlab创建后填入,以确保两者的关联性的正确
+	 */
+	private Integer id;
+
+	private String username;
+
+	private String phone;
+
+	private String email;
+
+	private UserIdentity role;
+
+	@Override
+	public Collection<? extends GrantedAuthority> getAuthorities() {
+		return Collections.singleton(WebSecurityConstants.getAuthority(role));
+	}
+
+	/**
+	 * 此后端整合portal门户系统,不需要登陆功能,不用重写此方法
+	 */
+	@Override
+	public String getPassword() {
+		return "";
+	}
+
+	// spring security以下四个方法目前没有需求,默认全部返回true
+
+	@Override
+	public boolean isAccountNonExpired() {
+		return true;
+	}
+
+	@Override
+	public boolean isAccountNonLocked() {
+		return true;
+	}
+
+	@Override
+	public boolean isCredentialsNonExpired() {
+		return true;
+	}
+
+	@Override
+	public boolean isEnabled() {
+		return true;
+	}
+}

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/vo/GitWebHookVO.java → web/src/main/java/seecoder/devcloud/web/model/vo/GitWebHookVO.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.vo;
+package seecoder.devcloud.web.model.vo;
 
 import lombok.Data;
 import lombok.NoArgsConstructor;

+ 43 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/Response.java

@@ -0,0 +1,43 @@
+package seecoder.devcloud.web.model.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import seecoder.devcloud.common.exceptions.ServiceException;
+
+import java.io.Serializable;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/2/1
+ * @description:
+ */
+@Data
+public class Response<T> implements Serializable {
+
+    private Integer code;
+
+    private String msg;
+
+    private T data;
+
+    public Response(Integer code, String msg, T data) {
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+    }
+
+
+    public static Response buildSuccess() {
+        return new Response(200, "", null);
+    }
+
+
+    public static <T> Response<T> buildSuccess(T result) {
+        return new Response<T>(200, "", result);
+    }
+
+    public static  Response buildFailure(Integer code, String message) {
+        return new Response(code,message, null);
+    }
+}

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


+ 35 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/DeploymentInfoVO.java

@@ -0,0 +1,35 @@
+package seecoder.devcloud.web.model.vo.pipeline;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ */
+@Data
+@ApiModel("流水线部署的实例信息")
+public class DeploymentInfoVO {
+
+    @ApiModelProperty("实例id")
+    private Integer id;
+
+    @ApiModelProperty("关联的流水线")
+    private Integer pipelineId;
+
+    @ApiModelProperty("部署的实例名称")
+    private String name;
+
+    @ApiModelProperty("最新一次部署时间")
+    private Timestamp deployedTime;
+
+    @ApiModelProperty("实例的访问地址")
+    private String accessUrl;
+
+    @ApiModelProperty("实例运行状态")
+    private String status;
+}

+ 28 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineConfigVO.java

@@ -0,0 +1,28 @@
+package seecoder.devcloud.web.model.vo.pipeline;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.beans.BeanUtils;
+import seecoder.devcloud.web.model.po.pipeline.Pipeline;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ */
+@Data
+@ApiModel("流水线的json配置信息")
+public class PipelineConfigVO {
+
+    @ApiModelProperty("流水线id")
+    Integer id;
+
+    @ApiModelProperty("流水线配置json")
+    String configJson;
+
+
+    public PipelineConfigVO(Pipeline pipeline){
+        BeanUtils.copyProperties(pipeline,this);
+    }
+}

+ 24 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineCreateVO.java

@@ -0,0 +1,24 @@
+package seecoder.devcloud.web.model.vo.pipeline;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import javax.validation.Valid;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/12
+ * @description:
+ */
+@Data
+@ApiModel("流水线创建表单信息")
+public class PipelineCreateVO {
+
+    private Integer projectId;
+
+    private Integer pipelineId;
+
+    private String name;
+
+    private String templateName;
+}

+ 45 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineHistoryVO.java

@@ -0,0 +1,45 @@
+package seecoder.devcloud.web.model.vo.pipeline;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
+
+import java.sql.Timestamp;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ */
+@Data
+@NoArgsConstructor
+@ApiModel("流水线历史构建记录")
+public class PipelineHistoryVO {
+
+    @ApiModelProperty("流水线构建历史id")
+    Integer id;
+
+    @ApiModelProperty("流水线id")
+    Integer pipelineId;
+
+    @ApiModelProperty("构建开始的时间")
+    Timestamp startTime;
+
+
+    @ApiModelProperty("发起流水线构建的用户名")
+    String username;
+
+    @ApiModelProperty("执行结果")
+    String result;
+
+    @ApiModelProperty("执行结果细节")
+    String details;
+
+
+    public PipelineHistoryVO(PipelineHistory history){
+        BeanUtils.copyProperties(history,this);
+    }
+}

+ 52 - 0
web/src/main/java/seecoder/devcloud/web/model/vo/pipeline/PipelineInfoVO.java

@@ -0,0 +1,52 @@
+package seecoder.devcloud.web.model.vo.pipeline;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import seecoder.devcloud.web.model.po.pipeline.Pipeline;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistory;
+
+import java.sql.Timestamp;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description:
+ */
+@Data
+@Builder
+@ApiModel("流水线基本信息")
+@AllArgsConstructor
+public class PipelineInfoVO {
+
+    @ApiModelProperty("流水线id")
+    Integer id;
+
+    @ApiModelProperty("流水线名称")
+    String name;
+
+    @ApiModelProperty("最后一次执行流水线构建的时间")
+    Timestamp startTime;
+
+    @ApiModelProperty("最后一次发起流水线构建的人")
+    String username;
+
+    @ApiModelProperty("最后一次发起流水线构建的执行结果")
+    String result;
+
+    @ApiModelProperty("最后一次发起流水线构建的执行结果详情")
+    String details;
+
+    public PipelineInfoVO(Pipeline pipeline, PipelineHistory pipelineHistory){
+        startTime = pipelineHistory.getStartTime();
+        username = pipelineHistory.getUsername();
+        result = pipelineHistory.getResult();
+        details = pipelineHistory.getDetails();
+        name = pipeline.getName();
+        id =pipeline.getId();
+    }
+
+}

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


+ 2 - 2
web/src/main/java/seecoder/devcloud/web/vo/user/GroupVO.java → web/src/main/java/seecoder/devcloud/web/model/vo/user/GroupVO.java

@@ -1,9 +1,9 @@
-package seecoder.devcloud.web.vo.user;
+package seecoder.devcloud.web.model.vo.user;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import seecoder.devcloud.web.po.user.Group;
+import seecoder.devcloud.web.model.po.user.Group;
 
 import java.util.List;
 import java.util.stream.Collectors;

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/vo/user/RegisterVO.java → web/src/main/java/seecoder/devcloud/web/model/vo/user/RegisterVO.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.vo.user;
+package seecoder.devcloud.web.model.vo.user;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.AllArgsConstructor;

+ 9 - 11
web/src/main/java/seecoder/devcloud/web/vo/user/UserVO.java → web/src/main/java/seecoder/devcloud/web/model/vo/user/UserVO.java

@@ -1,30 +1,28 @@
-package seecoder.devcloud.web.vo.user;
+package seecoder.devcloud.web.model.vo.user;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.springframework.beans.BeanUtils;
-import seecoder.devcloud.common.serializer.TimestampLocalDateTimeSerializer;
-import seecoder.devcloud.web.enums.UserIdentity;
-import seecoder.devcloud.web.po.user.User;
+import seecoder.devcloud.web.model.enums.UserIdentity;
+import seecoder.devcloud.web.model.po.user.User;
 
 import java.sql.Timestamp;
-import java.time.LocalDateTime;
 
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class UserVO {
     private Integer id;
-    private UserIdentity role;
+
     private String username;
-    private String nickname;
-    private String email;
+
     private String phone;
-    @JsonProperty("created_at")
-    private Timestamp createdAt;
+
+    private String email;
+
+    private UserIdentity role;
 
     public UserVO(User user) {
         BeanUtils.copyProperties(user,this);

+ 0 - 53
web/src/main/java/seecoder/devcloud/web/po/user/User.java

@@ -1,53 +0,0 @@
-package seecoder.devcloud.web.po.user;
-
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.apache.ibatis.annotations.Select;
-import org.apache.ibatis.type.Alias;
-import org.hibernate.annotations.LazyCollection;
-import org.hibernate.annotations.LazyCollectionOption;
-import org.springframework.data.annotation.CreatedDate;
-import org.springframework.data.jpa.domain.support.AuditingEntityListener;
-import seecoder.devcloud.web.enums.UserIdentity;
-
-import javax.persistence.*;
-import java.sql.Timestamp;
-import java.time.LocalDateTime;
-import java.util.HashSet;
-import java.util.Set;
-
-@Data
-public class User {
-
-	/**
-	 * 注意用户id并非由此后端数据库生成,而是gitlab创建后填入,以确保两者的关联性的正确
-	 */
-	private Integer id;
-
-	private String username;
-
-	private String nickname="";
-
-	private String password;
-
-	private String phone;
-
-	private String email;
-
-	private UserIdentity role;
-
-	private Timestamp createdAt;
-
-	/**
-	 * 这个属性来自于gitlab
-	 */
-	private Integer namespace;
-
-	/**
-	 * 这个属性来自于gitlab
-	 */
-	private String token;
-}

+ 31 - 0
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/DeploymentServiceImpl.java

@@ -0,0 +1,31 @@
+package seecoder.devcloud.web.service.impl.pipeline;
+
+import org.springframework.stereotype.Service;
+import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
+import seecoder.devcloud.web.service.pipeline.DeploymentService;
+
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/12
+ * @description:
+ */
+@Service
+public class DeploymentServiceImpl implements DeploymentService {
+    @Override
+    public List<DeploymentInfoVO> retrieveDeploymentInfos(Integer projectId) {
+        //todo  需要远端查看k8s实例的status
+        return null;
+    }
+
+    @Override
+    public void deploy(Integer projectId, Integer pipelineId) {
+
+    }
+
+    @Override
+    public void delete(Integer projectId, Integer pipelineId) {
+
+    }
+}

+ 102 - 0
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java

@@ -0,0 +1,102 @@
+package seecoder.devcloud.web.service.impl.pipeline;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import seecoder.devcloud.web.dao.pipeline.PipelineHistoryMapper;
+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.PipelineHistory;
+import seecoder.devcloud.web.model.po.user.User;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineConfigVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineCreateVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineInfoVO;
+import seecoder.devcloud.web.service.pipeline.PipelineService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/12
+ * @description:
+ */
+@Service
+public class PipelineServiceImpl implements PipelineService {
+
+    private final PipelineHistoryMapper pipelineHistoryMapper;
+
+    private final PipelineMapper pipelineMapper;
+
+    private final UserMapper userMapper;
+
+
+    @Autowired
+    public PipelineServiceImpl(PipelineHistoryMapper pipelineHistoryMapper, PipelineMapper pipelineMapper, UserMapper userMapper) {
+        this.pipelineHistoryMapper = pipelineHistoryMapper;
+        this.pipelineMapper = pipelineMapper;
+        this.userMapper = userMapper;
+    }
+
+
+    @Override
+    public List<PipelineInfoVO> retrievePipelineInfos(Integer projectId) {
+        projectAuthentication(projectId);
+        List<Pipeline> pipelines = pipelineMapper.selectByProjectId(projectId);
+        List<Integer> pipelineIds = pipelines.stream().map(Pipeline::getId).collect(Collectors.toList());
+        List<PipelineHistory> histories = pipelineHistoryMapper.selectRecentlyHistoryBy(pipelineIds);
+        Map<Integer,PipelineHistory> historyMap = histories.stream().collect(Collectors.toMap(PipelineHistory::getPipelineId, x->x));
+        return pipelines.stream().map(x->new PipelineInfoVO(x,historyMap.get(x.getId()))).collect(Collectors.toList());
+    }
+
+    @Override
+    public PipelineConfigVO retrievePipelineConfig(Integer projectId, Integer pipelineId) {
+        projectAuthentication(projectId);
+        return new PipelineConfigVO(pipelineMapper.selectById(pipelineId));
+    }
+
+    @Override
+    public List<PipelineHistoryVO> retrievePipelineHistory(Integer projectId, Integer pipelineId) {
+        projectAuthentication(projectId);
+        List<PipelineHistory> histories = pipelineHistoryMapper.selectByPipelineId(pipelineId);
+        return histories.stream().map(PipelineHistoryVO::new).collect(Collectors.toList());
+    }
+
+    @Override
+    public void createPipelineConfig(PipelineCreateVO pipelineCreateVO) {
+        projectAuthentication(pipelineCreateVO.getProjectId());
+        Pipeline pipeline = Pipeline.builder()
+                .name(pipelineCreateVO.getName())
+                .projectId(pipelineCreateVO.getProjectId())
+                .configJson("") //todo 提供模板
+                .build();
+        pipelineMapper.insert(pipeline);
+
+
+    }
+
+    @Override
+    public void savePipelineConfig(Integer projectId, Integer pipelineId, String configJson) {
+        projectAuthentication(projectId);
+        pipelineMapper.updateConfigJson(pipelineId,configJson);
+
+    }
+
+    @Override
+    public void deletePipelineConfig(Integer projectId, Integer pipelineId) {
+        projectAuthentication(projectId);
+        pipelineMapper.delete(pipelineId);
+    }
+
+    /**
+     * 判断用户是否有权限修改这些流水线配置,
+     * 防止用户修改提交的参数从而修改其他组的流水线
+     */
+    private void projectAuthentication(Integer projectId){
+        User user = userMapper.findLoginUser();
+        //todo 鉴权
+
+    }
+}

+ 6 - 7
web/src/main/java/seecoder/devcloud/web/service/impl/tree/TreeNodeServiceImpl.java

@@ -6,12 +6,11 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import seecoder.devcloud.web.aop.TreeLogging;
 import seecoder.devcloud.web.enums.OperationEnum;
-import seecoder.devcloud.web.po.TreeNodePO;
+import seecoder.devcloud.web.model.po.TreeNodePO;
 import seecoder.devcloud.web.service.tree.TreeNodeService;
-import seecoder.devcloud.web.vo.Response;
-import seecoder.devcloud.web.vo.TreeNodeVO;
+import seecoder.devcloud.web.model.vo.Response;
+import seecoder.devcloud.web.model.vo.TreeNodeVO;
 import seecoder.devcloud.web.dao.tree.TreeNodeMapper;
-
 import java.util.List;
 
 @Service
@@ -26,7 +25,7 @@ public class TreeNodeServiceImpl implements TreeNodeService {
     @Override
     public Response listTreeNodesByProjectId(int projectId) {
         // TODO:safety check
-        return Response.ok(treeNodeMapper.listTreeNodesByProjectId(projectId));
+        return Response.buildSuccess(treeNodeMapper.listTreeNodesByProjectId(projectId));
     }
 
     @Override
@@ -36,7 +35,7 @@ public class TreeNodeServiceImpl implements TreeNodeService {
         BeanUtils.copyProperties(treeNodeVO,treeNodePO);
         int res = treeNodeMapper.insertTreeNode(treeNodePO);
         // TODO:safety check
-        return Response.ok();
+        return Response.buildSuccess();
     }
 
     @Override
@@ -46,7 +45,7 @@ public class TreeNodeServiceImpl implements TreeNodeService {
         BeanUtils.copyProperties(treeNodeVO,treeNodePO);
         int res = treeNodeMapper.updateTreeNode(treeNodePO);
         // TODO:safety check
-        return Response.ok();
+        return Response.buildSuccess();
     }
 
     @Override

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

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

+ 16 - 128
web/src/main/java/seecoder/devcloud/web/service/impl/user/UserServiceImpl.java

@@ -2,154 +2,42 @@ package seecoder.devcloud.web.service.impl.user;
 
 
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.gitlab4j.api.GitLabApiException;
-import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Sort;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.Assert;
-import seecoder.devcloud.api.gitlab.GitlabApi;
-import seecoder.devcloud.api.gitlab.model.GitlabUser;
-import seecoder.devcloud.api.jenkins.JenkinsApi;
-import seecoder.devcloud.common.exceptions.Asserts;
-import seecoder.devcloud.common.exceptions.InvalidRequestException;
-import seecoder.devcloud.common.exceptions.ServiceException;
-import seecoder.devcloud.common.util.ToolKit;
-import seecoder.devcloud.web.dao.user.UserMapper;
-import seecoder.devcloud.web.vo.user.ChangePasswordVO;
-import seecoder.devcloud.web.vo.user.RegisterVO;
 
-import seecoder.devcloud.web.enums.UserIdentity;
-import seecoder.devcloud.web.po.user.User;
-import seecoder.devcloud.web.vo.user.UserVO;
-import seecoder.devcloud.web.service.user.MailService;
+import seecoder.devcloud.web.dao.user.UserMapper;
+import seecoder.devcloud.web.model.vo.user.UserVO;
 import seecoder.devcloud.web.service.user.UserService;
 
 @Service
 @Slf4j
-public class UserServiceImpl implements UserService {
-	private static final Sort PAGE_SORT = Sort.by(Sort.Direction.ASC, "id");
+public class UserServiceImpl implements UserService, UserDetailsService {
+
+
 
 	private final UserMapper userMapper;
-	private final MailService mailService;
-	private final GitlabApi gitlabApi;
-	private final JenkinsApi jenkinsApi;
 
 	@Autowired
-	public UserServiceImpl(UserMapper userMapper, MailService mailService, GitlabApi gitlabApi, JenkinsApi jenkinsApi) {
+	public UserServiceImpl(UserMapper userMapper) {
 		this.userMapper = userMapper;
-		this.mailService = mailService;
-		this.gitlabApi = gitlabApi;
-		this.jenkinsApi = jenkinsApi;
-	}
-
-	@Override
-	@Transactional
-	public UserVO register(RegisterVO form) throws ServiceException {
-		return register(form.getUsername(), form.getEmail(), form.getPassword(),form.getNickname(), UserIdentity.STUDENT);
 	}
 
 	@Override
-	@Transactional
-	public UserVO registerTeacher(RegisterVO form) throws ServiceException {
-		return register(form.getUsername(), form.getEmail(), form.getPassword(),form.getNickname(), UserIdentity.TEACHER);
+	public UserVO getLoginUser(){
+		return new UserVO(userMapper.findLoginUser());
 	}
 
-	private UserVO register(String username, String email, String password, String nickname,UserIdentity role) throws ServiceException {
-		User user = userMapper.findByUsername(username);
-		Asserts.isNull(user, "用户名已被使用!");
-		user = userMapper.findByEmail(email);
-		Asserts.isNull(user, "邮箱已被使用!");
-		String realPassword = password == null ? ToolKit.randomPassword() : password;
-		GitlabUser gitlabUser;
-		try {
-			gitlabUser = gitlabApi.createUser(username, email, realPassword);
-		} catch (GitLabApiException e) {
-			log.error(e.getMessage(), e);
-			throw new ServiceException("创建GitLab用户时发生异常[" + e.getMessage() + "]");
-		}
-		user = new User();
-		BeanUtils.copyProperties(gitlabUser, user);
-		if(nickname!=null){
-			user.setNickname(nickname);
-		}
-
-		user.setUsername(username);
-		user.setEmail(email);
-		//在gitlab注册后,直接加密
-		user.setPassword(DigestUtils.sha256Hex(realPassword));
-		user.setRole(role);
-		userMapper.insert(user, "created_at");
-		final UserVO userVO = new UserVO(user);
-		if (password == null) {
-			mailService.send("尊敬的" + username + "您好, 您的初始密码为" + realPassword + ", 请及时修改", "注册成功 | SEECODER", email);
-		}
-		return userVO;
-	}
 
+	/**
+	 * 此后端整合portal门户系统,不需要登陆功能,不用重写此方法
+	 */
 	@Override
-	@Transactional
-	public void delete(int userId) throws ServiceException {
-		User user = userMapper.findById(userId);
-		Assert.notNull(user, "找不到要删除的用户");
-		Assert.isTrue(user.getRole() == UserIdentity.STUDENT, "目标用户只能是学生");
-		try {
-			gitlabApi.deleteUser(userId);
-		} catch (Exception e) {
-			log.error(e.getMessage(), e);
-			throw new ServiceException("删除GitLab用户时发生异常[" + e.getMessage() + "]");
-		}
-		//todo 删除用户需要连带删除什么
-		userMapper.delete(user);
+	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+		return null;
 	}
 
-	@Override
-	public UserVO getUserById(Integer userid) {
-		return new UserVO(userMapper.findById(userid));
-	}
 
-	@Override
-	public UserVO changeUserInfo(Integer userid, String nickName) throws ServiceException {
-		User one = userMapper.findById(userid);
-		if (one == null) {
-			throw new ServiceException("用户不存在");
-		}
-		one.setNickname(nickName);
-		userMapper.updateById(one);
-		return new UserVO(one);
-	}
-
-	@Override
-	public void changePassword(ChangePasswordVO form) throws ServiceException {
-		User user = userMapper.findById(form.getUserId());
-
-		if (!user.getPassword().equals(DigestUtils.sha256Hex(form.getOrigin()))) {
-			throw new InvalidRequestException("原密码验证失败,如忘记密码请联系管理员重置");
-		}
-		changePassword(user, form.getPassword(), false);
-	}
-
-	private void changePassword(User user, String password, boolean reset) throws ServiceException {
-		try {
-			/**
-			 * todo 修改密码容易导致gitlab与devcloud不一致
-			 * 管理员每次修改密码,会导致下次普通用户登陆gitlab的时候强制重新改密码
-			 * 如果这时候学生在gitlab那边改的密码与这里改的不一样,就产生了密码不一致的结果
-			 * 而且目前官方gitlab client api不支持普通用户通过api改密码
-			 * 见 https://docs.gitlab.com/ce/api/users.html
-			 * 所以这个bug暂时无解,最好是让学生建立用户完毕之后不要乱改密码
-			 */
-			gitlabApi.changePassword(user.getId(), password);
-		} catch (GitLabApiException e) {
-			log.error(e.getMessage(), e);
-			throw new ServiceException("修改GitLab用户密码时发生异常[" + e.getMessage() + "]");
-		}
-		user.setPassword(DigestUtils.sha256Hex(password));
-		userMapper.updateById(user);
-		if (reset) {
-			mailService.send( "您的新密码为"+password,"密码变更提醒 | SEECODER",user.getEmail());
-		}
-	}
 }

+ 31 - 0
web/src/main/java/seecoder/devcloud/web/service/pipeline/DeploymentService.java

@@ -0,0 +1,31 @@
+package seecoder.devcloud.web.service.pipeline;
+
+import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
+
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description: 流水线实例部署相关的service
+ */
+public interface DeploymentService {
+
+    /**
+     * 获取项目部署的实例信息
+     */
+    List<DeploymentInfoVO> retrieveDeploymentInfos(Integer projectId);
+
+
+    /**
+     * 执行一条pipepine
+     * todo 异步/异步异常捕获刷新result
+     */
+    void deploy(Integer projectId,Integer pipelineId);
+
+    /**
+     * 删除一个实例
+     * todo 异步/异步异常捕获刷新result
+     */
+    void delete(Integer projectId,Integer pipelineId);
+}

+ 57 - 0
web/src/main/java/seecoder/devcloud/web/service/pipeline/PipelineService.java

@@ -0,0 +1,57 @@
+package seecoder.devcloud.web.service.pipeline;
+
+import seecoder.devcloud.web.model.po.pipeline.Deployment;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineConfigVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineCreateVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineHistoryVO;
+import seecoder.devcloud.web.model.vo.pipeline.PipelineInfoVO;
+
+import java.util.List;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/11
+ * @description: 流水线配置相关的service
+ *
+ *
+ * todo 验证是否有权限
+ */
+public interface PipelineService {
+
+//    /**
+//     * 获取此用户所在的所有组的所有的流水线信息
+//     */
+//    List<PipelineInfoVO> retrievePipelineInfos();
+
+    /**
+     * 获取一个项目所有的流水线信息
+     */
+    List<PipelineInfoVO> retrievePipelineInfos(Integer projectId);
+
+    /**
+     * 获取指定一条流水线的配置json信息
+     */
+    PipelineConfigVO retrievePipelineConfig(Integer projectId, Integer pipelineId);
+
+    /**
+     * 获取指定一条流水线的历史构建信息
+     */
+    List<PipelineHistoryVO> retrievePipelineHistory(Integer projectId, Integer pipelineId);
+
+    /**
+     * 依据模板创建一个流水线配置
+     */
+    void createPipelineConfig(PipelineCreateVO pipelineCreateVO);
+
+
+    /**
+     * 保存一条流水线的配置json信息
+     */
+    void savePipelineConfig(Integer projectId,Integer pipelineId, String configJson);
+
+    /**
+     * 删除一条流水线
+     */
+    void deletePipelineConfig(Integer projectId, Integer pipelineId);
+
+}

+ 1 - 4
web/src/main/java/seecoder/devcloud/web/service/user/GroupService.java

@@ -5,10 +5,7 @@ package seecoder.devcloud.web.service.user;
 import org.springframework.stereotype.Service;
 import seecoder.devcloud.common.exceptions.EntityNotFoundException;
 import seecoder.devcloud.common.exceptions.ServiceException;
-import seecoder.devcloud.web.vo.user.GroupVO;
-import seecoder.devcloud.web.vo.user.InnerGroupVO;
-
-import java.util.List;
+import seecoder.devcloud.web.model.vo.user.GroupVO;
 
 /**
  * @InterfaceName GroupService

+ 2 - 19
web/src/main/java/seecoder/devcloud/web/service/user/UserService.java

@@ -1,28 +1,11 @@
 package seecoder.devcloud.web.service.user;
 
 
-import seecoder.devcloud.common.exceptions.ServiceException;
-
-import seecoder.devcloud.web.vo.user.ChangePasswordVO;
-import seecoder.devcloud.web.vo.user.RegisterVO;
-import seecoder.devcloud.web.vo.user.UserVO;
+import seecoder.devcloud.web.model.vo.user.UserVO;
 
 public interface UserService {
 
-	UserVO register(RegisterVO form) throws ServiceException;
-
-	/**
-	 * 暂时没这个需求,先保留
-	 */
-	@Deprecated
-	UserVO registerTeacher(RegisterVO form) throws ServiceException;
-
-	void delete(int userId) throws ServiceException;
-
-	UserVO getUserById(Integer userid);
-
-	UserVO changeUserInfo(Integer userid, String nickName) throws ServiceException;
+    UserVO getLoginUser();
 
-	void changePassword(ChangePasswordVO form) throws ServiceException;
 
 }

+ 0 - 70
web/src/main/java/seecoder/devcloud/web/vo/Response.java

@@ -1,70 +0,0 @@
-package seecoder.devcloud.web.vo;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import seecoder.devcloud.web.enums.ResponseEnums;
-
-import java.io.Serializable;
-
-/**
- * @author PuHong Weng
- * @date 2021/2/1
- * @description:
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class Response<T> implements Serializable {
-
-    private String code;
-
-    private String msg;
-
-    private T data;
-
-    public Response(String code, String msg) {
-        this.code = code;
-        this.msg = msg;
-    }
-
-    public Response(ResponseEnums responseEnums) {
-        this.code = responseEnums.getCode();
-        this.msg = responseEnums.getMsg();
-    }
-
-    public Response(ResponseEnums responseEnums, T data) {
-        this.code = responseEnums.getCode();
-        this.msg = responseEnums.getMsg();
-        this.data = data;
-    }
-
-    public static Response ok() {
-        return new Response(ResponseEnums.OK);
-    }
-
-    public static <T> Response<T> ok(T data) {
-        return new Response<T>(ResponseEnums.OK,data);
-    }
-
-    public static Response notFound(String message) {
-        return new Response(ResponseEnums.NOT_FOUND, message);
-    }
-
-    public static Response badRequest(String message) {
-        return new Response(ResponseEnums.BAD_REQUEST, message);
-    }
-
-    public static Response forbidden(String message) {
-        return new Response(ResponseEnums.FORBIDDEN, message);
-    }
-
-    public static Response unauthorized(String message) {
-        return new Response(ResponseEnums.UNAUTHORIZED, message);
-    }
-
-    public static Response serverInternalError(String message) {
-        return new Response(ResponseEnums.SERVER_INTERNAL_ERROR, message);
-    }
-
-}

+ 0 - 25
web/src/main/java/seecoder/devcloud/web/vo/user/ChangePasswordVO.java

@@ -1,25 +0,0 @@
-package seecoder.devcloud.web.vo.user;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import seecoder.devcloud.common.validate.FieldEquals;
-
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Pattern;
-
-@Data
-@FieldEquals(firstField = "password", secondField = "confirm", message = "两次输入的新密码不一致!")
-@AllArgsConstructor
-public class ChangePasswordVO {
-
-	private Integer userId;
-	@NotNull(message = "请填写原密码!")
-	private String origin;
-	@Pattern(regexp = "[0-9a-zA-Z_]{8,16}", message = "密码只能包含大小写字母、数字和下划线,且必须为8-16位!")
-	@NotNull(message = "请填写新密码!")
-	private String password;
-	/**
-	 * 新密码要输入两遍,做确认
-	 */
-	private String confirm;
-}

+ 0 - 85
web/src/main/java/seecoder/devcloud/web/vo/user/CustomUserDetails.java

@@ -1,85 +0,0 @@
-//package seecoder.devcloud.web.vo.user;
-//
-//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-//
-//import lombok.*;
-//import org.apache.commons.codec.digest.DigestUtils;
-//import org.springframework.beans.BeanUtils;
-//import org.springframework.security.core.GrantedAuthority;
-//import org.springframework.security.core.userdetails.UserDetails;
-//import org.springframework.security.core.userdetails.UsernameNotFoundException;
-//import seecoder.devcloud.web.po.user.User;
-//
-//import java.util.Collections;
-//import java.util.Set;
-//
-//import static seecoder.devcloud.web.enums.UserIdentity.STUDENT;
-//import static seecoder.devcloud.web.enums.UserIdentity.TEACHER;
-//import static seecoder.devcloud.web.infrastructure.security.WebSecurityConstants.*;
-//
-//
-//@Data
-//@EqualsAndHashCode
-//@ToString
-//@NoArgsConstructor
-//@AllArgsConstructor
-//@JsonIgnoreProperties(ignoreUnknown = true)
-//public class CustomUserDetails implements UserDetails {
-//	private Integer id;
-//	private String username;
-//	private String password;
-//	private Set<GrantedAuthority> authorities;
-//
-//	CustomUserDetails(User user) {
-//		BeanUtils.copyProperties(user, this);
-//		switch (user.getRole()) {
-//			case STUDENT:
-//				this.authorities = Collections.singleton(STUDENT_AUTHORITY);
-//				break;
-//			case TEACHER:
-//				this.authorities = Collections.singleton(TEACHER_AUTHORITY);
-//				break;
-//			default:
-//				throw new UsernameNotFoundException(username);
-//		}
-//	}
-//
-//	CustomUserDetails(String username, String password) {
-//		this.id = 0;
-//		this.username = username;
-//		this.password = DigestUtils.sha256Hex(password);
-//		this.authorities = Collections.singleton(ADMIN_AUTHORITY);
-//	}
-//
-//	@Override
-//	public boolean isAccountNonExpired() {
-//		return true;
-//	}
-//
-//	@Override
-//	public boolean isAccountNonLocked() {
-//		return true;
-//	}
-//
-//	@Override
-//	public boolean isCredentialsNonExpired() {
-//		return true;
-//	}
-//
-//	@Override
-//	public boolean isEnabled() {
-//		return true;
-//	}
-//
-//	public boolean isStudent() {
-//		return authorities.contains(STUDENT_AUTHORITY);
-//	}
-//
-//	public boolean isTeacher() {
-//		return authorities.contains(TEACHER_AUTHORITY);
-//	}
-//
-//	public boolean isAdmin() {
-//		return authorities.contains(ADMIN_AUTHORITY);
-//	}
-//}

+ 0 - 24
web/src/main/java/seecoder/devcloud/web/vo/user/GroupDTO.java

@@ -1,24 +0,0 @@
-package seecoder.devcloud.web.vo.user;
-
-import lombok.Data;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-
-import javax.validation.constraints.NotNull;
-
-/**
- * @ClassName GroupDTO
- * @PackageName com.moekr.moocoder.web.dto
- * @Author sheen
- * @Date 2019/1/9
- * @Version 1.0
- * @Description //TODO
- **/
-@Data
-public class GroupDTO {
-    private Integer id;
-    @NotNull(message = "小组名称不能为空!", groups = {PostMapping.class, PutMapping.class})
-    private String name;
-    @NotNull(message = "课程ID不能为空!", groups = {PostMapping.class, PutMapping.class})
-    private Integer courseId;
-}

+ 0 - 31
web/src/main/java/seecoder/devcloud/web/vo/user/InnerGroupVO.java

@@ -1,31 +0,0 @@
-package seecoder.devcloud.web.vo.user;
-
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import seecoder.devcloud.web.po.user.Group;
-import seecoder.devcloud.web.po.user.User;
-
-import java.util.List;
-
-/**
- * 暂定为系统内部给作业部分使用的VO
- */
-@Data
-@EqualsAndHashCode(exclude = {"members"})
-@ToString(exclude = {"members"})
-public class InnerGroupVO {
-    private Integer id;
-    private Integer namespace;
-    private String name;
-    private List<User> members;
-
-
-    public InnerGroupVO(Group group) {
-        this.id = group.getId();
-        this.namespace = group.getNamespace();
-        this.name = group.getName();
-        this.members = group.getMembers();
-    }
-}

+ 0 - 24
web/src/main/java/seecoder/devcloud/web/vo/user/UserDTO.java

@@ -1,24 +0,0 @@
-package seecoder.devcloud.web.vo.user;
-
-import lombok.Data;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import seecoder.devcloud.web.enums.UserIdentity;
-
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Pattern;
-
-@Data
-public class UserDTO {
-	@Pattern(regexp = "[0-9a-zA-Z_]{4,16}", message = "用户名只能包含大小写字母、数字和下划线,且必须为4-16位!", groups = PostMapping.class)
-	@NotNull(message = "请填写用户名!", groups = PostMapping.class)
-	private String username;
-	@Email(message = "邮箱格式不正确!", groups = {PostMapping.class, PutMapping.class})
-	@NotNull(message = "请填写邮箱!", groups = {PostMapping.class, PutMapping.class})
-	private String email;
-//	@NotNull(message = "请选择用户角色!", groups = PostMapping.class)
-	private UserIdentity role;
-	//string | null
-	private String nickname;
-}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio