فهرست منبع

zhurui 更新题库后端代码

Leonezhurui 5 سال پیش
والد
کامیت
08e60e7bd0
37فایلهای تغییر یافته به همراه1374 افزوده شده و 46 حذف شده
  1. 17 3
      seecoder-bok-client/src/main/java/cn/seecoder/bok/client/SeecoderBokClient.java
  2. 7 0
      seecoder-bok-common/pom.xml
  3. 26 0
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/QuestionState.java
  4. 14 0
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/UserRole.java
  5. 40 14
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/api/SeecoderBokQuestionApi.java
  6. 7 7
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/KnowledgeNodeVO.java
  7. 6 1
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/QuestionVO.java
  8. 43 0
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/question/AbstractQuestionVO.java
  9. 49 0
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/user/UpdateUserVO.java
  10. 60 0
      seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/user/UserVO.java
  11. 29 0
      seecoder-bok-server/pom.xml
  12. 81 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/aspect/auth/AuthAspect.java
  13. 15 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/aspect/auth/AuthorizationImpl.java
  14. 18 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/aspect/auth/Authorized.java
  15. 32 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/config/CorsConfig.java
  16. 39 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/config/webSecurityConfig.java
  17. 130 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/domain/Knowledge.java
  18. 40 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/domain/Question.java
  19. 113 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/domain/User.java
  20. 24 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/exception/MyServiceException.java
  21. 28 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/mapper/KnowledgeMapper.java
  22. 27 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/mapper/QuestionConvertor.java
  23. 22 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/mapper/UserConvertor.java
  24. 17 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/repository/KnowledgeRepository.java
  25. 14 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/repository/UserRepository.java
  26. 25 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/service/KnowledgeService.java
  27. 22 3
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/service/QuestionService.java
  28. 69 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/service/UserService.java
  29. 68 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/util/JwtUtil.java
  30. 38 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/KnowledgeController.java
  31. 57 13
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/QuestionController.java
  32. 61 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/Response.java
  33. 57 0
      seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/UserController.java
  34. 15 5
      seecoder-bok-server/src/main/resources/application-dev.yml
  35. 3 0
      seecoder-bok-server/src/main/resources/application.yml
  36. 29 0
      seecoder-bok-server/src/test/java/cn/seecoder/seecoderbokserver/jwtTest.java
  37. 32 0
      seecoder-bok-server/src/test/java/cn/seecoder/seecoderbokserver/repository/UserRepositoryTest.java

+ 17 - 3
seecoder-bok-client/src/main/java/cn/seecoder/bok/client/SeecoderBokClient.java

@@ -10,6 +10,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import okhttp3.HttpUrl;
 import okhttp3.Response;
 import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
 
 import javax.validation.constraints.NotBlank;
@@ -63,7 +64,20 @@ public class SeecoderBokClient
         return getQuestionVOS(pageable, urlBuilder);
     }
 
-    @Override
+    /**
+     * TODO 可能有误
+     * @param offset    页号
+     * @param pageSize  页容量
+     * @return
+     */
+//    @Override
+    public Page<QuestionVO> getTargetQuestionList(int offset, int pageSize) {
+        Pageable pageable = PageRequest.of(offset, pageSize);
+        HttpUrl.Builder urlBuilder = req.createUrlBuilder("/api/question1");
+        return getQuestionVOS(pageable, urlBuilder);
+    }
+
+//    @Override
     public QuestionVO createQuestion(@NotNull QuestionVO question) {
         HttpUrl httpUrl = req.createUrlBuilder("/api/question").build();
         Response response = req.post(httpUrl, req.writeRequestBody(question));
@@ -85,14 +99,14 @@ public class SeecoderBokClient
         return req.getResponseBody(response, QuestionVO.class);
     }
 
-    @Override
+//    @Override
     public QuestionVO updateQuestion(@NotNull QuestionVO question) {
         HttpUrl httpUrl = req.createUrlBuilder(formatUrl("/api/question/{0}", encodeValue(question.getId()))).build();
         Response response = req.put(httpUrl, req.writeRequestBody(question));
         return req.getResponseBody(response, QuestionVO.class).orElseThrow(() -> SeecoderBokException.UNWRAP_EXCEPTION);
     }
 
-    @Override
+//    @Override
     public void deleteQuestionById(@NotBlank String questionId) {
         HttpUrl httpUrl = req.createUrlBuilder(formatUrl("/api/question/{0}", questionId)).build();
         req.delete(httpUrl);

+ 7 - 0
seecoder-bok-common/pom.xml

@@ -27,6 +27,13 @@
             <artifactId>mapstruct</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+            <version>1.18.10</version>
+        </dependency>
+
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>

+ 26 - 0
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/QuestionState.java

@@ -0,0 +1,26 @@
+package cn.seecoder.bok.common;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/18 - 3:46 下午
+ * @Package: SEEC-BOK
+ */
+
+public enum QuestionState {
+    APPROVED("APPROVED"),
+    CHECKING("CHECKING"),
+    REFUSED("REFUSED");
+
+    private final String name;
+
+    QuestionState(String name) {
+        this.name = name;
+    }
+
+    @JsonValue
+    public String getName() {
+        return name;
+    }
+}

+ 14 - 0
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/UserRole.java

@@ -0,0 +1,14 @@
+package cn.seecoder.bok.common;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/16 - 10:24 下午
+ * @Package: SEEC-BOK
+ */
+
+public enum UserRole {
+    TEACHER,
+    STUDENT,
+    HR,
+    ADMIN
+}

+ 40 - 14
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/api/SeecoderBokQuestionApi.java

@@ -30,13 +30,39 @@ public interface SeecoderBokQuestionApi {
                                      List<QuestionType> types, List<Integer> weights,
                                      List<String> knowledgeIds, Pageable pageable);
 
+//    /**
+//     * 搜索获得问题列表
+//     *
+//     * @param stem
+//     * @param tags
+//     * @param types
+//     * @param weights
+//     * @param knowledgeIds
+//     * @param offset
+//     * @param pageSize
+//     * @return
+//     */
+//    Page<QuestionVO> getSearchQuestionList(String stem, List<String> tags,
+//                                     List<QuestionType> types, List<Integer> weights,
+//                                     List<String> knowledgeIds, int offset, int pageSize);
+
+
+//    /**
+//     * 根据页号和页容量返回数据
+//     *
+//     * @param offset    页号
+//     * @param pageSize  页容量
+//     * @return 分页后的题目列表
+//     */
+//    Response getTargetQuestionList(int offset, int pageSize);
+
     /**
      * 创建题目
      *
      * @param question 题目信息
      * @return 创建后赋予id的题目信息
      */
-    QuestionVO createQuestion(@NotNull QuestionVO question);
+//    QuestionVO createQuestion(@NotNull QuestionVO question);
 
     /**
      * 创建很多题目
@@ -54,18 +80,18 @@ public interface SeecoderBokQuestionApi {
      */
     Optional<QuestionVO> getQuestionById(@NotBlank String questionId);
 
-    /**
-     * 更新题目信息
-     *
-     * @param question 题目信息
-     * @return 题目信息
-     */
-    QuestionVO updateQuestion(@NotNull QuestionVO question);
+//    /**
+//     * 更新题目信息
+//     *
+//     * @param question 题目信息
+//     * @return 题目信息
+//     */
+//    QuestionVO updateQuestion(@NotNull QuestionVO question);
 
-    /**
-     * 删除题目
-     *
-     * @param questionId 题目id
-     */
-    void deleteQuestionById(@NotBlank String questionId);
+//    /**
+//     * 删除题目
+//     *
+//     * @param questionId 题目id
+//     */
+//    void deleteQuestionById(@NotBlank String questionId);
 }

+ 7 - 7
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/KnowledgeNodeVO.java

@@ -12,7 +12,7 @@ public class KnowledgeNodeVO {
     private String abbreviation;
 
     private String name;
-    private String englishName;
+    private String nameEng;
     private String parentId;
     private String parentName;
 
@@ -40,12 +40,12 @@ public class KnowledgeNodeVO {
         this.name = name;
     }
 
-    public String getEnglishName() {
-        return englishName;
+    public String getNameEng() {
+        return nameEng;
     }
 
-    public void setEnglishName(String englishName) {
-        this.englishName = englishName;
+    public void setNameEng(String nameEng) {
+        this.nameEng = nameEng;
     }
 
     public String getParentId() {
@@ -69,7 +69,7 @@ public class KnowledgeNodeVO {
         knowledgeNodeVO.id = neo.getId();
         knowledgeNodeVO.abbreviation = neo.getAbbreviation();
         knowledgeNodeVO.name = neo.getName();
-        knowledgeNodeVO.englishName = neo.getNameEng();
+        knowledgeNodeVO.nameEng = neo.getNameEng();
         knowledgeNodeVO.parentId = neo.getParentId();
         knowledgeNodeVO.parentName = neo.getParentName();
         return knowledgeNodeVO;
@@ -152,7 +152,7 @@ public class KnowledgeNodeVO {
                 "id='" + id + '\'' +
                 ", abbreviation='" + abbreviation + '\'' +
                 ", name='" + name + '\'' +
-                ", englishName='" + englishName + '\'' +
+                ", nameEng='" + nameEng + '\'' +
                 ", parentId='" + parentId + '\'' +
                 ", parentName='" + parentName + '\'' +
                 '}';

+ 6 - 1
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/QuestionVO.java

@@ -102,14 +102,19 @@ public class QuestionVO extends AbstractQuestionVO {
                 ", millisecondLimit=" + millisecondLimit +
                 ", memoryLimit=" + memoryLimit +
                 ", id='" + id + '\'' +
+                ", state=" + state +
+                ", checkedUserId=" + checkedUserId +
+                ", savedUserId=" + savedUserId +
                 ", type=" + type +
                 ", title='" + title + '\'' +
                 ", stem='" + stem + '\'' +
                 ", analysis='" + analysis + '\'' +
+                ", weight=" + weight +
                 ", keyPoints='" + keyPoints + '\'' +
                 ", tags=" + tags +
                 ", knowledgeId=" + knowledgeId +
+                ", createdTime=" + createdTime +
                 ", lastModifiedTime=" + lastModifiedTime +
-                "} ";
+                '}';
     }
 }

+ 43 - 0
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/question/AbstractQuestionVO.java

@@ -1,5 +1,6 @@
 package cn.seecoder.bok.common.vo.question;
 
+import cn.seecoder.bok.common.QuestionState;
 import cn.seecoder.bok.common.QuestionType;
 import com.fasterxml.jackson.annotation.JsonFormat;
 
@@ -19,6 +20,21 @@ public abstract class AbstractQuestionVO {
      */
     protected QuestionType type;
 
+    /**
+     * 题目状态
+     */
+    protected QuestionState state;
+
+    /**
+     * 审核人
+     */
+    protected Integer checkedUserId;
+
+    /**
+     * 申请人
+     */
+    protected Integer savedUserId;
+
     /**
      * 简单的标题,旧版本未出现,是可选字段
      */
@@ -152,10 +168,37 @@ public abstract class AbstractQuestionVO {
         this.lastModifiedTime = lastModifiedTime;
     }
 
+    public QuestionState getState() {
+        return state;
+    }
+
+    public void setState(QuestionState state) {
+        this.state = state;
+    }
+
+    public Integer getCheckedUserId() {
+        return checkedUserId;
+    }
+
+    public void setCheckedUserId(Integer checkedUserId) {
+        this.checkedUserId = checkedUserId;
+    }
+
+    public Integer getSavedUserId() {
+        return savedUserId;
+    }
+
+    public void setSavedUserId(Integer savedUserId) {
+        this.savedUserId = savedUserId;
+    }
+
     @Override
     public String toString() {
         return "AbstractQuestionVO{" +
                 "id='" + id + '\'' +
+                ", state=" + state +
+                ", checkedUserId=" + checkedUserId +
+                ", savedUserId=" + savedUserId +
                 ", type=" + type +
                 ", title='" + title + '\'' +
                 ", stem='" + stem + '\'' +

+ 49 - 0
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/user/UpdateUserVO.java

@@ -0,0 +1,49 @@
+package cn.seecoder.bok.common.vo.user;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.ToString;
+
+
+@Data
+@ToString
+public class UpdateUserVO {
+    private Integer id;
+
+    private String name;
+
+    private String email;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public UpdateUserVO() {
+    }
+
+    public UpdateUserVO(Integer id, String name, String email) {
+        this.id = id;
+        this.name = name;
+        this.email = email;
+    }
+}

+ 60 - 0
seecoder-bok-common/src/main/java/cn/seecoder/bok/common/vo/user/UserVO.java

@@ -0,0 +1,60 @@
+package cn.seecoder.bok.common.vo.user;
+
+import cn.seecoder.bok.common.UserRole;
+import lombok.Data;
+import lombok.ToString;
+
+
+@Data
+@ToString
+public class UserVO {
+    private Integer id;
+
+    private UserRole role;
+
+    private String name;
+
+    private String email;
+
+    private String phone;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public UserRole getRole() {
+        return role;
+    }
+
+    public void setRole(UserRole role) {
+        this.role = role;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+}

+ 29 - 0
seecoder-bok-server/pom.xml

@@ -77,6 +77,10 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-validation</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
@@ -92,6 +96,31 @@
             <artifactId>postgresql</artifactId>
             <scope>runtime</scope>
         </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.11.0</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-configuration-processor</artifactId>

+ 81 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/aspect/auth/AuthAspect.java

@@ -0,0 +1,81 @@
+package cn.seecoder.seecoderbokserver.aspect.auth;
+
+import cn.seecoder.bok.common.vo.user.UpdateUserVO;
+import cn.seecoder.seecoderbokserver.domain.User;
+import cn.seecoder.seecoderbokserver.exception.MyServiceException;
+import cn.seecoder.seecoderbokserver.mapper.UserConvertor;
+import cn.seecoder.seecoderbokserver.service.UserService;
+import cn.seecoder.seecoderbokserver.util.JwtUtil;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.auth0.jwt.interfaces.Claim;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author mars
+ */
+@Aspect
+@Configuration
+@Order(1)
+public class AuthAspect {
+    private final UserService userService;
+
+    @Autowired
+    public AuthAspect(UserService userService) {
+        this.userService = userService;
+    }
+
+    private User getUserByToken(String token) throws JWTVerificationException {
+        try {
+            Claim claim = JwtUtil.parseJwt(token);
+            return claim.as(User.class);
+        } catch (MyServiceException e) {
+            throw new  MyServiceException(e.getCode(), "myTag"+e.getMessage());
+        }
+    }
+
+    @Before(value = "execution(public * cn.seecoder.seecoderbokserver.web.rest.*.*(..)) && @annotation(authorized)")
+    public void authCheck(JoinPoint joinPoint, Authorized authorized) {
+        HttpServletRequest httpServletRequest = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
+        String token = Optional.ofNullable(httpServletRequest.getHeader("Authorization")).
+                orElseThrow(() -> new MyServiceException("A0223", "用户未获得第三方登录授权"));
+
+        User user = getUserByToken(token);
+        // 创建或者更新用户
+        if (userService.existsById(user.getId())) {
+            userService.updateUser(new UpdateUserVO(user.getId(), user.getName(), user.getEmail()));
+        } else {
+            //TODO 这里没有对HR和TEACHER作区分
+            userService.createUser(UserConvertor.convertToVO(user));
+        }
+
+        // 判断切面方法是否包含当前token对应的角色
+        if (!Arrays.stream(authorized.roles()).collect(Collectors.toList()).contains(user.getRole())) {
+            throw new MyServiceException("A0301", "访问未授权");
+        } else {
+            // 将token的对象赋值给切面方法的user参数
+            Object[] objects = joinPoint.getArgs();
+            for (Object o : objects) {
+                if (o instanceof User) {
+                    System.out.println(user);
+                    BeanUtils.copyProperties(user, o);
+                    break;
+                }
+            }
+        }
+    }
+}

+ 15 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/aspect/auth/AuthorizationImpl.java

@@ -0,0 +1,15 @@
+package cn.seecoder.seecoderbokserver.aspect.auth;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * @author mars
+ */
+@Component
+public class AuthorizationImpl {
+
+    public boolean authorize(String token) {
+        // implement jwt or any any token based authorization logic
+        return true;
+    }
+}

+ 18 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/aspect/auth/Authorized.java

@@ -0,0 +1,18 @@
+package cn.seecoder.seecoderbokserver.aspect.auth;
+
+import cn.seecoder.bok.common.UserRole;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author mars
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Authorized {
+    UserRole[]  roles() default {UserRole.ADMIN, UserRole.STUDENT, UserRole.HR, UserRole.TEACHER};
+    String message() default "";
+}

+ 32 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/config/CorsConfig.java

@@ -0,0 +1,32 @@
+//package cn.seecoder.seecoderbokserver.config;
+//
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.web.cors.CorsConfiguration;
+//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+//import org.springframework.web.filter.CorsFilter;
+//
+///**
+// * @author: Leonezhurui
+// * @Date: 2021/8/21 - 11:20 下午
+// * @Package: SEEC-BOK
+// */
+//
+//@Configuration
+//public class CorsConfig {
+//    @Bean
+//    public CorsFilter corsFilter() {
+//        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
+//        final CorsConfiguration corsConfiguration = new CorsConfiguration();
+//        /*是否允许请求带有验证信息*/
+//        corsConfiguration.setAllowCredentials(true);
+//        /*允许访问的客户端域名*/
+//        corsConfiguration.addAllowedOrigin("*");
+//        /*允许服务端访问的客户端请求头*/
+//        corsConfiguration.addAllowedHeader("*");
+//        /*允许访问的方法名,GET POST等*/
+//        corsConfiguration.addAllowedMethod("*");
+//        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
+//        return new CorsFilter(urlBasedCorsConfigurationSource);
+//    }
+//}

+ 39 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/config/webSecurityConfig.java

@@ -0,0 +1,39 @@
+package cn.seecoder.seecoderbokserver.config;
+
+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.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/17 - 9:39 下午
+ * @Package: SEEC-BOK
+ */
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled=true)
+class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+
+    @Override
+    protected void configure( HttpSecurity httpSecurity ) throws Exception {
+        //httpSecurity.authorizeRequests().anyRequest().permitAll();
+        httpSecurity.csrf().disable();
+
+        httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+                .authorizeRequests()
+                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
+
+                .antMatchers(HttpMethod.POST).permitAll()
+                .antMatchers(HttpMethod.PUT).permitAll()
+                .antMatchers(HttpMethod.DELETE).permitAll()
+                .antMatchers(HttpMethod.GET).permitAll();
+        httpSecurity.headers().cacheControl();
+    }
+
+}

+ 130 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/domain/Knowledge.java

@@ -0,0 +1,130 @@
+package cn.seecoder.seecoderbokserver.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/8/30 - 9:16 上午
+ * @Package: SEEC-BOK
+ */
+
+@Entity
+@Table(name = "knowledge")
+public class Knowledge {
+    @Id
+    private int id;
+
+    @Column(name = "name", nullable = false)
+    private String name;
+
+    @Column(name = "name_eng", nullable = false)
+    private String nameEng;
+
+    @Column(name = "abbreviation", nullable = false)
+    private String abbreviation;
+
+    @Column(name = "parent_id", nullable = false)
+    private int parentId;
+
+    @Column(name = "parent_name", nullable = false)
+    private String parentName;
+
+    @Column(name = "uid", nullable = false)
+    private int uid;
+
+    @Column(name = "pid", nullable = false)
+    private int pid;
+
+    @Column(name = "isleaf", nullable = false)
+    private int isleaf;
+
+    @Override
+    public String toString() {
+        return "Knowledge{" +
+                "id=" + id +
+                ", name='" + name + '\'' +
+                ", nameEng='" + nameEng + '\'' +
+                ", abbreviation='" + abbreviation + '\'' +
+                ", parentId=" + parentId +
+                ", parentName='" + parentName + '\'' +
+                ", uid=" + uid +
+                ", pid=" + pid +
+                ", isleaf=" + isleaf +
+                '}';
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getNameEng() {
+        return nameEng;
+    }
+
+    public void setNameEng(String nameEng) {
+        this.nameEng = nameEng;
+    }
+
+    public String getAbbreviation() {
+        return abbreviation;
+    }
+
+    public void setAbbreviation(String abbreviation) {
+        this.abbreviation = abbreviation;
+    }
+
+    public int getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(int parentId) {
+        this.parentId = parentId;
+    }
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    public void setParentName(String parentName) {
+        this.parentName = parentName;
+    }
+
+    public int getUid() {
+        return uid;
+    }
+
+    public void setUid(int uid) {
+        this.uid = uid;
+    }
+
+    public int getPid() {
+        return pid;
+    }
+
+    public void setPid(int pid) {
+        this.pid = pid;
+    }
+
+    public int getIsleaf() {
+        return isleaf;
+    }
+
+    public void setIsleaf(int isleaf) {
+        this.isleaf = isleaf;
+    }
+}

+ 40 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/domain/Question.java

@@ -1,5 +1,6 @@
 package cn.seecoder.seecoderbokserver.domain;
 
+import cn.seecoder.bok.common.QuestionState;
 import cn.seecoder.bok.common.QuestionType;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.annotation.Id;
@@ -10,6 +11,8 @@ import org.springframework.data.elasticsearch.annotations.Document;
 import org.springframework.data.elasticsearch.annotations.Field;
 import org.springframework.data.elasticsearch.annotations.FieldType;
 
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
 import java.time.Instant;
 import java.util.List;
 import java.util.Map;
@@ -27,6 +30,16 @@ public class Question {
     @Field(name = "type", type = FieldType.Keyword)
     private QuestionType type;
 
+    @Enumerated(EnumType.STRING)
+    @Field(name = "state", type = FieldType.Keyword)
+    private QuestionState state;
+
+    @Field(name = "checkedUserId", type = FieldType.Integer)
+    private Integer checkedUserId;
+
+    @Field(name = "savedUserId", type = FieldType.Integer)
+    private Integer savedUserId;
+
     @Field(name = "title", type = FieldType.Text)
     private String title;
 
@@ -210,11 +223,38 @@ public class Question {
         this.createdTime = createdTime;
     }
 
+    public Integer getCheckedUserId() {
+        return checkedUserId;
+    }
+
+    public void setCheckedUserId(Integer checkedUserId) {
+        this.checkedUserId = checkedUserId;
+    }
+
+    public Integer getSavedUserId() {
+        return savedUserId;
+    }
+
+    public void setSavedUserId(Integer savedUserId) {
+        this.savedUserId = savedUserId;
+    }
+
+    public QuestionState getState() {
+        return state;
+    }
+
+    public void setState(QuestionState state) {
+        this.state = state;
+    }
+
     @Override
     public String toString() {
         return "Question{" +
                 "id='" + id + '\'' +
                 ", type=" + type +
+                ", state=" + state +
+                ", checkedUserId=" + checkedUserId +
+                ", savedUserId=" + savedUserId +
                 ", title='" + title + '\'' +
                 ", stem='" + stem + '\'' +
                 ", weight=" + weight +

+ 113 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/domain/User.java

@@ -0,0 +1,113 @@
+package cn.seecoder.seecoderbokserver.domain;
+
+import cn.seecoder.bok.common.UserRole;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author mars
+ */
+
+@Entity
+@Table(name = "user1")
+public class User {
+    @Id
+    @Column(name = "id")
+    private Integer id;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "role")
+    private UserRole role;
+
+    @Column(name = "name")
+    private String name;
+
+    @Column(name = "email")
+    private String email;
+
+    @Column(name = "phone")
+    private String phone;
+
+    public User() {
+    }
+
+    public User(Integer id, UserRole role, String name, String email, String phone) {
+        this.id = id;
+        this.role = role;
+        this.name = name;
+        this.email = email;
+        this.phone = phone;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public UserRole getRole() {
+        return role;
+    }
+
+    public void setRole(UserRole role) {
+        this.role = role;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    @Override
+    public String toString() {
+        return "User{" +
+                "id=" + id +
+                ", role=" + role +
+                ", name='" + name + '\'' +
+                ", email='" + email + '\'' +
+                ", phone='" + phone + '\'' +
+                '}';
+    }
+
+    //    /**
+//     * 学生参加的考试 中间表是score
+//     */
+//    @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
+//    @JoinTable(name = "score", joinColumns = @JoinColumn(name = "student_id"),
+//                                    inverseJoinColumns = @JoinColumn(name = "exam_id"))
+//    private List<Exam> exams = new ArrayList<>();
+//
+//    /**
+//     * 某个学生考试的个人成绩报告集合
+//     */
+//    @OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
+//    private List<Score> scores;
+
+}

+ 24 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/exception/MyServiceException.java

@@ -0,0 +1,24 @@
+package cn.seecoder.seecoderbokserver.exception;
+
+import org.hibernate.service.spi.ServiceException;
+
+public class MyServiceException extends ServiceException {
+    private String code;
+
+    public MyServiceException(String message, Throwable root) {
+        super(message, root);
+    }
+
+    public MyServiceException(String code, String message) {
+        super(message);
+        this.code = code;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+}

+ 28 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/mapper/KnowledgeMapper.java

@@ -0,0 +1,28 @@
+package cn.seecoder.seecoderbokserver.mapper;
+
+import cn.seecoder.bok.common.vo.KnowledgeNodeVO;
+import cn.seecoder.seecoderbokserver.domain.Knowledge;
+import org.mapstruct.Mapper;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/8/30 - 10:10 上午
+ * @Package: SEEC-BOK
+ */
+@Mapper(componentModel = "spring")
+public interface KnowledgeMapper {
+    /**
+     * domain -> vo
+     * @param knowledge
+     * @return KnowledgeNodeVO
+     */
+    KnowledgeNodeVO knowledgeToKnowledgeNodeVO(Knowledge knowledge);
+
+    /**
+     * vo -> domain
+     * @param knowledgeNodeVO
+     * @return Knowledge
+     */
+    Knowledge knowledgeNodeVOToKnowledge(KnowledgeNodeVO knowledgeNodeVO);
+
+}

+ 27 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/mapper/QuestionConvertor.java

@@ -0,0 +1,27 @@
+package cn.seecoder.seecoderbokserver.mapper;
+
+import cn.seecoder.bok.common.vo.QuestionVO;
+import cn.seecoder.bok.common.vo.user.UserVO;
+import cn.seecoder.seecoderbokserver.domain.Question;
+import cn.seecoder.seecoderbokserver.domain.User;
+import org.springframework.beans.BeanUtils;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/19 - 8:08 下午
+ * @Package: SEEC-BOK
+ */
+
+public class QuestionConvertor {
+    public static Question convertToEntity(QuestionVO questionVO) {
+        Question question = new Question();
+        BeanUtils.copyProperties(questionVO, question);
+        return question;
+    }
+
+    public static QuestionVO convertToVO(Question question) {
+        QuestionVO questionVO = new QuestionVO();
+        BeanUtils.copyProperties(question, questionVO);
+        return questionVO;
+    }
+}

+ 22 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/mapper/UserConvertor.java

@@ -0,0 +1,22 @@
+package cn.seecoder.seecoderbokserver.mapper;
+
+import cn.seecoder.bok.common.vo.user.UserVO;
+import cn.seecoder.seecoderbokserver.domain.User;
+import org.springframework.beans.BeanUtils;
+
+/**
+ * @author mars
+ */
+public class UserConvertor {
+    public static User convertToEntity(UserVO userVO) {
+        User user = new User();
+        BeanUtils.copyProperties(userVO, user);
+        return user;
+    }
+
+    public static UserVO convertToVO(User user) {
+        UserVO userVO = new UserVO();
+        BeanUtils.copyProperties(user, userVO);
+        return userVO;
+    }
+}

+ 17 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/repository/KnowledgeRepository.java

@@ -0,0 +1,17 @@
+package cn.seecoder.seecoderbokserver.repository;
+
+import cn.seecoder.seecoderbokserver.domain.Knowledge;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+import java.util.List;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/8/30 - 9:37 上午
+ * @Package: SEEC-BOK
+ */
+
+public interface KnowledgeRepository extends JpaRepository<Knowledge, Integer>, JpaSpecificationExecutor<Knowledge> {
+    List<Knowledge> findByAbbreviationLike(String keyPoints);
+}

+ 14 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/repository/UserRepository.java

@@ -0,0 +1,14 @@
+package cn.seecoder.seecoderbokserver.repository;
+
+import cn.seecoder.seecoderbokserver.domain.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/16 - 10:05 下午
+ * @Package: SEEC-BOK
+ */
+
+public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
+}

+ 25 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/service/KnowledgeService.java

@@ -0,0 +1,25 @@
+package cn.seecoder.seecoderbokserver.service;
+
+import cn.seecoder.bok.common.vo.KnowledgeNodeVO;
+import cn.seecoder.seecoderbokserver.domain.Knowledge;
+import cn.seecoder.seecoderbokserver.repository.KnowledgeRepository;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/8/30 - 9:42 上午
+ * @Package: SEEC-BOK
+ */
+
+@Service
+public class KnowledgeService {
+    private final KnowledgeRepository knowledgeRepository;
+
+    public KnowledgeService(KnowledgeRepository knowledgeRepository) {this.knowledgeRepository = knowledgeRepository;}
+
+    public List<Knowledge> findByAbbreviationLike(String keyPoints){
+        return knowledgeRepository.findByAbbreviationLike("%"+keyPoints+"%");
+    }
+}

+ 22 - 3
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/service/QuestionService.java

@@ -1,22 +1,20 @@
 package cn.seecoder.seecoderbokserver.service;
 
+import cn.seecoder.bok.common.QuestionState;
 import cn.seecoder.bok.common.QuestionType;
 import cn.seecoder.seecoderbokserver.domain.Question;
 import cn.seecoder.seecoderbokserver.repository.QuestionRepository;
 import cn.seecoder.seecoderbokserver.utility.EmptyCheck;
-import org.elasticsearch.index.query.QueryBuilder;
 import org.springframework.data.domain.*;
 import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
 import org.springframework.data.elasticsearch.core.SearchHit;
 import org.springframework.data.elasticsearch.core.SearchHits;
-import org.springframework.data.elasticsearch.core.SearchOperations;
 import org.springframework.data.elasticsearch.core.query.Criteria;
 import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
 import org.springframework.data.elasticsearch.core.query.Query;
 import org.springframework.lang.Nullable;
 import org.springframework.stereotype.Service;
 
-import javax.persistence.criteria.CriteriaBuilder;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
@@ -92,4 +90,25 @@ public class QuestionService {
                 .collect(Collectors.toList());
         return new PageImpl<>(questions, pageable, questionSearchHits.getTotalHits());
     }
+
+    public Page<Question> findUncheckedQuestion(QuestionState state, Pageable pageable){
+        Criteria criteria = new Criteria();
+        if (!EmptyCheck.instance.isEmpty(state.getName())) {
+            criteria = criteria.and("state").matches(state);
+        }
+
+        Query query = new CriteriaQuery(criteria);
+        Sort nextSort = Sort.by(pageable.getSort()
+                .map(order -> "id".equals(order.getProperty())
+                        ? new Sort.Order(order.getDirection(), "id.keyword")
+                        : order)
+                .toList());
+        query.setPageable(PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), nextSort));
+        SearchHits<Question> questionSearchHits = elasticsearchOperations.search(query, Question.class);
+        List<Question> questions = questionSearchHits.stream()
+                .map(SearchHit::getContent)
+                .collect(Collectors.toList());
+        return new PageImpl<>(questions, pageable, questionSearchHits.getTotalHits());
+    }
+
 }

+ 69 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/service/UserService.java

@@ -0,0 +1,69 @@
+package cn.seecoder.seecoderbokserver.service;
+
+import cn.seecoder.bok.common.vo.user.UpdateUserVO;
+import cn.seecoder.bok.common.vo.user.UserVO;
+import cn.seecoder.seecoderbokserver.domain.User;
+import cn.seecoder.seecoderbokserver.exception.MyServiceException;
+import cn.seecoder.seecoderbokserver.mapper.UserConvertor;
+import cn.seecoder.seecoderbokserver.repository.UserRepository;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/16 - 10:05 下午
+ * @Package: SEEC-BOK
+ */
+
+@Service
+public class UserService {
+    private final UserRepository userRepository;
+
+    public UserService(UserRepository userRepository) {
+        this.userRepository = userRepository;
+    }
+
+    static User loginUser(){
+        return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+    }
+
+    public User getLoginUser(int id){
+        User loginUser = UserService.loginUser();
+        Optional<User> user = userRepository.findById(loginUser.getId());
+
+
+        return userRepository.save(loginUser);
+    }
+
+    public UserVO getUserById(Integer id) {
+        User user = userRepository.findById(id).orElse(null);
+        if (user != null) {
+            return UserConvertor.convertToVO(user);
+        } else {
+            throw new MyServiceException("A0201", "用户账号不存在");
+        }
+    }
+
+    public boolean existsById(Integer id) {
+        return userRepository.existsById(id);
+    }
+
+    public UserVO updateUser(UpdateUserVO updateUserVO) {
+        User user = userRepository.findById(updateUserVO.getId()).orElse(null);
+        if (user != null) {
+            user.setEmail(updateUserVO.getEmail());
+            user.setName(updateUserVO.getName());
+            return UserConvertor.convertToVO(user);
+        } else {
+            throw new MyServiceException("A0201", "用户账号不存在");
+        }
+    }
+
+    public UserVO createUser(UserVO userVO) {
+        User user = userRepository.save(UserConvertor.convertToEntity(userVO));
+        return UserConvertor.convertToVO(user);
+    }
+
+}

+ 68 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/util/JwtUtil.java

@@ -0,0 +1,68 @@
+package cn.seecoder.seecoderbokserver.util;
+
+import cn.seecoder.seecoderbokserver.exception.MyServiceException;
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.auth0.jwt.interfaces.Claim;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author mars
+ */
+@Component
+public class JwtUtil {
+    private static String jwtSecret;
+    private static String jpa;
+    private static String debug;
+
+    public static String getDebug() {
+        return debug;
+    }
+
+    @Value("${debug}")
+    public void setDebug(String debug) {
+        JwtUtil.debug = debug;
+    }
+
+    @Value("${jwt.secret}")
+    public void setJwtSecret(String jwtSecret) { //通过set让static方法读取配置文件中的值
+        JwtUtil.jwtSecret = jwtSecret;
+    }
+
+    public static String getJwtSecret() {
+        return JwtUtil.jwtSecret;
+    }
+
+    public static String getJpa() {
+        return JwtUtil.jpa;
+    }
+
+    @Value("${spring.jpa.database}")
+    public void setJpa(String jpa){
+        JwtUtil.jpa = jpa;
+    }
+
+    public static Claim parseJwt(String token) {
+//        jwtSecret
+        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("SEEC-1919810-OIDC-114514")).build();
+        DecodedJWT decodedjwt;
+        try {
+            decodedjwt = jwtVerifier.verify(token);
+        } catch (TokenExpiredException e) {
+            throw new MyServiceException("A0230", "用户登陆已过期");
+        } catch (JWTVerificationException | IllegalArgumentException e) { //解析错误 或者 token写错
+            e.printStackTrace();
+            throw new MyServiceException("A0200", "登陆失败");
+        }
+//        if (decodedjwt.getClaim("exp").asDate().before(new Date())) {
+//            throw new  MyServiceException("A0230", "用户登陆已过期");
+//        }
+        return decodedjwt.getClaim("user_info");
+    }
+
+}

+ 38 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/KnowledgeController.java

@@ -0,0 +1,38 @@
+package cn.seecoder.seecoderbokserver.web.rest;
+
+import cn.seecoder.bok.common.api.SeecoderBokKnowledgeApi;
+import cn.seecoder.bok.common.vo.KnowledgeNodeVO;
+import cn.seecoder.seecoderbokserver.mapper.KnowledgeMapper;
+import cn.seecoder.seecoderbokserver.service.KnowledgeService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/8/30 - 9:46 上午
+ * @Package: SEEC-BOK
+ */
+
+@RestController
+@RequestMapping("/api/knowledge")
+public class KnowledgeController implements SeecoderBokKnowledgeApi {
+    private final KnowledgeService knowledgeService;
+    private final KnowledgeMapper knowledgeMapper;
+
+    public KnowledgeController(KnowledgeService knowledgeService, KnowledgeMapper knowledgeMapper) {
+        this.knowledgeService = knowledgeService;
+        this.knowledgeMapper = knowledgeMapper;
+    }
+
+    @Override
+    @GetMapping("")
+    public List<KnowledgeNodeVO> getKnowledgeNode(@RequestParam(name = "abbreviation_keyPoints") String keyPoints) {
+        return knowledgeService.findByAbbreviationLike(keyPoints).stream().map(knowledgeMapper::knowledgeToKnowledgeNodeVO).collect(Collectors.toList());
+    }
+
+}

+ 57 - 13
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/QuestionController.java

@@ -1,19 +1,23 @@
 package cn.seecoder.seecoderbokserver.web.rest;
 
+import cn.seecoder.bok.common.QuestionState;
 import cn.seecoder.bok.common.QuestionType;
+import cn.seecoder.bok.common.UserRole;
 import cn.seecoder.bok.common.api.SeecoderBokQuestionApi;
 import cn.seecoder.bok.common.api.SeecoderBokQuestionQueryApi;
 import cn.seecoder.bok.common.vo.QuestionVO;
+import cn.seecoder.seecoderbokserver.aspect.auth.Authorized;
 import cn.seecoder.seecoderbokserver.domain.Question;
+import cn.seecoder.seecoderbokserver.mapper.QuestionConvertor;
 import cn.seecoder.seecoderbokserver.mapper.QuestionMapper;
 import cn.seecoder.seecoderbokserver.service.QuestionService;
 import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -47,12 +51,34 @@ public class QuestionController implements SeecoderBokQuestionApi, SeecoderBokQu
                 .map(questionMapper::questionToQuestionVO);
     }
 
-    @Override
+    @GetMapping("/searchQuestion")
+    public Response getSearchQuestionList(
+            @RequestParam(name = "stem", required = false) String stem,
+            @RequestParam(name = "tag", required = false) List<String> tags,
+            @RequestParam(name = "type", required = false) List<QuestionType> questionTypes,
+            @RequestParam(name = "weight", required = false) List<Integer> weights,
+            @RequestParam(name = "knowledgeId", required = false) List<String> knowledgeIds,
+            @RequestParam(name = "offset", required = false) int offset,
+            @RequestParam(name = "pageSize", required = false) int pageSize) {
+        Pageable pageable = PageRequest.of(offset, pageSize);
+        return Response.buildSuccess(questionService.find(stem, tags, questionTypes, weights, knowledgeIds, pageable)
+                .map(questionMapper::questionToQuestionVO));
+    }
+
+    @GetMapping("/pageQuestion")
+    public Response getTargetQuestionList(
+            @RequestParam(name = "offset", required = false) int offset,
+            @RequestParam(name = "pageSize", required = false) int pageSize) {
+        Pageable pageable = PageRequest.of(offset, pageSize);
+        return Response.buildSuccess(questionService.find(null, null, null, null, null, pageable)
+                .map(questionMapper::questionToQuestionVO));
+    }
+
     @PostMapping("/question")
-    public QuestionVO createQuestion(@NotNull @RequestBody QuestionVO question) {
-        Question rawQuestion = questionMapper.questionVOTOQuestion(question);
-        return questionMapper.questionToQuestionVO(
-                questionService.save(rawQuestion));
+    public Response createQuestion(@NotNull @RequestBody QuestionVO question) {
+        Question rawQuestion = QuestionConvertor.convertToEntity(question);
+        return Response.buildSuccess(QuestionConvertor.convertToVO(
+                questionService.save(rawQuestion)));
     }
 
     @Override
@@ -72,20 +98,19 @@ public class QuestionController implements SeecoderBokQuestionApi, SeecoderBokQu
                 .map(questionMapper::questionToQuestionVO);
     }
 
-    @Override
     @PutMapping("/question/{id}")
-    public QuestionVO updateQuestion(
+    public Response updateQuestion(
             @NotNull @RequestBody QuestionVO question) {
-        Question rawQuestion = questionMapper.questionVOTOQuestion(question);
-        return questionMapper.questionToQuestionVO(
-                questionService.save(rawQuestion));
+        Question rawQuestion = QuestionConvertor.convertToEntity(question);
+        return Response.buildSuccess(
+                QuestionConvertor.convertToVO(questionService.save(rawQuestion)));
     }
 
-    @Override
     @DeleteMapping("/question/{id}")
-    public void deleteQuestionById(
+    public Response deleteQuestionById(
             @NotBlank @PathVariable(name = "id") String questionId) {
         questionService.delete(questionId);
+        return Response.buildSuccess("Delete Successfully");
     }
 
     @Override
@@ -94,4 +119,23 @@ public class QuestionController implements SeecoderBokQuestionApi, SeecoderBokQu
         return StreamSupport.stream(questionService.findAllById(ids).spliterator(), false)
                 .map(questionMapper::questionToQuestionVO).collect(Collectors.toList());
     }
+
+//    @GetMapping("/test")
+//
+//    public String testQuestionController() {
+//        return "OK!";
+//    }
+
+
+    @GetMapping("/state")
+    @Authorized(roles = {UserRole.ADMIN, UserRole.HR, UserRole.TEACHER})
+    public Response findUncheckedQuestion(
+            @RequestParam(name = "state") QuestionState questionState,
+            @RequestParam(name = "offset", required = false) int offset,
+            @RequestParam(name = "pageSize", required = false) int pageSize
+            ){
+        Pageable pageable = PageRequest.of(offset, pageSize);
+        return Response.buildSuccess(questionService.findUncheckedQuestion(questionState, pageable));
+    }
+
 }

+ 61 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/Response.java

@@ -0,0 +1,61 @@
+package cn.seecoder.seecoderbokserver.web.rest;
+
+import lombok.Data;
+import org.hibernate.service.spi.ServiceException;
+
+@Data
+public class Response {
+    private String code;
+    private String msg;
+    private Object result;
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Object getResult() {
+        return result;
+    }
+
+    public void setResult(Object result) {
+        this.result = result;
+    }
+
+    public Response(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public Response() {
+    }
+
+    public Response(String code, String msg, Object result) {
+        this.code = code;
+        this.msg = msg;
+        this.result = result;
+    }
+
+    public static Response buildSuccess(Object result) {
+        return new Response("00000", "Success", result);
+    }
+
+    public static Response buildFailed(String code, ServiceException e) {
+        return new Response(code, e.getLocalizedMessage(), null);
+    }
+
+    public static Response buildFailed(String code, String msg) {
+        return new Response(code, msg, null);
+    }
+}

+ 57 - 0
seecoder-bok-server/src/main/java/cn/seecoder/seecoderbokserver/web/rest/UserController.java

@@ -0,0 +1,57 @@
+package cn.seecoder.seecoderbokserver.web.rest;
+
+import cn.seecoder.bok.common.vo.user.UpdateUserVO;
+import cn.seecoder.bok.common.vo.user.UserVO;
+import cn.seecoder.seecoderbokserver.aspect.auth.Authorized;
+import cn.seecoder.seecoderbokserver.domain.User;
+import cn.seecoder.seecoderbokserver.service.UserService;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/16 - 10:04 下午
+ * @Package: SEEC-BOK
+ */
+
+@RestController
+@RequestMapping("/api/user")
+public class UserController {
+    private final UserService userService;
+
+    public UserController(UserService userService) {
+        this.userService = userService;
+    }
+
+    @GetMapping("")
+    @Authorized()
+    public Response getCurrentUser(User user) {
+        return Response.buildSuccess(userService.getUserById(user.getId()));
+    }
+
+    @GetMapping("/uid")
+    public Response findUserById(@RequestParam(name = "uid") Integer uid){
+        System.out.println(uid);
+        return Response.buildSuccess(userService.getUserById(uid));
+    }
+
+    @PostMapping("")
+    public UserVO createUser(@RequestBody UserVO userVO){
+        return userService.createUser(userVO);
+    }
+
+    @GetMapping("/exist")
+    public boolean existsById(@RequestParam int id){
+        return userService.existsById(id);
+    }
+
+    @PostMapping("/update")
+    public UserVO updateUser(@RequestBody UpdateUserVO updateUserVO){
+        return userService.updateUser(updateUserVO);
+    }
+
+    @GetMapping("/test")
+    public String test(){
+        return "hello";
+    }
+}

+ 15 - 5
seecoder-bok-server/src/main/resources/application-dev.yml

@@ -7,15 +7,25 @@ logging:
         client:
           RestClient: trace
 
+
+
 spring:
   jpa:
     show-sql: true
   datasource:
-    url: jdbc:postgresql://centos8.local:5432/bok
-    username: postgres
-    password: 12345678qwerQWER
+      url: jdbc:postgresql://localhost:5432/bok
+      username: postgres
+      password: 123456
+#    url: jdbc:postgresql://centos8.local:5432/bok
+#    username: postgres
+#    password: 12345678qwerQWER
+
   elasticsearch:
     rest:
-      uris: http://centos8.local:9200
+      uris: http://zhuruideMacBook-Pro.local:9200
       username: elastic
-      password: 12345678qwerQWER
+      password: 123456
+
+jwt:
+  header: Authorization
+  secret: SEEC-1919810-OIDC-114514

+ 3 - 0
seecoder-bok-server/src/main/resources/application.yml

@@ -7,3 +7,6 @@ spring:
   datasource:
     type: com.zaxxer.hikari.HikariDataSource
 
+jwt:
+  header: Authorization
+  secret: SEEC-1919810-OIDC-114514

+ 29 - 0
seecoder-bok-server/src/test/java/cn/seecoder/seecoderbokserver/jwtTest.java

@@ -0,0 +1,29 @@
+package cn.seecoder.seecoderbokserver;
+
+import cn.seecoder.seecoderbokserver.aspect.auth.Authorized;
+import cn.seecoder.seecoderbokserver.domain.User;
+import cn.seecoder.seecoderbokserver.util.JwtUtil;
+import com.auth0.jwt.interfaces.Claim;
+import io.jsonwebtoken.Jwt;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/17 - 6:54 下午
+ * @Package: SEEC-BOK
+ */
+
+public class jwtTest {
+    public static Claim testParse(String token){
+        return JwtUtil.parseJwt(token);
+    }
+
+    public static void main(String[] args) {
+        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJwLnNlZWNvZGVyLmNuIiwic3ViIjoiMTg4NTE5OTkzMDgiLCJhdWQiOiJzZWVjLW1vb2MiLCJhdXRoX3RpbWUiOjE2MzE4NzIxNTEsImlhdCI6MTYzMTg3MjE1MSwiZXhwIjoxNjMxOTU4NTUxLCJ1c2VyX2luZm8iOnsicGhvbmUiOiIxODg1MTk5OTMwOCIsImVtYWlsIjoiMTgxMjUwMjEyQHNtYWlsLm5qdS5lZHUuY24iLCJpZCI6MzY0LCJuYW1lIjoiTGVvbmUiLCJyb2xlIjoiU1RVREVOVCJ9fQ.N_fluvIauktOaDIK-_g6KYO57mFol-gCGVvH_P1WchY";
+        System.out.println(testParse(token).as(User.class).toString());
+//        System.out.println(JwtUtil.getJwtSecret());
+//        System.out.println(JwtUtil.getJpa());
+//        System.out.println(JwtUtil.getDebug());
+    }
+}

+ 32 - 0
seecoder-bok-server/src/test/java/cn/seecoder/seecoderbokserver/repository/UserRepositoryTest.java

@@ -0,0 +1,32 @@
+package cn.seecoder.seecoderbokserver.repository;
+
+import cn.seecoder.bok.common.UserRole;
+import cn.seecoder.seecoderbokserver.domain.User;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+
+/**
+ * @author: Leonezhurui
+ * @Date: 2021/9/18 - 8:28 上午
+ * @Package: SEEC-BOK
+ */
+
+@DataJpaTest
+public class UserRepositoryTest {
+    @Autowired
+    private UserRepository userRepository;
+
+    @Test
+    public void testcreate(){
+        User user = new User(9999, UserRole.STUDENT, "xiaosu", "sudeemail@qq.com", "12345678901");
+        System.out.println(UserRole.STUDENT);
+        userRepository.save(user);
+    }
+
+    @Test
+    public void test(){
+        System.out.println("niamde");
+    }
+
+}