فهرست منبع

milestone - 测试环境当前版本

master 分支修复 bug,新功能在新分支上开发
reghao 5 سال پیش
والد
کامیت
21261b1542
40فایلهای تغییر یافته به همراه318 افزوده شده و 200 حذف شده
  1. 2 2
      common/src/main/java/cn/reghao/autodop/common/deploy/DeployConfig.java
  2. 1 1
      common/src/main/java/cn/reghao/autodop/common/grpc/facade/app/AppDeployService.java
  3. 5 10
      common/src/main/java/cn/reghao/autodop/common/notification/DingNotify.java
  4. 1 1
      common/src/main/java/cn/reghao/autodop/common/notification/Notify.java
  5. 0 1
      common/src/main/java/cn/reghao/autodop/common/notification/ding/DingMsg.java
  6. 2 3
      common/src/main/java/cn/reghao/autodop/common/notification/ding/DingText.java
  7. 9 5
      dagent/src/main/java/cn/reghao/autodop/dagent/app/AppDeployServiceImpl.java
  8. 1 3
      dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/Deploy.java
  9. 1 2
      dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/DockerDeploy.java
  10. 1 2
      dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/ZipDeploy.java
  11. 1 3
      dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/ZipRemoteDeploy.java
  12. 5 5
      dmaster/src/main/java/cn/reghao/autodop/dmaster/DmasterApplication.java
  13. 3 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/AppBuildController.java
  14. 3 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/BaseEntity.java
  15. 2 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/orchestration/AppOrchestration.java
  16. 0 17
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/repository/orchestration/AppDAO.java
  17. 2 4
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/repository/orchestration/AppOrchestrationRepository.java
  18. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppBuildService.java
  19. 0 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/build/AppBuildPipeline.java
  20. 4 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/build/BuildDispatcher.java
  21. 4 5
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/deploy/AppDeployTask.java
  22. 22 10
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/deploy/AppDeployer.java
  23. 26 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/deploy/NotifyTask.java
  24. 1 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/tools/updater/GitImpl.java
  25. 13 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/IndexController.java
  26. 57 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/GrantedAuthorityImpl.java
  27. 10 7
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/UserAuth.java
  28. 18 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/jwt/JwtTokenFilter.java
  29. 0 11
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/jwt/UserDetailsServiceImpl.java
  30. 0 1
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/repository/RoleRepository.java
  31. 25 35
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/UserService.java
  32. 39 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/vo/UserAuthVO.java
  33. 2 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/common/config/SysConfig.java
  34. 0 22
      dmaster/src/main/java/cn/reghao/autodop/dmaster/common/config/SysConfigProperties.java
  35. 24 16
      dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/AfterAppStart.java
  36. 3 3
      dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/BeforeAppShutdown.java
  37. 24 0
      dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/UserContext.java
  38. 3 7
      dmaster/src/main/resources/application-dev.yml
  39. 1 5
      dmaster/src/main/resources/application-test.yml
  40. 2 2
      dmaster/src/test/java/cn/reghao/autodop/common/notification/DingNotifyTest.java

+ 2 - 2
common/src/main/java/cn/reghao/autodop/common/deploy/DeployConfig.java

@@ -11,8 +11,8 @@ import lombok.Data;
 @Data
 public class DeployConfig {
     private String appId;
-    private String appPath;
     private String packerType;
-    private String runningDir;
+    private String appPath;
     private String host;
+    private String runningDir;
 }

+ 1 - 1
common/src/main/java/cn/reghao/autodop/common/grpc/facade/app/AppDeployService.java

@@ -11,5 +11,5 @@ import cn.reghao.autodop.common.grpc.common.serializer.SerializerType;
  */
 @GrpcService(service = "appDeploy", serialization = SerializerType.FastJson)
 public interface AppDeployService {
-    Object deploy(Object object) throws Exception;
+    void deploy(Object object) throws Exception;
 }

+ 5 - 10
common/src/main/java/cn/reghao/autodop/common/notification/DingNotify.java

@@ -14,16 +14,11 @@ public class DingNotify implements Notify {
     private WebRequest webRequest = new DefaultWebRequest();
 
     @Override
-    public boolean send(String destination, String content) {
-        try {
-            DingText dingText = new DingText(content);
-            WebResponse webResponse = webRequest.postJson(destination, JsonUtil.objectToJson(dingText));
-            if (webResponse.getStatusCode() == 200) {
-                return true;
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
+    public void send(String destination, Object content) throws Exception {
+        DingText dingText = new DingText(content);
+        WebResponse webResponse = webRequest.postJson(destination, JsonUtil.objectToJson(dingText));
+        if (webResponse.getStatusCode() == 200) {
+            throw new Exception("发送通知失败");
         }
-        return false;
     }
 }

+ 1 - 1
common/src/main/java/cn/reghao/autodop/common/notification/Notify.java

@@ -5,5 +5,5 @@ package cn.reghao.autodop.common.notification;
  * @date 2020-05-07 01:41:27
  */
 public interface Notify {
-    boolean send(String dest, String content);
+    void send(String dest, Object content) throws Exception;
 }

+ 0 - 1
common/src/main/java/cn/reghao/autodop/common/notification/ding/DingMsg.java

@@ -20,7 +20,6 @@ public class DingMsg<T> {
 
     public DingMsg(String msgtype) {
         this.msgtype = msgtype;
-
         this.at = new HashMap<>();
         at.put("atMobiles", null);
         at.put("isAtAll", String.valueOf(true));

+ 2 - 3
common/src/main/java/cn/reghao/autodop/common/notification/ding/DingText.java

@@ -15,11 +15,10 @@ import java.util.Map;
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class DingText extends DingMsg<String> {
-    private Map<String, String> text;
+    private Map<String, Object> text;
 
-    public DingText(String content) {
+    public DingText(Object content) {
         super("text");
-
         text = new HashMap<>();
         text.put("content", content);
     }

+ 9 - 5
dagent/src/main/java/cn/reghao/autodop/dagent/app/DockerAppDeployServiceImpl.java → dagent/src/main/java/cn/reghao/autodop/dagent/app/AppDeployServiceImpl.java

@@ -10,16 +10,18 @@ import com.alibaba.fastjson.JSONObject;
 import org.springframework.stereotype.Service;
 
 /**
+ * 应用部署服务
+ *
  * @author reghao
  * @date 2019-11-07 10:54:01
  */
 @Service
-public class DockerAppDeployServiceImpl implements AppDeployService {
-    public DockerAppDeployServiceImpl() {
+public class AppDeployServiceImpl implements AppDeployService {
+    public AppDeployServiceImpl() {
     }
 
     @Override
-    public Boolean deploy(Object object) throws Exception {
+    public void deploy(Object object) throws Exception {
         JSONObject jsonObject = (JSONObject) object;
         DeployConfig deployConfig = jsonObject.toJavaObject(DeployConfig.class);
 
@@ -33,7 +35,8 @@ public class DockerAppDeployServiceImpl implements AppDeployService {
             case docker:
                 deployApp = new DockerDeploy();
                 // TODO 对变量的使用,变量返回后应避免再设置其内部字段的值
-                return deployApp.deploy(appId, appPath, null);
+                deployApp.deploy(appId, appPath, null);
+                break;
             /*case maven:
                 break;
             case jar:
@@ -42,7 +45,8 @@ public class DockerAppDeployServiceImpl implements AppDeployService {
                 break;*/
             case zip:
                 deployApp = new ZipDeploy();
-                return deployApp.deploy(appId, appPath, runningDir);
+                deployApp.deploy(appId, appPath, runningDir);
+                break;
             default:
                 throw new Exception("打包类型 " + packerType + " 不存在");
         }

+ 1 - 3
dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/Deploy.java

@@ -13,9 +13,7 @@ public interface Deploy {
      * @param appId 应用标识
      * @param appPath 完成的应用路径(HTTP 地址或 docker 地址)
      * @param runningDir 应用运行根目录
-     *
-     * @return true or false
      * @date 2019-10-15 下午4:57
      */
-    boolean deploy(String appId, String appPath, String runningDir) throws Exception;
+    void deploy(String appId, String appPath, String runningDir) throws Exception;
 }

+ 1 - 2
dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/DockerDeploy.java

@@ -13,11 +13,10 @@ import lombok.extern.slf4j.Slf4j;
 @Slf4j
 public class DockerDeploy implements Deploy {
     @Override
-    public boolean deploy(String appId, String appPath, String runningDir) throws DockerException {
+    public void deploy(String appId, String appPath, String runningDir) throws DockerException {
         try(DockerClient docker = new DockerClient()) {
             docker.pull(appPath);
             docker.run(appId, appPath);
-            return true;
         }
     }
 }

+ 1 - 2
dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/ZipDeploy.java

@@ -15,7 +15,7 @@ import java.io.File;
  */
 public class ZipDeploy implements Deploy {
     @Override
-    public boolean deploy(String appId, String appPath, String runningDir) throws Exception {
+    public void deploy(String appId, String appPath, String runningDir) throws Exception {
         WebRequest request = new DefaultWebRequest();
         String appDir = runningDir + "/" + appId;
         String appRunningDir = appDir + "/app";
@@ -30,7 +30,6 @@ public class ZipDeploy implements Deploy {
         // TODO 前端静态文件并不存在运行的概念,它与二进制运行文件和 Python 之类的应用不同
         FileUtil.eraseDir(new File(appRunningDir));
         ZipUtil.unzip(filepath, appRunningDir);
-        return true;
     }
 
     private void checkDir(String appDir, String appRunningDir) throws Exception {

+ 1 - 3
dagent/src/main/java/cn/reghao/autodop/dagent/app/deploy/ZipRemoteDeploy.java

@@ -15,7 +15,7 @@ import java.io.File;
  */
 public class ZipRemoteDeploy implements Deploy {
     @Override
-    public boolean deploy(String appId, String appPath, String runningDir) throws Exception {
+    public void deploy(String appId, String appPath, String runningDir) throws Exception {
         WebRequest request = new DefaultWebRequest();
         String appDir = runningDir + "/" + appId;
         String appRunningDir = appDir + "/app";
@@ -28,8 +28,6 @@ public class ZipRemoteDeploy implements Deploy {
         }
         FileUtil.eraseDir(new File(appRunningDir));
         ZipUtil.unzip(filepath, appRunningDir);
-
-        return true;
     }
 
     private void checkDir(String appDir, String appRunningDir) throws Exception {

+ 5 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/DmasterApplication.java

@@ -1,7 +1,7 @@
 package cn.reghao.autodop.dmaster;
 
 import cn.reghao.autodop.common.grpc.common.annotation.GrpcServiceScan;
-import cn.reghao.autodop.dmaster.common.utils.BeforeShutdown;
+import cn.reghao.autodop.dmaster.common.utils.BeforeAppShutdown;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.domain.EntityScan;
@@ -24,14 +24,14 @@ public class DmasterApplication {
 	}
 
 	@Bean
-	public BeforeShutdown shutdownGracefully() {
-		return new BeforeShutdown(30);
+	public BeforeAppShutdown shutdownGracefully() {
+		return new BeforeAppShutdown(30);
 	}
 
 	@Bean
-	public ConfigurableServletWebServerFactory webServerFactory(final BeforeShutdown beforeShutdown) {
+	public ConfigurableServletWebServerFactory webServerFactory(final BeforeAppShutdown beforeAppShutdown) {
 		TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
-		factory.addConnectorCustomizers(beforeShutdown);
+		factory.addConnectorCustomizers(beforeAppShutdown);
 		return factory;
 	}
 }

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/controller/AppBuildController.java

@@ -98,9 +98,9 @@ public class AppBuildController {
             @ApiImplicitParam(name="commitId", value="应用地址", paramType="query", dataType = "String")
     })
     @PostMapping("/deploy")
-    public String deploy(@RequestParam("appId") String appId, @RequestParam("commitId") String commitId)
-            throws Exception {
-        return WebResult.fail("待实现");
+    public String deploy(@RequestParam("appId") String appId, @RequestParam("commitId") String commitId) {
+        buildDispatcher.deploy(appId, commitId);
+        return WebResult.success("待实现");
     }
 
     @ApiOperation(value = "部署 OSS 资源")

+ 3 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/BaseEntity.java

@@ -24,6 +24,9 @@ public class BaseEntity implements Serializable {
     @Id
     @GeneratedValue(strategy = GenerationType.TABLE)
     protected Long id;
+    // 记录是否已删除
+    @Column(nullable = false)
+    private boolean isDelete;
 
     @CreationTimestamp
     @Column(updatable = false)

+ 2 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/entity/orchestration/AppOrchestration.java

@@ -52,13 +52,12 @@ public class AppOrchestration extends BaseEntity implements Cloneable {
     @ManyToOne(cascade = CascadeType.PERSIST)
     @JoinColumn(name = "notification_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
     private Notification notification;
-    /*@ManyToOne(cascade = CascadeType.PERSIST)
+    @ManyToOne(cascade = CascadeType.PERSIST)
     @JoinColumn(name = "role_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
-    private Role role;*/
+    private Role role;
     // 是否启用编排
     @Column(nullable = false)
     private boolean enable;
-    //private boolean delete;
     // TODO 添加定时构建部署选项
     // TODO 接入到项目管理系统
 

+ 0 - 17
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/repository/orchestration/AppDAO.java

@@ -1,6 +1,5 @@
 package cn.reghao.autodop.dmaster.app.repository.orchestration;
 
-import cn.reghao.autodop.dmaster.app.entity.deploy.DeployedApp;
 import org.hibernate.Session;
 import org.springframework.stereotype.Repository;
 
@@ -41,20 +40,4 @@ public class AppDAO {
             return list;
         }
     }
-
-    public List<DeployedApp> findDeployedApps(String env) {
-        try (Session session = (Session) em.getDelegate()) {
-            String hql = "select app.appId,deployed.commitId from DeployedApp deployed " +
-                    "inner join AppOrchestration app " +
-                    "on deployed.app=app " +
-                    "where app.env=:env " +
-                    "order by deployed.updateTime desc";
-
-            Query hqlQuery = session.createQuery(hql)
-                    .setParameter("env", env);
-
-            List list = hqlQuery.getResultList();
-            return list;
-        }
-    }
 }

+ 2 - 4
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/repository/orchestration/AppOrchestrationRepository.java

@@ -7,7 +7,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Modifying;
 
 import javax.transaction.Transactional;
-import java.util.List;
 
 /**
  *
@@ -15,10 +14,9 @@ import java.util.List;
  * @date 2020-01-21 14:53:03
  */
 public interface AppOrchestrationRepository extends JpaRepository<AppOrchestration, Long> {
-    AppOrchestration findByAppId(String appId);
-    List<AppOrchestration> findAllByEnableIsTrue();
-    Page<AppOrchestration> findAllByEnableIsTrueAndEnv(String env, Pageable pageable);
     Page<AppOrchestration> findByEnv(String env, Pageable pageable);
+    Page<AppOrchestration> findAllByEnableIsTrueAndIsDeleteIsFalseAndEnv(String env, Pageable pageable);
+    AppOrchestration findByAppId(String appId);
 
     @Modifying
     @Transactional

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/AppBuildService.java

@@ -44,7 +44,7 @@ public class AppBuildService {
 
     public PageList<AppToBuild> buildList(String env, PageRequest pageRequest) {
         PageList<AppToBuild> pageList = new PageList<>();
-        Page<AppOrchestration> apps = appRepository.findAllByEnableIsTrueAndEnv(env, pageRequest);
+        Page<AppOrchestration> apps = appRepository.findAllByEnableIsTrueAndIsDeleteIsFalseAndEnv(env, pageRequest);
         pageList.setTotalSize(apps.getTotalElements());
         pageList.setTotalPages(apps.getTotalPages());
         Set<String> appIds = apps.stream()

+ 0 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/build/AppBuildPipeline.java

@@ -48,7 +48,6 @@ public class AppBuildPipeline implements Callable<BuildDeployLog> {
 
         if (isDeploy) {
             appIntegrate.deploy();
-            return appIntegrate.log();
         }
 
         return appIntegrate.log();

+ 4 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/build/BuildDispatcher.java

@@ -109,4 +109,8 @@ public class BuildDispatcher {
 
         return list;
     }
+
+    public void deploy(String appId, String commitId) {
+        AppOrchestration app = caching.findByAppId(appId);
+    }
 }

+ 4 - 5
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/deploy/AppDeployTask.java

@@ -12,7 +12,7 @@ import java.util.concurrent.Callable;
  * @author reghao
  * @date 2019-11-16 21:39:53
  */
-public class AppDeployTask implements Callable<Boolean> {
+public class AppDeployTask implements Callable<Void> {
     // TODO 配置文件中指定 gRPC 服务器端口
     private static final int GRPC_PORT = 4001;
     private DeployConfig deployConfig;
@@ -23,13 +23,12 @@ public class AppDeployTask implements Callable<Boolean> {
 
     // 异常在 Future 中抛出
     @Override
-    public Boolean call() throws Exception {
+    public Void call() throws Exception {
         // TODO 公共网络下,gRPC 调用需要经过认证
-        // TODO 使用异步消息替换 gRPC
         AppDeployService appDeployService = (AppDeployService)new GrpcClientProxy<AppDeployService>()
                 .getProxy(deployConfig.getHost(), GRPC_PORT, AppDeployService.class);
-
         // TODO 处理超时未返回的情况
-        return (Boolean) appDeployService.deploy(deployConfig);
+        appDeployService.deploy(deployConfig);
+        return null;
     }
 }

+ 22 - 10
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/deploy/AppDeployer.java

@@ -12,6 +12,7 @@ import cn.reghao.autodop.dmaster.app.entity.log.DeployResult;
 import cn.reghao.autodop.dmaster.app.entity.orchestration.AppOrchestration;
 import cn.reghao.autodop.dmaster.app.entity.orchestration.Notification;
 import cn.reghao.autodop.dmaster.app.thread.ThreadPoolWrapper;
+import lombok.Data;
 
 import java.util.*;
 import java.util.concurrent.ExecutorService;
@@ -42,7 +43,7 @@ public class AppDeployer {
 
         AppPack appPack = app.getAppBuild().getAppPack();
         AppDeploy appDeploy = app.getAppDeploy();
-        Map<String, Future<Boolean>> futureMap = new HashMap<>();
+        Map<String, Future<Void>> futureMap = new HashMap<>();
         for (String host : appDeploy.getHosts()) {
             DeployConfig deployConfig = new DeployConfig();
             deployConfig.setAppId(app.getAppId());
@@ -58,9 +59,9 @@ public class AppDeployer {
         deployLog.setBuildLog(buildLog);
         Set<DeployResult> deployResults = new HashSet<>();
         deployLog.setDeployResults(deployResults);
-        for (Map.Entry<String, Future<Boolean>> entry : futureMap.entrySet()) {
+        for (Map.Entry<String, Future<Void>> entry : futureMap.entrySet()) {
             String host = entry.getKey();
-            Future<Boolean> future = entry.getValue();
+            Future<Void> future = entry.getValue();
             while (!future.isDone() && !future.isCancelled()) {
                 // 休眠等待异步任务结束
                 try {
@@ -71,19 +72,30 @@ public class AppDeployer {
             }
 
             // TODO 检查应用是否成功运行,若启动失败,则回退到上一个版本。若上一个版本仍失败,则返回错误并发出紧急通知
+            NotifyMsg notifyMsg = new NotifyMsg(app.getAppId(), buildLog.getCommitLog().getCommitId());
             try {
-                Boolean isDeploy = future.get();
-                if (isDeploy) {
-                    deployResults.add(DeployResult.success(host));
-                }
+                future.get();
+                notifyMsg.setMsg("部署成功");
+                deployResults.add(DeployResult.success(host));
             } catch (Exception e) {
                 e.printStackTrace();
+                notifyMsg.setMsg("部署失败");
                 deployResults.add(DeployResult.fail(host, e.getMessage()));
             }
+            threadPool.submit(new NotifyTask(notify, dest, notifyMsg));
         }
-        // TODO 异步发送通知
-        //notify.send(dest, JsonUtil.objectToJson(deployMsg));
-        // TODO 部署成功后记录到数据库
         return deployLog;
     }
+
+    @Data
+    static class NotifyMsg {
+        private String appId;
+        private String commitId;
+        private String msg;
+
+        public NotifyMsg(String appId, String commitId) {
+            this.appId = appId;
+            this.commitId = commitId;
+        }
+    }
 }

+ 26 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/deploy/NotifyTask.java

@@ -0,0 +1,26 @@
+package cn.reghao.autodop.dmaster.app.service.deploy;
+
+import cn.reghao.autodop.common.notification.Notify;
+import java.util.concurrent.Callable;
+
+/**
+ * @author reghao
+ * @date 2020-06-24 10:32:34
+ */
+public class NotifyTask implements Callable<Void> {
+    private Notify notify;
+    private String dest;
+    private Object msg;
+
+    public NotifyTask(Notify notify, String dest, Object msg) {
+        this.notify = notify;
+        this.dest = dest;
+        this.msg = msg;
+    }
+
+    @Override
+    public Void call() throws Exception {
+        notify.send(dest, msg);
+        return null;
+    }
+}

+ 1 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/app/service/tools/updater/GitImpl.java

@@ -19,7 +19,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * git 实现
+ * TODO git 实现
  *
  * @author reghao
  * @date 2019-10-12 22:22:00

+ 13 - 7
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/controller/IndexController.java

@@ -1,10 +1,14 @@
 package cn.reghao.autodop.dmaster.auth.controller;
 
+import cn.reghao.autodop.common.utils.DateTimeUtil;
 import cn.reghao.autodop.common.utils.JsonUtil;
 import cn.reghao.autodop.dmaster.auth.entity.Permission;
 import cn.reghao.autodop.dmaster.auth.entity.Role;
+import cn.reghao.autodop.dmaster.auth.entity.UserAuth;
 import cn.reghao.autodop.dmaster.auth.repository.PermissionRepository;
 import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
+import cn.reghao.autodop.dmaster.common.utils.UserContext;
+import cn.reghao.autodop.dmaster.common.webresult.WebResult;
 import cn.reghao.autodop.dmaster.vue.VueRole;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -13,11 +17,9 @@ import io.swagger.annotations.ApiOperation;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.bind.annotation.*;
 
+import java.time.LocalDateTime;
 import java.util.*;
 
 /**
@@ -42,9 +44,8 @@ public class IndexController {
     )
     @GetMapping("/api/getPages")
     public ResponseEntity<String> getPages() {
-        // TODO 使用 UserContext 来获取当前线程访问的用户
-        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
-        String username = auth.getName();
+        UserAuth auth = UserContext.currentUser();
+        String username = auth.getUsername();
         List<String> roles = new ArrayList<>();
         auth.getAuthorities().forEach(authority -> {
             Role role = roleRepository.findRoleByName(authority.getAuthority());
@@ -60,7 +61,7 @@ public class IndexController {
 
         UserInfo userInfo = new UserInfo();
         userInfo.setName(username);
-        userInfo.setIntroduce("I am admin");
+        userInfo.setIntroduce("I am " + username);
         userInfo.setRoles(roles);
         result.setData(userInfo);
 
@@ -114,6 +115,11 @@ public class IndexController {
         return ResponseEntity.ok().body("bar data");
     }
 
+    @GetMapping("/datetime")
+    public ResponseEntity<String> test() {
+        return ResponseEntity.ok().body(DateTimeUtil.format(LocalDateTime.now()));
+    }
+
     @Data
     static class Result {
         private int code;

+ 57 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/GrantedAuthorityImpl.java

@@ -0,0 +1,57 @@
+package cn.reghao.autodop.dmaster.auth.entity;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.SpringSecurityCoreVersion;
+import org.springframework.util.Assert;
+
+import javax.persistence.Embeddable;
+
+/**
+ * SimpleGrantedAuthority 的重写
+ *
+ * @author reghao
+ * @date 2020-06-24 14:44:25
+ */
+@Embeddable
+public class GrantedAuthorityImpl implements GrantedAuthority {
+    private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
+
+    private final String role;
+
+    public GrantedAuthorityImpl() {
+        this.role = "";
+    }
+
+    public GrantedAuthorityImpl(String role) {
+        Assert.hasText(role, "A granted authority textual representation is required");
+        this.role = role;
+    }
+
+    @Override
+    public String getAuthority() {
+        return role;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof GrantedAuthorityImpl) {
+            return role.equals(((GrantedAuthorityImpl) obj).role);
+        }
+
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.role.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return this.role;
+    }
+}

+ 10 - 7
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/entity/UserAuth.java

@@ -29,18 +29,21 @@ public class UserAuth  extends BaseEntity implements UserDetails {
     private String password;
     @Column(nullable = false)
     private String salt;
-    // 数据库表中默认为 ROLE_USER
-    /*@Column(nullable = false)
-    private int roleId;*/
-    @ManyToOne(cascade = CascadeType.PERSIST)
-    @JoinColumn(name = "role_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
-    private Role role;
     // 数据库表中默认为 0
     private int status;
     // 数据库表中默认为 0
     private int locked;
     @ElementCollection(fetch = FetchType.EAGER)
-    private Set<GrantedAuthority> authorities;
+    private Set<GrantedAuthorityImpl> authorities;
+
+    public UserAuth(String username, Set<GrantedAuthorityImpl> authorities) {
+        this.username = username;
+        this.authorities = authorities;
+    }
+
+    public Set<GrantedAuthorityImpl> authorities() {
+        return this.authorities;
+    }
 
     @Override
     public String getUsername() {

+ 18 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/jwt/JwtTokenFilter.java

@@ -1,5 +1,8 @@
 package cn.reghao.autodop.dmaster.auth.jwt;
 
+import cn.reghao.autodop.dmaster.auth.entity.GrantedAuthorityImpl;
+import cn.reghao.autodop.dmaster.auth.entity.UserAuth;
+import cn.reghao.autodop.dmaster.common.utils.UserContext;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.filter.OncePerRequestFilter;
@@ -8,6 +11,8 @@ import javax.servlet.*;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * 验证请求是否携带 JWT token,每个请求都会被验证
@@ -33,7 +38,19 @@ public class JwtTokenFilter extends OncePerRequestFilter {
             if (JwtToken.isValid(token)) {
                 // TODO 计算当前离过期时间还有多久
                 Authentication authentication = JwtToken.getAuthentication(request);
-                SecurityContextHolder.getContext().setAuthentication(authentication);
+                if (authentication != null) {
+                    SecurityContextHolder.getContext().setAuthentication(authentication);
+                    String username = authentication.getName();
+                    Set<GrantedAuthorityImpl> authorities = authentication.getAuthorities().stream()
+                            .map(authority -> new GrantedAuthorityImpl(authority.getAuthority()))
+                            .collect(Collectors.toSet());
+                    // TODO 获取当前访问的用户信息
+                    UserAuth userAuth = new UserAuth(username, authorities);
+                    try (UserContext context = new UserContext(userAuth)) {
+                        chain.doFilter(request, response);
+                    }
+                    return;
+                }
             } else {
                 // TODO 使用刷新令牌获取一个新的访问令牌
                 response.sendError(HttpServletResponse.SC_FORBIDDEN, "令牌已过期");

+ 0 - 11
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/jwt/UserDetailsServiceImpl.java

@@ -4,16 +4,11 @@ import cn.reghao.autodop.dmaster.auth.entity.UserAuth;
 import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
 import cn.reghao.autodop.dmaster.auth.repository.UserAuthRepository;
 import org.springframework.security.authentication.DisabledException;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
 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 java.util.HashSet;
-import java.util.Set;
-
 /**
  * 用户名密码认证
  *
@@ -34,12 +29,6 @@ public class UserDetailsServiceImpl implements UserDetailsService {
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
         UserAuth userAuth = authRepository.findUserAuthByUsername(username);
         if (userAuth != null) {
-            String role = userAuth.getRole().getName();
-            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
-            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role);
-            grantedAuthorities.add(grantedAuthority);
-            // 用户的权限
-            userAuth.setAuthorities(grantedAuthorities);
             return userAuth;
         } else {
             // Spring Security 会将 UsernameNotFoundException 捕获并替换,使得前端无法看到信息

+ 0 - 1
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/repository/RoleRepository.java

@@ -9,5 +9,4 @@ import org.springframework.data.jpa.repository.JpaRepository;
  */
 public interface RoleRepository extends JpaRepository<Role, Integer> {
     Role findRoleByName(String roleName);
-    Role findRoleById(long id);
 }

+ 25 - 35
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/service/UserService.java

@@ -11,12 +11,15 @@ import cn.reghao.autodop.dmaster.auth.entity.UserAuth;
 import cn.reghao.autodop.dmaster.auth.repository.PermissionRepository;
 import cn.reghao.autodop.dmaster.auth.repository.RoleRepository;
 import cn.reghao.autodop.dmaster.auth.repository.UserAuthRepository;
+import cn.reghao.autodop.dmaster.auth.vo.UserAuthVO;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
+import org.springframework.security.core.GrantedAuthority;
 import org.springframework.stereotype.Service;
 
 import java.security.NoSuchAlgorithmException;
 import java.time.LocalDateTime;
+import java.util.List;
 import java.util.stream.Collectors;
 
 /**
@@ -74,31 +77,28 @@ public class UserService {
                 }
                 break;
             case 3:
-                UserAuth userAuth = (UserAuth) JsonUtil.jsonToObject(json, UserAuth.class);
-                String password = userAuth.getPassword();
-                String salt = Salt.get(64);
-                String encryptedPwd = cryptor.encrypt(password + salt);
-                userAuth.setPassword(encryptedPwd);
-                userAuth.setSalt(salt);
-                String roleName = rolePrefix + userAuth.getRole().getName();
-                Role roleEntity2 = roleRepository.findRoleByName(roleName);
-                if (roleEntity2 != null) {
-                    userAuth.setRole(roleEntity2);
-                } else {
-                    return;
-                }
-
+                UserAuthVO vo = (UserAuthVO) JsonUtil.jsonToObject(json, UserAuthVO.class);
+                UserAuth userAuth = vo.to();
                 UserAuth authEntity = userAuthRepository.findUserAuthByUsername(userAuth.getUsername());
                 if (authEntity == null) {
+                    String password = userAuth.getPassword();
+                    String salt = Salt.get(64);
+                    String encryptedPwd = cryptor.encrypt(password + salt);
+                    userAuth.setPassword(encryptedPwd);
+                    userAuth.setSalt(salt);
                     userAuthRepository.save(userAuth);
                 } else {
-                    authEntity.setPassword(userAuth.getPassword());
-                    authEntity.setSalt(salt);
-                    authEntity.setRole(userAuth.getRole());
+                    if (!authEntity.getPassword().equals(userAuth.getPassword())) {
+                        String password = userAuth.getPassword();
+                        String salt = Salt.get(64);
+                        String encryptedPwd = cryptor.encrypt(password + salt);
+                        authEntity.setPassword(encryptedPwd);
+                        authEntity.setSalt(salt);
+                    }
+                    authEntity.setAuthorities(userAuth.authorities());
                     authEntity.setUpdateTime(LocalDateTime.now());
                     userAuthRepository.save(authEntity);
                 }
-
                 break;
             default:
                 break;
@@ -135,23 +135,13 @@ public class UserService {
                 return permissionPageList;
             case 3:
                 Page<UserAuth> userAuthPage = userAuthRepository.findAll(pageRequest);
-                PageList<UserAuth> userAuthPageList = new PageList<>();
-                userAuthPageList.setTotalSize(userAuthPage.getTotalElements());
-                userAuthPageList.setTotalPages(userAuthPage.getTotalPages());
-                userAuthPageList.setList(userAuthPage.getContent().stream()
-                        .peek(userAuth -> {
-                            // Role 是一个共享实体
-                            Role role = userAuth.getRole();
-                            /* TODO 数组越界异常后会返回 401,而不是 500
-                            String name = role.getName().split(rolePrefix)[1];
-                            role.setName(name);*/
-                            if (role.getName().contains(rolePrefix)) {
-                                String name = role.getName().split(rolePrefix)[1];
-                                role.setName(name);
-                            }
-                        }).collect(Collectors.toList()));
-
-                return userAuthPageList;
+                PageList<UserAuthVO> userAuthVOPageList = new PageList<>();
+                userAuthVOPageList.setTotalSize(userAuthPage.getTotalElements());
+                userAuthVOPageList.setTotalPages(userAuthPage.getTotalPages());
+                userAuthVOPageList.setList(userAuthPage.getContent().stream()
+                        .map(UserAuthVO::new)
+                        .collect(Collectors.toList()));
+                return userAuthVOPageList;
             default:
                 return null;
         }

+ 39 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/auth/vo/UserAuthVO.java

@@ -0,0 +1,39 @@
+package cn.reghao.autodop.dmaster.auth.vo;
+
+import cn.reghao.autodop.dmaster.auth.entity.GrantedAuthorityImpl;
+import cn.reghao.autodop.dmaster.auth.entity.UserAuth;
+import lombok.Data;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author reghao
+ * @date 2020-06-24 15:12:12
+ */
+@Data
+public class UserAuthVO {
+    private String username;
+    private String password;
+    private List<String> roles;
+
+    public UserAuthVO(UserAuth userAuth) {
+        this.username = userAuth.getUsername();
+        this.password = userAuth.getPassword();
+        this.roles = userAuth.getAuthorities().stream()
+                .map(GrantedAuthority::getAuthority)
+                .map(role -> role.split("ROLE_")[1])
+                .collect(Collectors.toList());
+    }
+
+    public UserAuth to() {
+        UserAuth userAuth = new UserAuth();
+        userAuth.setUsername(this.getUsername());
+        userAuth.setAuthorities(this.getRoles().stream()
+                .map(role -> "ROLE_" + role)
+                .map(GrantedAuthorityImpl::new)
+                .collect(Collectors.toSet()));
+        return userAuth;
+    }
+}

+ 2 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/common/config/SysConfig.java

@@ -1,6 +1,8 @@
 package cn.reghao.autodop.dmaster.common.config;
 
 /**
+ * TODO 使用缓存替代
+ *
  * @author reghao
  * @date 2020-03-09 14:36:41
  */

+ 0 - 22
dmaster/src/main/java/cn/reghao/autodop/dmaster/common/config/SysConfigProperties.java

@@ -1,22 +0,0 @@
-package cn.reghao.autodop.dmaster.common.config;
-
-import lombok.Data;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * @author reghao
- * @date 2019-08-27 00:17:55
- */
-@Data
-@Component
-@ConfigurationProperties(prefix = "sysconfig")
-public class SysConfigProperties {
-    @Value("${sysconfig.localRepo}")
-    private String localRepo;
-    @Value("${sysconfig.compileDir}")
-    private String compileDir;
-    @Value("${sysconfig.packDir}")
-    private String packDir;
-}

+ 24 - 16
dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/SysInitializer.java → dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/AfterAppStart.java

@@ -1,8 +1,9 @@
 package cn.reghao.autodop.dmaster.common.utils;
 
 import cn.reghao.autodop.common.utils.FileUtil;
+import cn.reghao.autodop.dmaster.app.entity.orchestration.LocalFsConfig;
+import cn.reghao.autodop.dmaster.app.repository.orchestration.LocalFsConfigRepository;
 import cn.reghao.autodop.dmaster.common.config.SysConfig;
-import cn.reghao.autodop.dmaster.common.config.SysConfigProperties;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.ApplicationArguments;
 import org.springframework.boot.ApplicationRunner;
@@ -11,32 +12,39 @@ import org.springframework.stereotype.Component;
 import java.io.File;
 
 /**
- * dmaster 系统初始化
+ * 应用启动完成后执行,此时所有的 bean 都已初始化
  *
  * @author reghao
- * @date 2019-10-22 11:05:19
+ * @date 2019-09-26 17:22:16
  */
 @Slf4j
 @Component
-public class SysInitializer implements ApplicationRunner {
-    private SysConfigProperties sysConfigProperties;
+public class AfterAppStart implements ApplicationRunner {
+    private LocalFsConfigRepository configRepository;
 
-    public SysInitializer(SysConfigProperties sysConfigProperties) {
-        this.sysConfigProperties = sysConfigProperties;
+    public AfterAppStart(LocalFsConfigRepository configRepository) {
+        this.configRepository = configRepository;
     }
 
     @Override
     public void run(ApplicationArguments args) throws Exception {
-        initialize();
+        // TODO 应用启动完成后初始化本地目录
+        String env = SpringBootUtil.getEnv();
+        LocalFsConfig config = configRepository.findByEnv(env);
+        if (config != null) {
+            initialize(config);
+            log.info("autodop-dmaster 系统初始化完成...");
+        } else {
+            throw new Exception("应用启动失败...");
+        }
     }
 
-    public void initialize() {
-        SysConfig.localRepo = sysConfigProperties.getLocalRepo();
-        SysConfig.compileDir = sysConfigProperties.getCompileDir();
-        SysConfig.packDir = sysConfigProperties.getPackDir();
-
-        checkAndSet();
-        log.info("autodop 系统初始化完成...");
+    public void initialize(LocalFsConfig config) {
+        // TODO 放入缓存
+        SysConfig.localRepo = config.getLocalRepo();
+        SysConfig.compileDir = config.getCompileDir();
+        SysConfig.packDir = config.getPackDir();
+        checkAndSetLocalDir();
     }
 
     /**
@@ -44,7 +52,7 @@ public class SysInitializer implements ApplicationRunner {
      *
      * @date 2019-11-17 上午11:38
      */
-    private void checkAndSet() {
+    private void checkAndSetLocalDir() {
         File localRepo = new File(SysConfig.localRepo);
         if (!localRepo.exists() && !FileUtil.mkdir(localRepo)) {
             log.error("{} 不存在且创建失败...", localRepo.getAbsolutePath());

+ 3 - 3
dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/BeforeShutdown.java → dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/BeforeAppShutdown.java

@@ -11,18 +11,18 @@ import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 /**
- * 优雅关闭 Spring Boot 应用
+ * 应用进程结束前执行,优雅关闭
  * TODO 考虑应用停止的多种情况
  *
  * @author reghao
  * @date 2019-09-06 13:31:16
  */
 @Slf4j
-public class BeforeShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
+public class BeforeAppShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
     private volatile Connector connector;
     private long timeout;
 
-    public BeforeShutdown(long timeout) {
+    public BeforeAppShutdown(long timeout) {
         this.timeout = timeout;
     }
 

+ 24 - 0
dmaster/src/main/java/cn/reghao/autodop/dmaster/common/utils/UserContext.java

@@ -0,0 +1,24 @@
+package cn.reghao.autodop.dmaster.common.utils;
+
+import cn.reghao.autodop.dmaster.auth.entity.UserAuth;
+
+/**
+ * @author reghao
+ * @date 2020-06-23 19:20:56
+ */
+public class UserContext implements AutoCloseable {
+    static final ThreadLocal<UserAuth> CURRENT = new ThreadLocal<>();
+
+    public UserContext(UserAuth auth) {
+        CURRENT.set(auth);
+    }
+
+    public static UserAuth currentUser() {
+        return CURRENT.get();
+    }
+
+    @Override
+    public void close() {
+        CURRENT.remove();
+    }
+}

+ 3 - 7
dmaster/src/main/resources/application-dev.yml

@@ -1,9 +1,5 @@
 spring:
   datasource:
-    url: jdbc:mysql://localhost:3306/reghao_autodop_rdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
-    username: reghao
-    password: 12345678
-sysconfig:
-  localRepo: /home/reghao/tmp/autodop/opt/data/local-repo
-  compileDir: /home/reghao/tmp/autodop/opt/data/compile-dir
-  packDir: /home/reghao/tmp/autodop/opt/data/pack-dir
+    url: jdbc:mysql://192.168.0.220:3306/autodop_tdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
+    username: azy_test
+    password: Test@123456

+ 1 - 5
dmaster/src/main/resources/application-test.yml

@@ -2,8 +2,4 @@ spring:
   datasource:
     url: jdbc:mysql://192.168.0.220:3306/autodop_tdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
     username: azy_test
-    password: Test@123456
-sysconfig:
-  localRepo: /opt/data/local-repo
-  compileDir: /opt/data/compile-dir
-  packDir: /opt/data/pack-d
+    password: Test@123456

+ 2 - 2
dmaster/src/test/java/cn/reghao/autodop/common/notification/DingNotifyTest.java

@@ -6,11 +6,11 @@ import static org.junit.jupiter.api.Assertions.*;
 
 class DingNotifyTest {
     @Test
-    void main() {
+    void main() throws Exception {
         String webhook = "https://oapi.dingtalk.com/robot/send?access_token=ba9cf0d846cff8c471168e0d2f91ec0c44645a086cf5e4e421697c9b0c606bd2";
         DingNotify dingNotify = new DingNotify();
 
         String content = "maven 打包测试";
         dingNotify.send(webhook, content);
     }
-}
+}