Преглед на файлове

feat:1.完善AppInfo的相关接口以及数据接口;2.加入App的开发者相关信息;3.加入关于Bug上报的接口

shanshan преди 2 години
родител
ревизия
33cb79e773
променени са 25 файла, в които са добавени 584 реда и са изтрити 111 реда
  1. 20 1
      pom.xml
  2. 7 7
      src/main/java/cn/seecoder/fdroidrepository/Controller/AppController.java
  3. 25 0
      src/main/java/cn/seecoder/fdroidrepository/Controller/BugController.java
  4. 12 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/Enum/AppCategoryEnum.java
  5. 18 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/Enum/ResultCode.java
  6. 0 28
      src/main/java/cn/seecoder/fdroidrepository/DataObject/MetaData.java
  7. 17 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/AppContributeRelationPO.java
  8. 21 7
      src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/AppInfoPO.java
  9. 22 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/BugPO.java
  10. 13 11
      src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/BuildTaskPO.java
  11. 22 7
      src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/AppInfoVO.java
  12. 22 0
      src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/BugVO.java
  13. 3 1
      src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/BuildTaskCreateVO.java
  14. 13 10
      src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/BuildTaskVO.java
  15. 26 0
      src/main/java/cn/seecoder/fdroidrepository/Mapper/AppContributeRelationMapper.java
  16. 9 0
      src/main/java/cn/seecoder/fdroidrepository/Mapper/AppInfoMapper.java
  17. 18 0
      src/main/java/cn/seecoder/fdroidrepository/Mapper/BugMapper.java
  18. 8 4
      src/main/java/cn/seecoder/fdroidrepository/Service/AppService.java
  19. 11 0
      src/main/java/cn/seecoder/fdroidrepository/Service/BugService.java
  20. 67 25
      src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/AppServiceImpl.java
  21. 44 0
      src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/BugServiceImpl.java
  22. 48 0
      src/main/java/cn/seecoder/fdroidrepository/security/AuthTools.java
  23. 45 1
      src/main/java/cn/seecoder/fdroidrepository/security/JwtAuthenticationTokenFilter.java
  24. 53 0
      src/main/java/cn/seecoder/fdroidrepository/security/WebSecurityConfiguration.java
  25. 40 9
      src/main/resources/sql/table_init.sql

+ 20 - 1
pom.xml

@@ -82,7 +82,26 @@
             <artifactId>spring-security-test</artifactId>
             <scope>test</scope>
         </dependency>
-
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.0</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-api</artifactId>
+            <version>0.11.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-impl</artifactId>
+            <version>0.11.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-jackson</artifactId>
+            <version>0.11.2</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 7 - 7
src/main/java/cn/seecoder/fdroidrepository/Controller/AppController.java

@@ -26,17 +26,17 @@ public class AppController {
 //        } catch (Exception exception) {
 //            return Response.buildFailure(500, exception.getMessage());
 //        }
-        return Response.buildSuccess(appService.createAppInfo(appInfoVO));
+        return appService.createAppInfo(appInfoVO);
+    }
+
+    @PostMapping("/updateApp")
+    private Response updateApp(@RequestBody AppInfoVO appInfoVO) {
+        return null;
     }
 
     @PostMapping("/buildApp")
     private Response buildApp(@RequestBody BuildTaskCreateVO buildTaskCreateVO) {
-        int result = appService.createBuildTask(buildTaskCreateVO.getAppId(), buildTaskCreateVO.getCreateUserId(),
-                buildTaskCreateVO.getBranch(), buildTaskCreateVO.getBuildTypeEnum());
-        if (result == -1) {
-            return Response.buildFailure(400, "对应的AppId不存在");
-        }
-        return Response.buildSuccess(result);
+        return appService.createBuildTask(buildTaskCreateVO);
     }
 
     @GetMapping("/checkStatus")

+ 25 - 0
src/main/java/cn/seecoder/fdroidrepository/Controller/BugController.java

@@ -0,0 +1,25 @@
+package cn.seecoder.fdroidrepository.Controller;
+
+import cn.seecoder.fdroidrepository.DataObject.VO.BugVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import cn.seecoder.fdroidrepository.Service.BugService;
+import lombok.RequiredArgsConstructor;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/bug")
+@RequiredArgsConstructor
+public class BugController {
+    private final BugService bugService;
+
+    @PostMapping("/create")
+    public Response createBug(@RequestBody BugVO bugVO) {
+        return bugService.createBug(bugVO);
+    }
+
+    @GetMapping("/listBugs")
+    public Response listBugs(@Param("appId") Integer appId) {
+        return bugService.selectByApp(appId);
+    }
+}

+ 12 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/Enum/AppCategoryEnum.java

@@ -0,0 +1,12 @@
+package cn.seecoder.fdroidrepository.DataObject.Enum;
+
+public enum AppCategoryEnum {
+    MEDIA("Media"),
+    GAME("Game"),
+    EFFICIENCY("Efficiency");
+    private final String value;
+
+    AppCategoryEnum(String value) {
+        this.value = value;
+    }
+}

+ 18 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/Enum/ResultCode.java

@@ -0,0 +1,18 @@
+package cn.seecoder.fdroidrepository.DataObject.Enum;
+
+import lombok.Getter;
+
+@Getter
+public enum ResultCode {
+    ILLEGAL_ARGUMENT(10001, "方法的参数错误"),
+    // App 相关的错误代码
+    APPINFO_NON_EXIST(20001, "对应的AppInfo不存在"),
+    GRADLE_REWRITE_FAIL(20002, "Gradle文件重写错误"),
+    BUILD_TASK_NON_EXIST(20003, "对应的BuildTask不存在");
+    private Integer code;
+    private String message;
+    ResultCode(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+}

+ 0 - 28
src/main/java/cn/seecoder/fdroidrepository/DataObject/MetaData.java

@@ -1,28 +0,0 @@
-package cn.seecoder.fdroidrepository.DataObject;
-
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class MetaData {
-    Integer id;
-
-    List<String> categories;
-    String license;
-    String authorName;
-    String authorEmail;
-    String website;
-    String sourceCode;
-    String issueTracker;
-    String changeLog;
-    String donate;
-    String bitcoin;
-    String litecoin;
-
-    String name;
-    String autoName;
-
-    String repoType;
-    String repo;
-}

+ 17 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/AppContributeRelationPO.java

@@ -0,0 +1,17 @@
+package cn.seecoder.fdroidrepository.DataObject.PO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 保存 某一个 App 的开发者信息
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class AppContributeRelationPO {
+    private Integer id;
+    private Integer appId;
+    private Integer userId;
+}

+ 21 - 7
src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/AppInfoPO.java

@@ -1,21 +1,35 @@
 package cn.seecoder.fdroidrepository.DataObject.PO;
 
+import cn.seecoder.fdroidrepository.DataObject.Enum.AppCategoryEnum;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.util.Date;
+import java.util.List;
+
 @Data
 @Builder
 @AllArgsConstructor
 @NoArgsConstructor
 public class AppInfoPO {
-    Integer id;
-    String appName;
-    Integer authorId;
-    String repoUrl;
-    String buildBranch;
-    String dailyBuildBranch;
-    Boolean enableDailyBuild; // 是否开启daily build功能
+    private Integer id;
+    private String appName;
+    private String icon; // App图标,应该为一个OSS链接地址
+    private String description; // App的功能介绍
+
+    private String repoUrl;
+    private Integer authorId;
+    private String authorName;
+
+    private Double rate; // App的评分
+    private Integer rateCount; // 参与评分的人数
+
+    private AppCategoryEnum category; // App所属的类别
+    private Date createTime;
 
+    private String buildBranch;
+    private String dailyBuildBranch;
+    private Boolean enableDailyBuild; // 是否开启daily build功能
 }

+ 22 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/BugPO.java

@@ -0,0 +1,22 @@
+package cn.seecoder.fdroidrepository.DataObject.PO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class BugPO {
+    private Integer id;
+    private Integer appId;
+    private String version;
+    private Integer userId;
+    private String userName;
+    private Date createTime;
+    private Date updateTime;
+    private String description; // 对该Bug的描述,是一个HTML文本,前端可以直接进行展示
+    private Boolean fixed;
+}

+ 13 - 11
src/main/java/cn/seecoder/fdroidrepository/DataObject/PO/BuildTaskPO.java

@@ -18,15 +18,17 @@ import java.util.Date;
 @AllArgsConstructor
 @Builder
 public class BuildTaskPO {
-    Integer id;
-    Integer appId;
-    Integer createUserId;
-    Date createTime;
-    Date updateTime;
-    BuildTaskStatusEnum status;
-    BuildTypeEnum buildType;
-    String repoUrl;
-    String branch;
-    String message;
-    String result;
+    private Integer id;
+    private Integer appId;
+    private Integer createUserId;
+    private String createUserName; // 用于前端展示方便
+    private String description;
+    private String version; // 对应的版本号
+
+    private Date createTime;
+    private Date updateTime;
+
+    private BuildTaskStatusEnum status;
+    private BuildTypeEnum buildType;
+    private String message;
 }

+ 22 - 7
src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/AppInfoVO.java

@@ -1,16 +1,31 @@
 package cn.seecoder.fdroidrepository.DataObject.VO;
 
+import cn.seecoder.fdroidrepository.DataObject.Enum.AppCategoryEnum;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
 
 @Data
 public class AppInfoVO implements Serializable {
-    Integer id;
-    String appName;
-    Integer authorId;
-    String repoUrl;
-    String buildBranch;
-    String dailyBuildBranch;
-    Boolean enableDailyBuild; // 是否开启daily build功能
+    private Integer id;
+    private String appName;
+    private String icon; // App图标,应该为一个OSS链接地址
+    private String description; // App的功能介绍
+
+    private String repoUrl;
+    private Integer authorId;
+    private String authorName;
+    private List<Integer> contributorIds; // App开发者的ID,开发者会有独特的界面
+
+    private Double rate; // App的评分
+    private Integer rateCount; // 参与评分的人数
+
+    private AppCategoryEnum category; // App所属的类别
+    private Date createTime;
+
+    private String buildBranch;
+    private String dailyBuildBranch;
+    private Boolean enableDailyBuild;
 }

+ 22 - 0
src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/BugVO.java

@@ -0,0 +1,22 @@
+package cn.seecoder.fdroidrepository.DataObject.VO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class BugVO {
+    private Integer id;
+    private Integer appId;
+    private String version;
+    private Integer userId;
+    private String userName;
+    private Date createTime;
+    private Date updateTime;
+    private String description; // 对该Bug的描述,是一个HTML文本,前端可以直接进行展示
+    private Boolean fixed;
+}

+ 3 - 1
src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/BuildTaskCreateVO.java

@@ -11,6 +11,8 @@ import lombok.NoArgsConstructor;
 public class BuildTaskCreateVO {
     private Integer appId;
     private Integer createUserId;
-    private String branch;
+    private String createUserName;
     private BuildTypeEnum buildTypeEnum;
+    private String description;
+    private String version;
 }

+ 13 - 10
src/main/java/cn/seecoder/fdroidrepository/DataObject/VO/BuildTaskVO.java

@@ -9,14 +9,17 @@ import java.util.Date;
 
 @Data
 public class BuildTaskVO implements Serializable {
-    Integer id;
-    Integer appId;
-    Integer createUserId;
-    Date createTime;
-    Date updateTime;
-    BuildTaskStatusEnum status;
-    BuildTypeEnum buildType;
-    String repoUrl;
-    String branch;
-    String message;
+    private Integer id;
+    private Integer appId;
+    private Integer createUserId;
+    private String createUserName; // 用于前端展示方便
+    private String description;
+    private String version;
+
+    private Date createTime;
+    private Date updateTime;
+
+    private BuildTaskStatusEnum status;
+    private BuildTypeEnum buildType;
+    private String message;
 }

+ 26 - 0
src/main/java/cn/seecoder/fdroidrepository/Mapper/AppContributeRelationMapper.java

@@ -0,0 +1,26 @@
+package cn.seecoder.fdroidrepository.Mapper;
+
+import cn.seecoder.fdroidrepository.DataObject.PO.AppContributeRelationPO;
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface AppContributeRelationMapper {
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    Integer insert(@Param("obj") AppContributeRelationPO relation);
+
+    @Insert("insert into app_contribute_relation set app_id = #{appId}, user_id = #{userId}")
+    Integer insert(Integer appId, Integer userId);
+
+    @Select("select app_id from app_contribute_relation where user_id = #{id}")
+    List<Integer> selectAppIdsByUserId(Integer id);
+
+    @Select("select user_id from app_contribute_relation where app_id = #{id}")
+    List<Integer> selectContributorIdsByAppId(Integer id);
+
+    @Delete("delete from app_contribute_relation where app_id = #{appId} and user_id = #{userId}")
+    Integer deleteRelation(Integer appId, Integer userId);
+
+}

+ 9 - 0
src/main/java/cn/seecoder/fdroidrepository/Mapper/AppInfoMapper.java

@@ -4,13 +4,22 @@ import cn.seecoder.fdroidrepository.DataObject.PO.AppInfoPO;
 import org.apache.ibatis.annotations.InsertProvider;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.UpdateProvider;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 @Repository
 public interface AppInfoMapper {
     @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
     Integer insertAppInfo(@Param("obj") AppInfoPO appInfoPO, String... ignoredCols);
 
+    @UpdateProvider(type = GeneralInsertUpdateSqlProvider.class, method = "updateById")
+    Integer updateAppInfo(@Param("obj") AppInfoPO appInfoPO);
+
     @Select("select * from app_info where id = #{id}")
     AppInfoPO selectById(Integer id);
+
+    @Select("select * from app_info where enable_daily_build = true")
+    List<AppInfoPO> selectDailyBuildApp();
 }

+ 18 - 0
src/main/java/cn/seecoder/fdroidrepository/Mapper/BugMapper.java

@@ -0,0 +1,18 @@
+package cn.seecoder.fdroidrepository.Mapper;
+
+import cn.seecoder.fdroidrepository.DataObject.PO.BugPO;
+import org.apache.ibatis.annotations.InsertProvider;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+public interface BugMapper {
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    Integer insert(@Param("obj") BugPO bugPO);
+
+    @Select("select * from bug where app_id = #{appId}")
+    List<BugPO> selectByAppId(Integer appId);
+}

+ 8 - 4
src/main/java/cn/seecoder/fdroidrepository/Service/AppService.java

@@ -2,14 +2,18 @@ package cn.seecoder.fdroidrepository.Service;
 
 
 import cn.seecoder.fdroidrepository.DataObject.Enum.BuildTypeEnum;
+import cn.seecoder.fdroidrepository.DataObject.Enum.ResultCode;
 import cn.seecoder.fdroidrepository.DataObject.PO.BuildTaskPO;
 import cn.seecoder.fdroidrepository.DataObject.VO.AppInfoVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.BuildTaskCreateVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
 
 public interface AppService {
-    Integer createAppInfo(AppInfoVO appInfoVO);
+    Response createAppInfo(AppInfoVO appInfoVO);
+    Response updateAppInfo(AppInfoVO appInfoVO);
 
-    Boolean rewriteGradleFile(Integer pipelineId, String fileName, String content);
-    BuildTaskPO checkTaskStatus(Integer taskId);
+    Response rewriteGradleFile(Integer pipelineId, String fileName, String content);
+    Response checkTaskStatus(Integer taskId);
 
-    Integer createBuildTask(Integer appId, Integer userId, String branch, BuildTypeEnum typeEnum);
+    Response createBuildTask(BuildTaskCreateVO createVO);
 }

+ 11 - 0
src/main/java/cn/seecoder/fdroidrepository/Service/BugService.java

@@ -0,0 +1,11 @@
+package cn.seecoder.fdroidrepository.Service;
+
+import cn.seecoder.fdroidrepository.DataObject.VO.BugVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+
+public interface BugService {
+
+    Response createBug(BugVO bugVO);
+
+    Response selectByApp(Integer appId);
+}

+ 67 - 25
src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/AppServiceImpl.java

@@ -3,9 +3,14 @@ package cn.seecoder.fdroidrepository.Service.ServiceImpl;
 import cn.seecoder.fdroidrepository.DataObject.ApplicationProperties;
 import cn.seecoder.fdroidrepository.DataObject.Enum.BuildTaskStatusEnum;
 import cn.seecoder.fdroidrepository.DataObject.Enum.BuildTypeEnum;
+import cn.seecoder.fdroidrepository.DataObject.Enum.ResultCode;
+import cn.seecoder.fdroidrepository.DataObject.PO.AppContributeRelationPO;
 import cn.seecoder.fdroidrepository.DataObject.PO.AppInfoPO;
 import cn.seecoder.fdroidrepository.DataObject.PO.BuildTaskPO;
 import cn.seecoder.fdroidrepository.DataObject.VO.AppInfoVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.BuildTaskCreateVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import cn.seecoder.fdroidrepository.Mapper.AppContributeRelationMapper;
 import cn.seecoder.fdroidrepository.Mapper.AppInfoMapper;
 import cn.seecoder.fdroidrepository.Mapper.BuildTaskMapper;
 import cn.seecoder.fdroidrepository.Pipeline.*;
@@ -21,31 +26,65 @@ import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
 import java.util.Date;
+import java.util.List;
 import java.util.concurrent.*;
 
 @Service
 public class AppServiceImpl implements AppService {
     private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(4, 8, 1000, TimeUnit.SECONDS, new LinkedBlockingQueue<>(512), new ThreadPoolExecutor.DiscardPolicy());
     private static final Logger logger = LoggerFactory.getLogger(AppServiceImpl.class);
+    private static final Integer SYSTEM_DEFAULT_ID = -1;
     private final BuildTaskMapper buildTaskMapper;
     private final AppInfoMapper appInfoMapper;
+    private final AppContributeRelationMapper relationMapper;
 
     @Autowired
-    public AppServiceImpl(BuildTaskMapper buildTaskMapper, AppInfoMapper appInfoMapper) {
+    public AppServiceImpl(BuildTaskMapper buildTaskMapper, AppInfoMapper appInfoMapper, AppContributeRelationMapper relationMapper) {
         this.buildTaskMapper = buildTaskMapper;
         this.appInfoMapper = appInfoMapper;
+        this.relationMapper = relationMapper;
     }
 
     @Override
-    public Integer createAppInfo(AppInfoVO appInfoVO) {
+    public Response createAppInfo(AppInfoVO appInfoVO) {
         AppInfoPO appInfoPO = new AppInfoPO();
         BeanUtils.copyProperties(appInfoVO, appInfoPO);
+        appInfoPO.setCreateTime(new Date(System.currentTimeMillis()));
         Integer appId = appInfoMapper.insertAppInfo(appInfoPO);
-        return appId;
+        // 创建 AppContributeRelation 并进行保存
+        for (Integer userId : appInfoVO.getContributorIds()) {
+            relationMapper.insert(appId, userId);
+        }
+        return Response.buildSuccess(appId);
+    }
+
+    @Override
+    public Response updateAppInfo(AppInfoVO appInfoVO) {
+        if (appInfoVO == null || appInfoVO.getId() == null) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        appInfoVO.setCreateTime(null);
+        AppInfoPO appInfoPO = new AppInfoPO();
+        BeanUtils.copyProperties(appInfoVO, appInfoPO);
+        Integer result = appInfoMapper.updateAppInfo(appInfoPO);
+        // 更改AppContributeRelation
+        List<Integer> oldContributorIds = relationMapper.selectContributorIdsByAppId(appInfoVO.getId());
+        List<Integer> newContributorIds = appInfoVO.getContributorIds();
+        for (Integer userId : oldContributorIds) {
+            if (!newContributorIds.contains(userId)) {
+                relationMapper.deleteRelation(appInfoVO.getId(), userId);
+            }
+        }
+        for (Integer userId : newContributorIds) {
+            if (!oldContributorIds.contains(userId)) {
+                relationMapper.insert(appInfoVO.getId(), userId);
+            }
+        }
+        return Response.buildSuccess();
     }
 
     @Override
-    public Boolean rewriteGradleFile(Integer taskId, String fileName, String content) {
+    public Response rewriteGradleFile(Integer taskId, String fileName, String content) {
         try {
             File file = new File(fileName);
             if (!file.exists()) {
@@ -68,23 +107,24 @@ public class AppServiceImpl implements AppService {
                 WaitLock waitLock = new WaitLock();
                 CommonValueTable.LockTable.put(taskId, waitLock);
             }
-            return true;
+            return Response.buildSuccess(true);
         } catch (Exception exception) {
             logger.error("重写Gradle文件失败,错误信息: {}", exception.getMessage());
-            return false;
+            return Response.buildFailure(ResultCode.GRADLE_REWRITE_FAIL.getCode(), ResultCode.GRADLE_REWRITE_FAIL.getMessage());
         }
     }
 
     @Override
-    public BuildTaskPO checkTaskStatus(Integer taskId) {
+    public Response checkTaskStatus(Integer taskId) {
         ExecuteResult result = CommonValueTable.ResultTable.get(taskId);
         BuildTaskPO buildTaskPO = this.buildTaskMapper.selectById(taskId);
-        if (result != null) {
+        if (result == null) {
+            return Response.buildFailure(ResultCode.BUILD_TASK_NON_EXIST.getCode(), ResultCode.BUILD_TASK_NON_EXIST.getMessage());
+        } else {
             // 根据对应的执行结果内容进行更新
             buildTaskPO.setStatus(result.getStatus());
             buildTaskPO.setUpdateTime(result.getUpdateTime());
             buildTaskPO.setMessage(result.getMessage());
-            buildTaskPO.setResult(result.getResult());
             buildTaskMapper.updateById(buildTaskPO);
 
             // 流水线已经执行完成,删除其在Map中的内容,防止空间堆积
@@ -92,31 +132,26 @@ public class AppServiceImpl implements AppService {
                 CommonValueTable.ResultTable.remove(taskId);
             }
         }
-        return buildTaskPO;
+        return Response.buildSuccess(buildTaskPO);
     }
 
     @Override
-    public Integer createBuildTask(Integer appId, Integer userId, String branch, BuildTypeEnum typeEnum) {
-        AppInfoPO appInfoPO = appInfoMapper.selectById(appId);
+    public Response createBuildTask(BuildTaskCreateVO createVO) {
+        AppInfoPO appInfoPO = appInfoMapper.selectById(createVO.getAppId());
         if (appInfoPO == null) {
-            // AppInfo不存在
-            logger.error("对应的AppInfo不存在");
-            return -1;
+            return Response.buildFailure(ResultCode.APPINFO_NON_EXIST.getCode(), ResultCode.APPINFO_NON_EXIST.getMessage());
         }
-        BuildTaskPO buildTaskPO = BuildTaskPO.builder()
-                .appId(appId)
-                .createUserId(userId)
-                .createTime(new Date(System.currentTimeMillis()))
-                .buildType(typeEnum)
-                .status(BuildTaskStatusEnum.NEW)
-                .build();
+        BuildTaskPO buildTaskPO = new BuildTaskPO();
+        BeanUtils.copyProperties(createVO, buildTaskPO);
+        buildTaskPO.setCreateTime(new Date(System.currentTimeMillis()));
+        buildTaskPO.setStatus(BuildTaskStatusEnum.NEW);
         Integer taskId = buildTaskMapper.insert(buildTaskPO);
         buildTaskPO.setId(taskId);
         ApplicationProperties app = ApplicationProperties.builder()
-                .appId(appId)
+                .appId(createVO.getAppId())
                 .appName(appInfoPO.getAppName())
                 .repoUrl(appInfoPO.getRepoUrl())
-                .branch(branch)
+                .branch(appInfoPO.getBuildBranch())
                 .build();
         THREAD_POOL_EXECUTOR.execute(new Runnable() {
             @Override
@@ -130,6 +165,13 @@ public class AppServiceImpl implements AppService {
                 }
             }
         });
-        return taskId;
+        return Response.buildSuccess(taskId);
+    }
+
+    private AppInfoVO buildAppInfoVO(AppInfoPO appInfoPO) {
+        AppInfoVO appInfoVO = new AppInfoVO();
+        BeanUtils.copyProperties(appInfoPO, appInfoVO);
+        appInfoVO.setContributorIds(relationMapper.selectContributorIdsByAppId(appInfoPO.getId()));
+        return appInfoVO;
     }
 }

+ 44 - 0
src/main/java/cn/seecoder/fdroidrepository/Service/ServiceImpl/BugServiceImpl.java

@@ -0,0 +1,44 @@
+package cn.seecoder.fdroidrepository.Service.ServiceImpl;
+
+import cn.seecoder.fdroidrepository.DataObject.Enum.ResultCode;
+import cn.seecoder.fdroidrepository.DataObject.PO.BugPO;
+import cn.seecoder.fdroidrepository.DataObject.VO.BugVO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import cn.seecoder.fdroidrepository.Mapper.BugMapper;
+import cn.seecoder.fdroidrepository.Service.BugService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class BugServiceImpl implements BugService {
+    private final BugMapper bugMapper;
+
+    @Override
+    public Response createBug(BugVO bugVO) {
+        BugPO bugPO = new BugPO();
+        BeanUtils.copyProperties(bugVO, bugPO);
+        Integer bugId = bugMapper.insert(bugPO);
+        return Response.buildSuccess(bugId);
+    }
+
+    /**
+     * 获取某一个App的全部Bug,并根据Version将其进行分组
+     * @param appId
+     * @return Map<String, List<BugPO>>
+     */
+    @Override
+    public Response selectByApp(Integer appId) {
+        if (appId == null) {
+            return Response.buildFailure(ResultCode.ILLEGAL_ARGUMENT.getCode(), ResultCode.ILLEGAL_ARGUMENT.getMessage());
+        }
+        List<BugPO> bugList = bugMapper.selectByAppId(appId);
+        Map<String, List<BugPO>> bugMap = bugList.stream().collect(Collectors.groupingBy(BugPO::getVersion));
+        return Response.buildSuccess(bugMap);
+    }
+}

+ 48 - 0
src/main/java/cn/seecoder/fdroidrepository/security/AuthTools.java

@@ -0,0 +1,48 @@
+package cn.seecoder.fdroidrepository.security;
+
+import cn.seecoder.fdroidrepository.DataObject.PO.AppInfoPO;
+import cn.seecoder.fdroidrepository.DataObject.PO.UserPO;
+import cn.seecoder.fdroidrepository.Mapper.AppContributeRelationMapper;
+import cn.seecoder.fdroidrepository.Mapper.AppInfoMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * AuthTools 用与WebSecurityConfiguration中
+ * 提供检测用户是否有权限操作某一个项目的相关接口
+ * 以Param结尾的方法表示需要的参数在httpRequest中,适用于@Param
+ * 其余方法适用于@PathVariable
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class AuthTools {
+    private final AppInfoMapper appInfoMapper;
+    private final AppContributeRelationMapper relationMapper;
+
+    private UserPO getCurrentUser() {
+        return (UserPO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+    }
+
+
+    public boolean checkAppContributorParam(HttpServletRequest request) {
+        String appIdStr = request.getParameter("appId");
+        if (!StringUtils.isNumeric(appIdStr)) {
+            return false;
+        }
+        Integer appId = Integer.parseInt(appIdStr);
+        return checkAppContributor(appId);
+    }
+
+    public boolean checkAppContributor(Integer appId) {
+        UserPO userPO = getCurrentUser();
+        List<Integer> contributorIds = relationMapper.selectContributorIdsByAppId(appId);
+        return contributorIds.contains(userPO.getId());
+    }
+}

+ 45 - 1
src/main/java/cn/seecoder/fdroidrepository/security/JwtAuthenticationTokenFilter.java

@@ -1,6 +1,17 @@
 package cn.seecoder.fdroidrepository.security;
 
+import cn.seecoder.fdroidrepository.DataObject.Enum.UserIdentity;
+import cn.seecoder.fdroidrepository.DataObject.PO.UserPO;
+import cn.seecoder.fdroidrepository.DataObject.VO.Response;
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.exceptions.JWTDecodeException;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import io.jsonwebtoken.Claims;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
 import org.springframework.stereotype.Component;
 import org.springframework.web.filter.OncePerRequestFilter;
 
@@ -9,6 +20,8 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
 
 @Component
 public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@@ -16,7 +29,38 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
         String authHeader = request.getHeader("Authorization");
         if (StringUtils.isNotEmpty(authHeader)) {
-
+            Long exp;
+            String auth;
+            Map<String, Object> userInfo;
+            try {
+                DecodedJWT decodedJWT = JWT.decode(authHeader);
+                exp = decodedJWT.getClaim("exp").asLong();
+                auth = decodedJWT.getClaim("auth").asString();
+                userInfo = decodedJWT.getClaim("user_info").asMap();
+                UserDetails userPO = UserPO.builder()
+                        .id((Integer) userInfo.get("id"))
+                        .email((String) userInfo.get("email"))
+                        .phone((String) userInfo.get("phone"))
+                        .role(UserIdentity.valueOf((String) userInfo.get("role")))
+                        .build();
+                if (exp >= System.currentTimeMillis() / 1000) {
+                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userPO, null);
+                    authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+                }
+                else {
+                    response.setCharacterEncoding("UTF-8");
+                    response.setCharacterEncoding("UTF-8");
+                    response.setStatus(10010);
+                    response.setContentType("application/json; charset=utf-8");
+                    PrintWriter out = response.getWriter();
+                    out.append(Response.buildFailure(10110,"Jwt token 过期").toString());
+                }
+            } catch (Exception exception) {
+                exception.printStackTrace();
+                response.sendError(500);
+            }
         }
+        filterChain.doFilter(request, response);
     }
 }

+ 53 - 0
src/main/java/cn/seecoder/fdroidrepository/security/WebSecurityConfiguration.java

@@ -0,0 +1,53 @@
+package cn.seecoder.fdroidrepository.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+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.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsUtils;
+
+import static org.springframework.http.HttpMethod.*;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfiguration {
+    private final JwtAuthenticationTokenFilter filter;
+    private final AuthTools authTools;
+
+    @Autowired
+    public WebSecurityConfiguration(JwtAuthenticationTokenFilter filter, AuthTools authTools) {
+        this.filter = filter;
+        this.authTools = authTools;
+    }
+
+    @Bean
+    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+        http
+                .cors()
+                .and()
+                .csrf().disable()
+                .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+                .and()
+                .addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class)
+                .authorizeRequests()
+                // AppController
+                .antMatchers(POST, "/app/createApp").authenticated()
+                .antMatchers(POST, "/app/buildApp").authenticated()
+                .antMatchers(GET, "/app/checkStatus").authenticated()
+                // BugController
+                .antMatchers(POST, "/bug/create").authenticated()
+                .antMatchers(GET, "/app/listBugs").access("@authTools.checkAppContributorParam(request)")
+                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
+                // 拒绝其他请求
+                .anyRequest().denyAll();
+        return http.build();
+    }
+}

+ 40 - 9
src/main/resources/sql/table_init.sql

@@ -1,25 +1,56 @@
+drop table if exists fdroid.app_info;
 create table if not exists fdroid.app_info
 (
     id int auto_increment primary key,
+    app_name varchar(30) not null,
+    icon text,
+    description text,
+    repo_url text,
     author_id int not null,
-    app_name varchar(64) not null,
-    repo_url varchar(128) not null,
-    build_branch varchar(64) null,
-    daily_build_branch varchar(64) null,
-    enable_daily_build boolean default false not null
+    author_name varchar(30) not null,
+    rate double not null default 0,
+    rate_count double not null default 0,
+    category varchar(20),
+    build_branch varchar(20) not null ,
+    daily_build_branch varchar(20),
+    enable_daily_build boolean not null default false,
+    create_time timestamp default current_timestamp not null
 ) charset = utf8;
 
+drop table if exists fdroid.build_task;
 create table if not exists fdroid.build_task
 (
     id int auto_increment primary key,
     app_id int not null,
     create_user_id int not null,
+    create_user_name varchar(30) not null,
+    description text,
+    version varchar(20) not null,
     create_time timestamp default current_timestamp not null,
     update_time timestamp,
     status varchar(20) not null,
     build_type varchar(20) not null,
-    repo_url varchar(128) not null,
-    branch varchar(64) not null,
-    message text,
-    result text
+    message text
+) charset = utf8;
+
+drop table if exists fdroid.app_contribute_relation;
+create table if not exists fdroid.app_contribute_relation
+(
+    id int auto_increment primary key,
+    app_id int not null,
+    user_id int not null
+) charset = utf8;
+
+drop table if exists fdroid.bug;
+create table if not exists fdroid.bug
+(
+    id int auto_increment primary key,
+    app_id int not null ,
+    version varchar(20) not null ,
+    user_id int not null ,
+    user_name int not null ,
+    create_time timestamp default current_timestamp not null ,
+    update_time timestamp,
+    fixed boolean default false not null ,
+    description text not null
 ) charset = utf8;