diff --git a/Dockerfile b/Dockerfile
index 0657fa9f..deaa7465 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,8 +1,34 @@
+#FROM openjdk:11
+#MAINTAINER LiXiaoKang 191250075@smail.nju.edu.cn
+#WORKDIR /ROOT
+#ADD ./target/dingtalk-0.0.1-SNAPSHOT.jar /ROOT/
+#ENV LD_LIBRARY_PATH /usr/lib
+#ENV PROFILES="prod"
+#EXPOSE 8080
+#ENTRYPOINT ["sh", "-c", "java -jar dingtalk-0.0.1-SNAPSHOT.jar --spring.profiles.active=$PROFILES"]
+
+# First stage: complete build environment
+FROM maven:3.6.3-jdk-11-slim AS builder
+WORKDIR /code
+COPY . /code
+# add pom.xml and source code
+ADD ./pom.xml /code/pom.xml
+ADD ./src /code/src
+# package jar
+COPY ./settings.xml /root/.m2/settings.xml
+RUN mvn package -DskipTests
+
+# Second stage: minimal runtime environment
FROM openjdk:11
-MAINTAINER zhanyeye zhanyeye@qq.com
-WORKDIR /ROOT
-ADD ./target/dingtalk-0.0.1-SNAPSHOT.jar /ROOT/
+WORKDIR /app
+# Change TimeZone
+# RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
+LABEL maintainer="191250075@smail.nju.edu.cn"
+# copy jar from the first stage
+COPY --from=builder /code/target/dingtalk-2.0.1-SNAPSHOT.jar /app/app.jar
+
ENV LD_LIBRARY_PATH /usr/lib
ENV PROFILES="prod"
EXPOSE 8080
-ENTRYPOINT ["sh", "-c", "java -jar dingtalk-0.0.1-SNAPSHOT.jar --spring.profiles.active=$PROFILES"]
\ No newline at end of file
+# run jar
+ENTRYPOINT ["sh", "-c", "java -jar /app/app.jar --spring.profiles.active=$PROFILES"]
diff --git a/README.md b/README.md
index 00392d2d..8ea1be23 100644
--- a/README.md
+++ b/README.md
@@ -88,7 +88,7 @@
-+ 钉钉SDK的封装 👉 :[com.softeng.dingtalk.api](https://github.com/nju-softeng/dingtalk-app-server/tree/main/src/main/java/com/softeng/dingtalk/api)
++ 钉钉SDK的封装 👉 :[com.softeng.dingtalk.dingApi](https://github.com/nju-softeng/dingtalk-app-server/tree/main/src/main/java/com/softeng/dingtalk/api)
+ 项目前端代码 👉 :[dingtalk-app-web](https://github.com/nju-softeng/dingtalk-app-web)
### 注意事项
diff --git a/pom.xml b/pom.xml
index accc90aa..08351e1e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
com.softeng
dingtalk
- 0.0.1-SNAPSHOT
+ 2.0.1-SNAPSHOT
dingtalk
Demo project for dingtalk mini program
@@ -182,7 +182,7 @@
com.github.ulisesbocchio
jasypt-spring-boot-starter
- 2.0.0
+ 3.0.5
diff --git a/settings.xml b/settings.xml
new file mode 100644
index 00000000..375fd900
--- /dev/null
+++ b/settings.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ alimaven
+ aliyun maven
+ http://maven.aliyun.com/nexus/content/groups/public/
+ central
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/softeng/dingtalk/DingtalkApplication.java b/src/main/java/com/softeng/dingtalk/DingtalkApplication.java
index 84a69791..f50f6011 100644
--- a/src/main/java/com/softeng/dingtalk/DingtalkApplication.java
+++ b/src/main/java/com/softeng/dingtalk/DingtalkApplication.java
@@ -1,7 +1,7 @@
package com.softeng.dingtalk;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
-import com.softeng.dingtalk.repository.impl.CustomizedRepositoryImpl;
+import com.softeng.dingtalk.dao.repository.impl.CustomizedRepositoryImpl;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -13,7 +13,7 @@
@EnableCaching
@EnableScheduling
@SpringBootApplication
-@MapperScan("com.softeng.dingtalk.mapper")
+@MapperScan("com.softeng.dingtalk.dao.mapper")
@EnableJpaRepositories(repositoryBaseClass = CustomizedRepositoryImpl.class)
public class DingtalkApplication {
diff --git a/src/main/java/com/softeng/dingtalk/aspect/ACBlockchainAspect.java b/src/main/java/com/softeng/dingtalk/aspect/ACBlockchainAspect.java
index 01649f5f..09a9b0ba 100644
--- a/src/main/java/com/softeng/dingtalk/aspect/ACBlockchainAspect.java
+++ b/src/main/java/com/softeng/dingtalk/aspect/ACBlockchainAspect.java
@@ -1,28 +1,17 @@
package com.softeng.dingtalk.aspect;
-import com.alibaba.fastjson.JSON;
import com.softeng.dingtalk.entity.AcRecord;
-import com.softeng.dingtalk.fabric.FabricManager;
-import com.softeng.dingtalk.repository.AcRecordRepository;
+import com.softeng.dingtalk.dao.repository.AcRecordRepository;
import com.softeng.dingtalk.service.SystemService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
-import org.hyperledger.fabric.sdk.exception.CryptoException;
-import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
-import org.hyperledger.fabric.sdk.exception.TransactionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Component;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
@ConditionalOnExpression("${blockchain.service.enable:true}")
@@ -37,16 +26,16 @@ public class ACBlockchainAspect {
boolean isCreate=false;
//FabricManager manager=FabricManager.obtain();
public static List timeCostList=new ArrayList<>();
- @Pointcut("execution(* com.softeng.dingtalk.repository.AcRecordRepository.save(..))")
+ @Pointcut("execution(* com.softeng.dingtalk.dao.repository.AcRecordRepository.save(..))")
public void saveRecord(){
}
- @Pointcut("execution(* com.softeng.dingtalk.repository.AcRecordRepository.deleteAll(..))")
+ @Pointcut("execution(* com.softeng.dingtalk.dao.repository.AcRecordRepository.deleteAll(..))")
public void deleteRecordList(){
}
- @Pointcut("execution(* com.softeng.dingtalk.repository.AcRecordRepository.saveAll(..)) ||" +
- "execution(* com.softeng.dingtalk.repository.AcRecordRepository.saveBatch(..))")
+ @Pointcut("execution(* com.softeng.dingtalk.dao.repository.AcRecordRepository.saveAll(..)) ||" +
+ "execution(* com.softeng.dingtalk.dao.repository.AcRecordRepository.saveBatch(..))")
public void saveRecordList(){
}
diff --git a/src/main/java/com/softeng/dingtalk/aspect/AccessPermission.java b/src/main/java/com/softeng/dingtalk/aspect/AccessPermission.java
new file mode 100644
index 00000000..fe212caf
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/aspect/AccessPermission.java
@@ -0,0 +1,17 @@
+package com.softeng.dingtalk.aspect;
+
+import com.softeng.dingtalk.enums.PermissionEnum;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 指定权限通行
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AccessPermission {
+ PermissionEnum value();
+}
diff --git a/src/main/java/com/softeng/dingtalk/aspect/AuthAspect.java b/src/main/java/com/softeng/dingtalk/aspect/AuthAspect.java
new file mode 100644
index 00000000..41b1e9a2
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/aspect/AuthAspect.java
@@ -0,0 +1,28 @@
+package com.softeng.dingtalk.aspect;
+
+import com.softeng.dingtalk.component.UserContextHolder;
+import com.softeng.dingtalk.exception.CustomExceptionEnum;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Aspect
+@Component
+public class AuthAspect {
+
+ @Resource
+ private UserContextHolder userContextHolder;
+
+ @Before("@annotation(accessPermission)")
+ public void checkPermission(AccessPermission accessPermission) {
+ for (Integer permissionId : userContextHolder.getUserContext().getPermissionIds()) {
+ if (accessPermission.value().getCode() == permissionId) {
+ return;
+ }
+ }
+ CustomExceptionEnum.ACCESS_DENIED.throwWithMessage("需要权限:" + accessPermission.value().getName());
+ }
+
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/EncryptorComponent.java b/src/main/java/com/softeng/dingtalk/component/EncryptorComponent.java
deleted file mode 100644
index b601d304..00000000
--- a/src/main/java/com/softeng/dingtalk/component/EncryptorComponent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.softeng.dingtalk.component;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpStatus;
-import org.springframework.security.crypto.encrypt.Encryptors;
-import org.springframework.stereotype.Component;
-import org.springframework.web.server.ResponseStatusException;
-
-import java.util.Map;
-
-/**
- * @author zhanyeye
- * @description 加密和解密的组件,用于token的加密和解密
- * @create 12/11/2019 10:08 AM
- */
-@Component
-public class EncryptorComponent {
- @Value("${my.secretkey}")
- private String secretKey;
- @Value("${my.salt}")
- private String salt;
-
- @Autowired
- private ObjectMapper objectMapper;
-
- /**
- * 加密: 将一个map序列化为字符串,并加密
- * @param payload
- * @return
- */
- public String encrypt(Map payload) {
- try {
- String json = objectMapper.writeValueAsString(payload);
- return Encryptors.text(secretKey, salt).encrypt(json);
- } catch (JsonProcessingException e) {}
- return null;
- }
-
- /**
- * 解密: 将字符串反序列化为map, 并解密
- * @param encryptString
- * @return
- */
- public Map decrypt(String encryptString) {
- try {
- String json = Encryptors.text(secretKey, salt).decrypt(encryptString);
- return objectMapper.readValue(json, Map.class);
- } catch (Exception e) {
- //若反序列化时抛异常,则说明 token 是伪造的,未登录!
- throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "未登录");
- }
- }
-}
diff --git a/src/main/java/com/softeng/dingtalk/component/Timer.java b/src/main/java/com/softeng/dingtalk/component/Timer.java
index a32117a6..0e5df7a8 100644
--- a/src/main/java/com/softeng/dingtalk/component/Timer.java
+++ b/src/main/java/com/softeng/dingtalk/component/Timer.java
@@ -1,27 +1,23 @@
package com.softeng.dingtalk.component;
-import com.softeng.dingtalk.api.MessageApi;
-import com.softeng.dingtalk.constant.LocalUrlConstant;
-import com.softeng.dingtalk.entity.*;
+import com.softeng.dingtalk.component.dingApi.MessageApi;
+import com.softeng.dingtalk.dao.repository.*;
import com.softeng.dingtalk.enums.Position;
-import com.softeng.dingtalk.repository.AcRecordRepository;
-import com.softeng.dingtalk.repository.ExternalPaperRepository;
-import com.softeng.dingtalk.repository.InternalPaperRepository;
-import com.softeng.dingtalk.repository.VoteRepository;
-import com.softeng.dingtalk.service.InitService;
-import com.softeng.dingtalk.service.SystemService;
-import com.softeng.dingtalk.service.VoteService;
-import com.softeng.dingtalk.service.WeeklyReportService;
+import com.softeng.dingtalk.enums.PracticeStateEnum;
+import com.softeng.dingtalk.entity.*;
+import com.softeng.dingtalk.service.*;
+import com.softeng.dingtalk.utils.stuNumUtils.StuNumParser;
+import com.softeng.dingtalk.utils.stuNumUtils.StuNumParserFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
+import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
-import java.util.stream.Collectors;
/**
* @author zhanyeye
@@ -54,6 +50,11 @@ public class Timer {
@Autowired
SystemService systemService;
+ @Resource
+ private PracticeRepository practiceRepository;
+ @Resource
+ private UserRepository userRepository;
+
/**
* 每周周日23点扫描一次,给当天还未提交周报的博士、硕士发送提醒消息
*/
@@ -67,9 +68,9 @@ public void weeklyReportAndPerformanceFillingReminder() {
* 每周一凌晨2点扫描一次,查询周日一整天没有提交周报的博士、硕士,每人扣 1 ac
*/
@Scheduled(cron = "0 0 2 ? * MON")
- public void deductedPointsUnsubmittedWeeklyReport() {
+ public void deductedPointsUnSubmittedWeeklyReport() {
log.info(LocalDate.now() + " 定时扫描扣分");
- systemService.manulDeductedPointsUnsubmittedWeeklyReport(LocalDate.now());
+ systemService.manualDeductedPointsUnSubmittedWeeklyReport(LocalDate.now().minusDays(1));
}
//每天凌晨扫描一次,会议的AC结算
@@ -174,4 +175,47 @@ private String startVoteInfo(String title, LocalDateTime dateTime) {
return " #### 投票 \n ##### 论文: " + title + " \n 截止时间: " + dateTime.toLocalTime().toString();
}
+
+// @Scheduled(cron = "0/20 * * * * ?")
+// public void test() {
+// log.info(LocalDate.now() + "test");
+// }
+
+ /**
+ * 每天凌晨一点根据审核通过的实习申请修改对应用户的工作状态
+ */
+ @Scheduled(cron = "0 0 1 * * ?")
+ public void editWorkState() {
+ log.info("每天凌晨一点根据审核通过的实习申请修改对应用户的工作状态");
+ List practiceList = practiceRepository.findAllByStateEquals(PracticeStateEnum.ACCEPTED.getValue());
+ LocalDate cur = LocalDate.now();
+ practiceList.forEach(practice -> {
+ LocalDate start = practice.getStart();
+ LocalDate end = practice.getEnd();
+ User user = practice.getUser();
+ user.setWorkState((cur.isAfter(start) || cur.isEqual(start)) && (cur.isBefore(end) || cur.isEqual(end)));
+ userRepository.save(user);
+ });
+ }
+
+ /**
+ * 每月22日15点10分进行用户职位的变更
+ */
+ @Scheduled(cron = "0 10 15 22 * ?")
+ public void updateUserPosition() {
+ log.info("每月22日15点10分进行用户职位的变更");
+ userRepository.findAllValidUser()
+ .stream()
+// 筛选出设置了学号的用户
+ .filter((user -> user.getStuNum() != null))
+ .forEach((user -> {
+ // 排除教师用户
+ if(user.getPosition() == Position.TEACHER || user.getPosition() == Position.DOCTOR) return;
+ StuNumParser parser= StuNumParserFactory.generateParser(user.getStuNum().trim().length());
+ assert parser != null;
+ user.setPosition(parser.parse(user.getStuNum()));
+ userRepository.save(user);
+ }));
+ }
+
}
diff --git a/src/main/java/com/softeng/dingtalk/component/UserContextHolder.java b/src/main/java/com/softeng/dingtalk/component/UserContextHolder.java
new file mode 100644
index 00000000..e93c6ea5
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/UserContextHolder.java
@@ -0,0 +1,72 @@
+package com.softeng.dingtalk.component;
+
+import com.softeng.dingtalk.component.encryptor.EncryptorComponent;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * @Author: LiXiaoKang
+ * @CreateTime: 2023-02-09
+ * @Description: 拦截器保存用户信息,切面验证权限后销毁
+ * @Version: 1.0
+ */
+
+@Slf4j
+@Component
+public class UserContextHolder {
+
+ @Resource
+ EncryptorComponent encryptorComponent;
+
+ @Data
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ @Accessors(chain = true)
+ public static class UserContext {
+ /**
+ * 对应user表的id字段
+ */
+ private Integer uid;
+ /**
+ * 这里的权限不仅包括permission表中的权限,还包括其他业务权限(例如评审,是否是是该组成员等)
+ */
+ private List permissionIds;
+
+ /**
+ *
+ * 用户角色,v2已弃用,设置主要是为了兼容v1
+ */
+ @Deprecated
+ private String role;
+ }
+ private final ThreadLocal userContext = new ThreadLocal<>();
+
+ public UserContext getUserContext() {
+ return userContext.get();
+ }
+
+ public void setUserContext(UserContext userContext) {
+ this.userContext.set(userContext);
+ }
+
+ public void remove() {
+ this.userContext.remove();
+ }
+
+ public UserContext decrypt(String str) {
+ return encryptorComponent.decrypt(str, UserContextHolder.UserContext.class);
+ }
+
+ public String encrypt(UserContext userContext) {
+ return encryptorComponent.encrypt(userContext);
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/AbstractConvertorTemplate.java b/src/main/java/com/softeng/dingtalk/component/convertor/AbstractConvertorTemplate.java
new file mode 100644
index 00000000..fc979f1a
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/AbstractConvertorTemplate.java
@@ -0,0 +1,48 @@
+package com.softeng.dingtalk.component.convertor;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * @Author: LiXiaoKang
+ * @CreateTime: 2023-02-08
+ * @Description: 对象转换器的模版类,实现init方法register特殊字段逻辑就可以使用
+ * @Version: 1.0
+ */
+
+public abstract class AbstractConvertorTemplate implements CommonConvertorInterface {
+
+ private final CommonConvertorHelper req2entityHelper;
+ private final CommonConvertorHelper entity2respHelper;
+
+ public AbstractConvertorTemplate() {
+ // 被继承后可以获取自身类型参数
+ Type[] types = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
+ Class reqClass = (Class) types[0];
+ Class respClass = (Class) types[1];
+ Class entityClass = (Class) types[2];
+ req2entityHelper = new CommonConvertorHelper<>(reqClass, entityClass);
+ entity2respHelper = new CommonConvertorHelper<>(entityClass, respClass);
+ req2EntityLogicRegister(req2entityHelper);
+ entity2RespLogicRegister(entity2respHelper);
+ }
+
+ /**
+ * 留四个钩子,在这把四个helper的例外转换逻辑register进去
+ * 没有特殊逻辑就不用管了
+ */
+ protected void req2EntityLogicRegister(CommonConvertorHelper helper) {}
+ protected void entity2RespLogicRegister(CommonConvertorHelper helper) {}
+
+
+ @Override
+ public ENTITY req2Entity(REQ req) {
+ return req2entityHelper.convert(req);
+ }
+
+
+ @Override
+ public RESP entity2Resp(ENTITY entity) {
+ return entity2respHelper.convert(entity);
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/CommonConvertorHelper.java b/src/main/java/com/softeng/dingtalk/component/convertor/CommonConvertorHelper.java
new file mode 100644
index 00000000..77bace40
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/CommonConvertorHelper.java
@@ -0,0 +1,106 @@
+package com.softeng.dingtalk.component.convertor;
+
+import lombok.SneakyThrows;
+import org.apache.commons.lang3.tuple.Triple;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: LiXiaoKang
+ * @CreateTime: 2023-02-08
+ * @Description: 处理两个需要转换类的信息,调用方法进行转换
+ * @Version: 1.0
+ */
+
+public class CommonConvertorHelper {
+
+ /**
+ * 用户指定的转换
+ */
+ private final List>> fieldTriples = new ArrayList<>();
+
+ private final Class fromClass;
+ private final Class toClass;
+
+ public CommonConvertorHelper(Class fromClass, Class toClass) {
+ this.fromClass = fromClass;
+ this.toClass = toClass;
+ // 存储可以直接转换的字段 名字相同 && 类型相同
+ Field[] srcFields = fromClass.getDeclaredFields();
+ Field[] tgtFields = toClass.getDeclaredFields();
+ for (Field srcField : srcFields) {
+ for (Field tgtField : tgtFields) {
+ if (srcField.getName().equals(tgtField.getName()) && srcField.getType().equals(tgtField.getType())) {
+ fieldTriples.add(Triple.of(srcField, tgtField, FieldConvertor.SAME_FIELD_CONVERTOR));
+ break;
+ }
+ }
+ }
+ }
+
+ @SneakyThrows
+ public CommonConvertorHelper register(Field srcField, Field tgtField, FieldConvertor fieldConvertor) {
+ // 1. 参数校验
+ assert fromClass.getDeclaredField(srcField.getName()).getType().equals(srcField.getType())
+ && toClass.getDeclaredField(tgtField.getName()).getType().equals(tgtField.getType());
+ ParameterizedType parameterizedType = (ParameterizedType) fieldConvertor.getClass().getGenericInterfaces()[0];
+ assert parameterizedType.getActualTypeArguments()[0].equals(srcField.getType())
+ && parameterizedType.getActualTypeArguments()[1].equals(tgtField.getType());
+ // 2. 加入列表
+ this.fieldTriples.add(Triple.of(srcField, tgtField, fieldConvertor));
+ return this;
+ }
+
+ @SneakyThrows
+ public CommonConvertorHelper register(String srcFieldName, String tgtFieldName, FieldConvertor fieldConvertor) {
+ return register(fromClass.getDeclaredField(srcFieldName), toClass.getDeclaredField(tgtFieldName), fieldConvertor);
+ }
+
+ @SneakyThrows
+ public TO convert(FROM from) {
+ if (from == null) {
+ return null;
+ }
+ TO to = toClass.getDeclaredConstructor().newInstance();
+ for (Triple> triple : fieldTriples) {
+ Field srcField = triple.getLeft();
+ Field tgtField = triple.getMiddle();
+ FieldConvertor fieldConvertor = triple.getRight();
+ boolean srcAcc = srcField.canAccess(from);
+ boolean tgtAcc = tgtField.canAccess(to);
+ srcField.setAccessible(true);
+ tgtField.setAccessible(true);
+ tgtField.set(to, fieldConvertor.convert(srcField.get(from)));
+ srcField.setAccessible(srcAcc);
+ tgtField.setAccessible(tgtAcc);
+ }
+ return to;
+ }
+
+ @FunctionalInterface
+ public interface FieldConvertor {
+ TO convert(FROM from);
+
+ /**
+ * 不能写成lambda,否则获取不到泛型参数
+ */
+ FieldConvertor, ?> SAME_FIELD_CONVERTOR = from -> from;
+// FieldConvertor STRING_CLASSIFIER_ENUM_FIELD_CONVERTOR = new FieldConvertor() {
+// @Override
+// public ClassifierEnum convert(String s) {
+// return ClassifierEnum.fromString(s);
+// }
+// };
+// FieldConvertor CLASSIFIER_ENUM_STRING_FIELD_CONVERTOR = new FieldConvertor() {
+// @Override
+// public String convert(ClassifierEnum classifierEnum) {
+// return classifierEnum.toString();
+// }
+// };
+
+ }
+
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/CommonConvertorInterface.java b/src/main/java/com/softeng/dingtalk/component/convertor/CommonConvertorInterface.java
new file mode 100644
index 00000000..f9bf3250
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/CommonConvertorInterface.java
@@ -0,0 +1,35 @@
+package com.softeng.dingtalk.component.convertor;
+
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @Author: LiXiaokang
+ * @CreateTime: 2023-02-08
+ * @Description: 微服务里四层对象转换器的接口
+ * @Version: 1.0
+ */
+public interface CommonConvertorInterface {
+
+ ENTITY req2Entity(REQ req);
+ RESP entity2Resp(ENTITY entity);
+
+ default List _batchTransfer(List froms, Function transferLogic) {
+ return CollectionUtils.isEmpty(froms)
+ ? new ArrayList<>()
+ : froms.stream().map(transferLogic).collect(Collectors.toList());
+ }
+
+ default List batchReq2Entity(List reqList) {
+ return _batchTransfer(reqList, this::req2Entity);
+ }
+
+ default List batchEntity2Resp(List entities) {
+ return _batchTransfer(entities, this::entity2Resp);
+ }
+
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/InternshipPeriodRecommendedConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/InternshipPeriodRecommendedConvertor.java
new file mode 100644
index 00000000..3f390271
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/InternshipPeriodRecommendedConvertor.java
@@ -0,0 +1,22 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.InternshipPeriodRecommendedReq;
+import com.softeng.dingtalk.dto.resp.InternshipPeriodRecommendedResp;
+import com.softeng.dingtalk.entity.InternshipPeriodRecommended;
+import com.softeng.dingtalk.entity.User;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+@Component
+public class InternshipPeriodRecommendedConvertor extends AbstractConvertorTemplate{
+ @Override
+ public InternshipPeriodRecommended req2Entity(InternshipPeriodRecommendedReq internshipPeriodRecommendedReq) {
+ InternshipPeriodRecommended res = super.req2Entity(internshipPeriodRecommendedReq);
+ res.setAuthor(new User().setId(internshipPeriodRecommendedReq.getAuthorId()));
+// 这里加上时间,因为News有release_time字段,且为null,
+// 会让数据库表的default CURRENT_TIMESTAMP失效
+ res.setReleaseTime(LocalDateTime.now());
+ return res;
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/NewsConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/NewsConvertor.java
new file mode 100644
index 00000000..73a5b729
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/NewsConvertor.java
@@ -0,0 +1,32 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.NewsReq;
+import com.softeng.dingtalk.dto.resp.NewsResp;
+import com.softeng.dingtalk.entity.News;
+import com.softeng.dingtalk.entity.User;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+@Component
+public class NewsConvertor extends AbstractConvertorTemplate{
+
+ @Override
+ public News req2Entity(NewsReq newsReq) {
+ News res = super.req2Entity(newsReq);
+ res.setAuthor(new User().setId(newsReq.getAuthorId()));
+ res.setIsDeleted(0);
+ res.setIsShown(1);
+// 这里加上时间,因为News有release_time字段,且为null,
+// 会让数据库表的default CURRENT_TIMESTAMP失效
+ res.setReleaseTime(LocalDateTime.now());
+ return res;
+ }
+
+ @Override
+ public NewsResp entity2Resp(News news) {
+ return super.entity2Resp(news)
+ .setAuthorName(news.getAuthor().getName())
+ .setAuthorId(news.getAuthor().getId());
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/PatentConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/PatentConvertor.java
new file mode 100644
index 00000000..21badf67
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/PatentConvertor.java
@@ -0,0 +1,25 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.PatentReq;
+import com.softeng.dingtalk.dto.resp.PatentResp;
+import com.softeng.dingtalk.entity.Patent;
+import com.softeng.dingtalk.utils.StreamUtils;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+public class PatentConvertor extends AbstractConvertorTemplate {
+ @Resource
+ private UserConvertor userConvertor;
+ @Resource
+ private PatentDetailConvertor patentDetailConvertor;
+
+ @Override
+ public PatentResp entity2Resp
+ (Patent patent) {
+ return super.entity2Resp(patent)
+ .setApplicant(userConvertor.entity2Resp(patent.getApplicant()))
+ .setPatentDetailList(StreamUtils.map(patent.getPatentDetailList(), patentDetail -> patentDetailConvertor.entity2Resp(patentDetail)));
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/PatentDetailConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/PatentDetailConvertor.java
new file mode 100644
index 00000000..fe9420bc
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/PatentDetailConvertor.java
@@ -0,0 +1,19 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.PatentDetailReq;
+import com.softeng.dingtalk.dto.resp.PatentDetailResp;
+import com.softeng.dingtalk.entity.PatentDetail;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+public class PatentDetailConvertor extends AbstractConvertorTemplate {
+ @Resource
+ private UserConvertor userConvertor;
+
+ @Override
+ public PatentDetailResp entity2Resp(PatentDetail patentDetail) {
+ return super.entity2Resp(patentDetail).setUser(userConvertor.entity2Resp(patentDetail.getUser()));
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/PermissionConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/PermissionConvertor.java
new file mode 100644
index 00000000..30ba30f7
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/PermissionConvertor.java
@@ -0,0 +1,10 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.PermissionReq;
+import com.softeng.dingtalk.dto.resp.PermissionResp;
+import com.softeng.dingtalk.entity.Permission;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PermissionConvertor extends AbstractConvertorTemplate {
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/PracticeConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/PracticeConvertor.java
new file mode 100644
index 00000000..3cc45a29
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/PracticeConvertor.java
@@ -0,0 +1,27 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dao.repository.UserRepository;
+import com.softeng.dingtalk.dto.req.PracticeReq;
+import com.softeng.dingtalk.dto.resp.PracticeResp;
+import com.softeng.dingtalk.entity.Practice;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+public class PracticeConvertor extends AbstractConvertorTemplate {
+ @Resource
+ private UserConvertor userConvertor;
+ @Resource
+ private UserRepository userRepository;
+
+ @Override
+ public PracticeResp entity2Resp(Practice practice) {
+ return super.entity2Resp(practice).setUser(userConvertor.entity2Resp(practice.getUser()));
+ }
+
+ @Override
+ public Practice req2Entity(PracticeReq practiceReq) {
+ return super.req2Entity(practiceReq).setUser(userRepository.findById(practiceReq.getUserId()).get());
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/ReimbursementConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/ReimbursementConvertor.java
new file mode 100644
index 00000000..0a549da3
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/ReimbursementConvertor.java
@@ -0,0 +1,18 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.ReimbursementReq;
+import com.softeng.dingtalk.dto.resp.ReimbursementResp;
+import com.softeng.dingtalk.entity.Reimbursement;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+public class ReimbursementConvertor extends AbstractConvertorTemplate {
+ @Resource
+ private UserConvertor userConvertor;
+ @Override
+ public ReimbursementResp entity2Resp(Reimbursement reimbursement) {
+ return super.entity2Resp(reimbursement).setUser(userConvertor.entity2Resp(reimbursement.getUser()));
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/TeamConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/TeamConvertor.java
new file mode 100644
index 00000000..b20c1b5a
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/TeamConvertor.java
@@ -0,0 +1,10 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.TeamReq;
+import com.softeng.dingtalk.dto.resp.TeamResp;
+import com.softeng.dingtalk.entity.Team;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TeamConvertor extends AbstractConvertorTemplate {
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/UserConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/UserConvertor.java
new file mode 100644
index 00000000..1e602ee5
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/UserConvertor.java
@@ -0,0 +1,26 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.UserReq;
+import com.softeng.dingtalk.dto.resp.UserResp;
+import com.softeng.dingtalk.entity.User;
+import com.softeng.dingtalk.service.PermissionService;
+import com.softeng.dingtalk.service.TeamService;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+public class UserConvertor extends AbstractConvertorTemplate {
+
+ @Resource
+ private PermissionService permissionService;
+ @Resource
+ private TeamService teamService;
+
+ @Override
+ public UserResp entity2Resp(User user) {
+ return super.entity2Resp(user)
+ .setPermissionList(permissionService.getPermissions(user.getId()))
+ .setTeamList(teamService.getTeams(user.getId()));
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/UserPermissionConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/UserPermissionConvertor.java
new file mode 100644
index 00000000..93597408
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/UserPermissionConvertor.java
@@ -0,0 +1,11 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.UserPermissionReq;
+import com.softeng.dingtalk.dto.resp.UserPermissionResp;
+import com.softeng.dingtalk.entity.UserPermission;
+import org.springframework.stereotype.Component;
+
+@Component
+public class UserPermissionConvertor extends AbstractConvertorTemplate {
+}
+
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/UserTeamConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/UserTeamConvertor.java
new file mode 100644
index 00000000..b23a0b3d
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/UserTeamConvertor.java
@@ -0,0 +1,10 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.UserTeamReq;
+import com.softeng.dingtalk.dto.resp.UserTeamResp;
+import com.softeng.dingtalk.entity.UserTeam;
+import org.springframework.stereotype.Component;
+
+@Component
+public class UserTeamConvertor extends AbstractConvertorTemplate {
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/convertor/VMApplyConvertor.java b/src/main/java/com/softeng/dingtalk/component/convertor/VMApplyConvertor.java
new file mode 100644
index 00000000..dfd8b884
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/convertor/VMApplyConvertor.java
@@ -0,0 +1,19 @@
+package com.softeng.dingtalk.component.convertor;
+
+import com.softeng.dingtalk.dto.req.VMApplyReq;
+import com.softeng.dingtalk.dto.resp.VMApplyResp;
+import com.softeng.dingtalk.entity.VMApply;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+@Component
+public class VMApplyConvertor extends AbstractConvertorTemplate {
+ @Resource
+ private UserConvertor userConvertor;
+
+ @Override
+ public VMApplyResp entity2Resp(VMApply vmApply) {
+ return super.entity2Resp(vmApply).setUser(userConvertor.entity2Resp(vmApply.getUser()));
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/api/BaseApi.java b/src/main/java/com/softeng/dingtalk/component/dingApi/BaseApi.java
similarity index 99%
rename from src/main/java/com/softeng/dingtalk/api/BaseApi.java
rename to src/main/java/com/softeng/dingtalk/component/dingApi/BaseApi.java
index 9d5b3db4..6327bf25 100644
--- a/src/main/java/com/softeng/dingtalk/api/BaseApi.java
+++ b/src/main/java/com/softeng/dingtalk/component/dingApi/BaseApi.java
@@ -1,4 +1,4 @@
-package com.softeng.dingtalk.api;
+package com.softeng.dingtalk.component.dingApi;
import com.aliyun.dingtalkdrive_1_0.models.*;
import com.aliyun.oss.ClientConfiguration;
diff --git a/src/main/java/com/softeng/dingtalk/api/ContactsApi.java b/src/main/java/com/softeng/dingtalk/component/dingApi/ContactsApi.java
similarity index 98%
rename from src/main/java/com/softeng/dingtalk/api/ContactsApi.java
rename to src/main/java/com/softeng/dingtalk/component/dingApi/ContactsApi.java
index fbbf4787..9c8d65cb 100644
--- a/src/main/java/com/softeng/dingtalk/api/ContactsApi.java
+++ b/src/main/java/com/softeng/dingtalk/component/dingApi/ContactsApi.java
@@ -1,4 +1,4 @@
-package com.softeng.dingtalk.api;
+package com.softeng.dingtalk.component.dingApi;
import com.dingtalk.api.request.OapiDepartmentListRequest;
import com.dingtalk.api.request.OapiUserGetDeptMemberRequest;
diff --git a/src/main/java/com/softeng/dingtalk/api/MessageApi.java b/src/main/java/com/softeng/dingtalk/component/dingApi/MessageApi.java
similarity index 98%
rename from src/main/java/com/softeng/dingtalk/api/MessageApi.java
rename to src/main/java/com/softeng/dingtalk/component/dingApi/MessageApi.java
index e698986f..23956c57 100644
--- a/src/main/java/com/softeng/dingtalk/api/MessageApi.java
+++ b/src/main/java/com/softeng/dingtalk/component/dingApi/MessageApi.java
@@ -1,4 +1,4 @@
-package com.softeng.dingtalk.api;
+package com.softeng.dingtalk.component.dingApi;
import com.dingtalk.api.request.OapiChatSendRequest;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
diff --git a/src/main/java/com/softeng/dingtalk/api/OAApi.java b/src/main/java/com/softeng/dingtalk/component/dingApi/OAApi.java
similarity index 87%
rename from src/main/java/com/softeng/dingtalk/api/OAApi.java
rename to src/main/java/com/softeng/dingtalk/component/dingApi/OAApi.java
index ae36d6c6..321654c9 100644
--- a/src/main/java/com/softeng/dingtalk/api/OAApi.java
+++ b/src/main/java/com/softeng/dingtalk/component/dingApi/OAApi.java
@@ -1,19 +1,16 @@
-package com.softeng.dingtalk.api;
+package com.softeng.dingtalk.component.dingApi;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiProcessInstanceTerminateRequest;
-import com.dingtalk.api.request.OapiProcessWorkrecordCreateRequest;
import com.dingtalk.api.request.OapiProcessinstanceCreateRequest;
import com.dingtalk.api.request.OapiProcessinstanceGetRequest;
import com.dingtalk.api.response.OapiProcessInstanceTerminateResponse;
-import com.dingtalk.api.response.OapiProcessWorkrecordCreateResponse;
import com.dingtalk.api.response.OapiProcessinstanceCreateResponse;
import com.dingtalk.api.response.OapiProcessinstanceGetResponse;
import com.softeng.dingtalk.entity.AbsentOA;
import com.softeng.dingtalk.entity.User;
import com.softeng.dingtalk.service.UserService;
-import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -22,8 +19,6 @@
import org.springframework.web.server.ResponseStatusException;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
@Slf4j
@@ -33,29 +28,29 @@ public class OAApi extends BaseApi{
UserService userService;
@Value("${OA.askForLeaveProcessCode}")
private String absentOAProcessCode;
- public String createAbsentOA(AbsentOA absentOA) {
+ public String createAbsentOA(AbsentOA absentOAPO) {
try {
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/create");
OapiProcessinstanceCreateRequest request= new OapiProcessinstanceCreateRequest();
- request.setAgentId(BaseApi.AGENTID);
+ request.setAgentId(AGENTID);
//设置process code
request.setProcessCode(absentOAProcessCode);
- request.setOriginatorUserId(userService.getUserid(absentOA.getUser().getId()));
+ request.setOriginatorUserId(userService.getUserid(absentOAPO.getUser().getId()));
request.setDeptId(-1L);
//设置表单内容
List form = new ArrayList<>();
OapiProcessinstanceCreateRequest.FormComponentValueVo type = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
form.add(type);
type.setName("请假类型");
- type.setValue(absentOA.getType());
+ type.setValue(absentOAPO.getType());
OapiProcessinstanceCreateRequest.FormComponentValueVo start = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
form.add(start);
start.setName("开始时间");
- start.setValue(absentOA.getDingTalkSchedule().getStart().toString());
+ start.setValue(absentOAPO.getDingTalkSchedule().getStart().toString());
OapiProcessinstanceCreateRequest.FormComponentValueVo end = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
form.add(end);
end.setName("结束时间");
- end.setValue(absentOA.getDingTalkSchedule().getEnd().toString());
+ end.setValue(absentOAPO.getDingTalkSchedule().getEnd().toString());
// OapiProcessinstanceCreateRequest.FormComponentValueVo dayNum = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
// form.add(dayNum);
// dayNum.setName("结束时间");
@@ -63,13 +58,13 @@ public String createAbsentOA(AbsentOA absentOA) {
OapiProcessinstanceCreateRequest.FormComponentValueVo reason = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
form.add(reason);
reason.setName("请假缘由");
- reason.setValue(absentOA.getReason());
+ reason.setValue(absentOAPO.getReason());
request.setFormComponentValues(form);
//设置审批人
List processInstanceApproverVoList = new ArrayList<>();
OapiProcessinstanceCreateRequest.ProcessInstanceApproverVo processInstanceApproverVo = new OapiProcessinstanceCreateRequest.ProcessInstanceApproverVo();
processInstanceApproverVoList.add(processInstanceApproverVo);
- request.setApprovers(absentOA.getDingTalkSchedule().getOrganizer().getUserid());
+ request.setApprovers(absentOAPO.getDingTalkSchedule().getOrganizer().getUserid());
OapiProcessinstanceCreateResponse rsp = client.execute(request, getAccessToken());
return rsp.getProcessInstanceId();
} catch (Exception e) {
diff --git a/src/main/java/com/softeng/dingtalk/api/ReportApi.java b/src/main/java/com/softeng/dingtalk/component/dingApi/ReportApi.java
similarity index 98%
rename from src/main/java/com/softeng/dingtalk/api/ReportApi.java
rename to src/main/java/com/softeng/dingtalk/component/dingApi/ReportApi.java
index 5967222b..811031a0 100644
--- a/src/main/java/com/softeng/dingtalk/api/ReportApi.java
+++ b/src/main/java/com/softeng/dingtalk/component/dingApi/ReportApi.java
@@ -1,4 +1,4 @@
-package com.softeng.dingtalk.api;
+package com.softeng.dingtalk.component.dingApi;
import com.dingtalk.api.request.OapiReportListRequest;
import com.dingtalk.api.response.OapiReportListResponse;
diff --git a/src/main/java/com/softeng/dingtalk/api/ScheduleApi.java b/src/main/java/com/softeng/dingtalk/component/dingApi/ScheduleApi.java
similarity index 99%
rename from src/main/java/com/softeng/dingtalk/api/ScheduleApi.java
rename to src/main/java/com/softeng/dingtalk/component/dingApi/ScheduleApi.java
index 41b85455..40720efe 100644
--- a/src/main/java/com/softeng/dingtalk/api/ScheduleApi.java
+++ b/src/main/java/com/softeng/dingtalk/component/dingApi/ScheduleApi.java
@@ -1,4 +1,4 @@
-package com.softeng.dingtalk.api;
+package com.softeng.dingtalk.component.dingApi;
import com.aliyun.dingtalkcalendar_1_0.models.*;
import com.aliyun.tea.TeaConverter;
diff --git a/src/main/java/com/softeng/dingtalk/encryption/Encryption.java b/src/main/java/com/softeng/dingtalk/component/encryptor/Encryption.java
similarity index 95%
rename from src/main/java/com/softeng/dingtalk/encryption/Encryption.java
rename to src/main/java/com/softeng/dingtalk/component/encryptor/Encryption.java
index 7fad003e..1d86ca02 100644
--- a/src/main/java/com/softeng/dingtalk/encryption/Encryption.java
+++ b/src/main/java/com/softeng/dingtalk/component/encryptor/Encryption.java
@@ -1,4 +1,4 @@
-package com.softeng.dingtalk.encryption;
+package com.softeng.dingtalk.component.encryptor;
import org.jasypt.util.text.BasicTextEncryptor;
import org.springframework.beans.factory.annotation.Value;
@@ -6,6 +6,7 @@
import org.springframework.stereotype.Component;
@Component
+@Deprecated
public class Encryption {
@Value("${encryption.key}")
diff --git a/src/main/java/com/softeng/dingtalk/component/encryptor/EncryptorComponent.java b/src/main/java/com/softeng/dingtalk/component/encryptor/EncryptorComponent.java
new file mode 100644
index 00000000..4030eac2
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/encryptor/EncryptorComponent.java
@@ -0,0 +1,86 @@
+package com.softeng.dingtalk.component.encryptor;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.crypto.encrypt.Encryptors;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ResponseStatusException;
+
+import java.util.Map;
+
+/**
+ * @author LiXiaoKang
+ * @description 加密和解密的组件,用于token的加密和解密(与UserContentHolder结合使用)
+ * @create 2/20/2023
+ */
+@Component
+public class EncryptorComponent {
+ @Value("${my.secretkey}")
+ private String ENCRYPT_SECRET_KEY;
+ @Value("${my.salt}")
+ private String FIXED_SALT;
+
+ public static final int DYNAMIC_SALT_LENGTH = 10;
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ /**
+ * 加密: 将一个map序列化为字符串,并加密
+ * @param payload
+ * @return
+ */
+ public String encrypt(Map payload) {
+ try {
+ String json = objectMapper.writeValueAsString(payload);
+ return Encryptors.text(ENCRYPT_SECRET_KEY, FIXED_SALT).encrypt(json);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 解密: 将字符串反序列化为map, 并解密
+ * @param encryptString
+ * @return
+ */
+ public Map decrypt(String encryptString) {
+ try {
+ String json = Encryptors.text(ENCRYPT_SECRET_KEY, FIXED_SALT).decrypt(encryptString);
+ return objectMapper.readValue(json, Map.class);
+ } catch (Exception e) {
+ //若反序列化时抛异常,则说明 token 是伪造的,未登录!
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "未登录");
+ }
+ }
+
+
+ /**
+ * @description 用于ContextHolder的加解密
+ */
+
+ public String encrypt(T obj) {
+ try {
+ String json = new ObjectMapper().writeValueAsString(obj);
+ String dynamicSalt = RandomStringUtils.randomAlphabetic(DYNAMIC_SALT_LENGTH);
+ return Encryptors
+ .text(ENCRYPT_SECRET_KEY, FIXED_SALT)
+ .encrypt(dynamicSalt + json);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public T decrypt(String str, Class tClass) {
+ try {
+ String plainText = Encryptors.text(ENCRYPT_SECRET_KEY, FIXED_SALT).decrypt(str);
+ return new ObjectMapper().readValue(plainText.substring(DYNAMIC_SALT_LENGTH), tClass);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/component/interceptor/LoginInterceptor.java b/src/main/java/com/softeng/dingtalk/component/interceptor/LoginInterceptor.java
new file mode 100644
index 00000000..9348a570
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/component/interceptor/LoginInterceptor.java
@@ -0,0 +1,60 @@
+package com.softeng.dingtalk.component.interceptor;
+
+import com.softeng.dingtalk.component.encryptor.EncryptorComponent;
+import com.softeng.dingtalk.component.UserContextHolder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Optional;
+
+/**
+ * @author zhanyeye
+ * @description 登录拦截器
+ * @date 12/8/2019
+ */
+@Component
+public class LoginInterceptor implements HandlerInterceptor {
+// @Autowired
+// private EncryptorComponent encryptorComponent;
+ @Resource
+ private UserContextHolder userContextHolder;
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+// String tmp = request.getHeader("token");
+ Optional.ofNullable(request.getHeader("token"))
+ .ifPresentOrElse(token -> {
+ // 如果token存在,则将token 解密后 里面的 uid 和 aid 塞入,request 请求中
+ // 这个token 是在客户端第一次登录(向LoginController发请求),登录成功后
+ // LoginController 封装 uid 和 aid 到repsonse响应,给客户端,用于后续客户端发送的请求的声明识别
+
+ /**
+ * @Deprecated: 废弃做法
+ */
+// var token_map = encryptorComponent.decrypt(token);
+// request.setAttribute("uid", token_map.get("uid")); //塞入 用户id
+// request.setAttribute("aid", token_map.get("aid")); //塞入 用户权限值
+
+
+ /**
+ * 改用userContextHolder保存登录信息(uid与permissionId)
+ */
+ userContextHolder.setUserContext(userContextHolder.decrypt(token));
+ request.setAttribute("uid", userContextHolder.getUserContext().getUid());
+ }, () -> {
+ throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "未登录!");
+ });
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+ HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
+ userContextHolder.remove();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/softeng/dingtalk/config/CommonExceptionConfig.java b/src/main/java/com/softeng/dingtalk/config/CommonExceptionConfig.java
new file mode 100644
index 00000000..580b3486
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/config/CommonExceptionConfig.java
@@ -0,0 +1,38 @@
+package com.softeng.dingtalk.config;
+
+import com.softeng.dingtalk.dto.CommonResult;
+import com.softeng.dingtalk.exception.CommonException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+/**
+ * @Author: lilingj
+ * @CreateTime: 2023-01-14 19:31
+ * @Description: 通用全局异常捕捉
+ * @Version: 1.0
+ */
+
+@RestControllerAdvice
+@Slf4j
+public class CommonExceptionConfig {
+
+ @ExceptionHandler(CommonException.class)
+ public CommonResult handleCommonException(CommonException e) {
+ log.error("CommonException", e);
+ return CommonResult.fail(e);
+ }
+
+ @ExceptionHandler(RuntimeException.class)
+ public CommonResult handleRuntimeException(RuntimeException e) {
+ log.error("RuntimeException", e);
+ return CommonResult.fail(e);
+ }
+
+ @ExceptionHandler(Exception.class)
+ public CommonResult handleException(Exception e) {
+ log.error("Exception", e);
+ return CommonResult.fail(e);
+ }
+
+}
diff --git a/src/main/java/com/softeng/dingtalk/config/WebMvcConfig.java b/src/main/java/com/softeng/dingtalk/config/WebMvcConfig.java
index 931544ad..523867c1 100644
--- a/src/main/java/com/softeng/dingtalk/config/WebMvcConfig.java
+++ b/src/main/java/com/softeng/dingtalk/config/WebMvcConfig.java
@@ -1,6 +1,6 @@
package com.softeng.dingtalk.config;
-import com.softeng.dingtalk.interceptor.LoginInterceptor;
+import com.softeng.dingtalk.component.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -24,6 +24,8 @@ public void addInterceptors(InterceptorRegistry registry) {
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login")
.excludePathPatterns("/api/login_test/**")
+ .excludePathPatterns("/api/v2/login")
+ .excludePathPatterns("/api/v2/login_test/**")
.excludePathPatterns("/wsapi");
}
diff --git a/src/main/java/com/softeng/dingtalk/controller/ApplicationController.java b/src/main/java/com/softeng/dingtalk/controller/ApplicationController.java
index 112f7645..7044be1a 100644
--- a/src/main/java/com/softeng/dingtalk/controller/ApplicationController.java
+++ b/src/main/java/com/softeng/dingtalk/controller/ApplicationController.java
@@ -1,7 +1,7 @@
package com.softeng.dingtalk.controller;
import com.softeng.dingtalk.component.DateUtils;
-import com.softeng.dingtalk.repository.DcSummaryRepository;
+import com.softeng.dingtalk.dao.repository.DcSummaryRepository;
import com.softeng.dingtalk.service.ApplicationService;
import com.softeng.dingtalk.service.AuditService;
import com.softeng.dingtalk.service.UserService;
@@ -55,7 +55,7 @@ public int[] getDate(@RequestBody LocalDate date) {
*/
@PostMapping("/application")
public void addApplication(@RequestAttribute int uid, @Valid @RequestBody ApplyVO vo) {
- if (userService.isAuditor(uid) && uid == vo.getAuditorid()) {
+ if (uid == vo.getAuditorid()) {
applicationService.addApplicationByAuditor(vo, uid);
} else {
applicationService.addApplication(vo, uid);
@@ -69,7 +69,7 @@ public void addApplication(@RequestAttribute int uid, @Valid @RequestBody ApplyV
*/
@PutMapping("/application/{id}")
public void updateApplication(@RequestAttribute int uid, @Valid @RequestBody ApplyVO vo) {
- if (userService.isAuditor(uid) && uid == vo.getAuditorid()) {
+ if (uid == vo.getAuditorid()) {
applicationService.updateApplicationByAuditor(vo, uid);
} else {
applicationService.updateApplication(vo, uid);
diff --git a/src/main/java/com/softeng/dingtalk/controller/AuditController.java b/src/main/java/com/softeng/dingtalk/controller/AuditController.java
index 4116a758..da12be75 100644
--- a/src/main/java/com/softeng/dingtalk/controller/AuditController.java
+++ b/src/main/java/com/softeng/dingtalk/controller/AuditController.java
@@ -1,8 +1,7 @@
package com.softeng.dingtalk.controller;
import com.softeng.dingtalk.component.DateUtils;
-import com.softeng.dingtalk.api.ReportApi;
-import com.softeng.dingtalk.entity.DcRecord;
+import com.softeng.dingtalk.component.dingApi.ReportApi;
import com.softeng.dingtalk.service.AuditService;
import com.softeng.dingtalk.service.NotifyService;
import com.softeng.dingtalk.service.UserService;
@@ -11,13 +10,11 @@
import com.softeng.dingtalk.vo.ToCheckVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
-import java.time.LocalTime;
import java.util.List;
import java.util.Map;
diff --git a/src/main/java/com/softeng/dingtalk/controller/BugController.java b/src/main/java/com/softeng/dingtalk/controller/BugController.java
index 8da4ee5a..49f103e8 100644
--- a/src/main/java/com/softeng/dingtalk/controller/BugController.java
+++ b/src/main/java/com/softeng/dingtalk/controller/BugController.java
@@ -1,7 +1,7 @@
package com.softeng.dingtalk.controller;
import com.softeng.dingtalk.entity.Bug;
-import com.softeng.dingtalk.repository.BugRepository;
+import com.softeng.dingtalk.dao.repository.BugRepository;
import com.softeng.dingtalk.service.BugService;
import com.softeng.dingtalk.vo.BugCheckVO;
import lombok.extern.slf4j.Slf4j;
diff --git a/src/main/java/com/softeng/dingtalk/controller/DingTalkScheduleController.java b/src/main/java/com/softeng/dingtalk/controller/DingTalkScheduleController.java
index b1e6399c..074fa76d 100644
--- a/src/main/java/com/softeng/dingtalk/controller/DingTalkScheduleController.java
+++ b/src/main/java/com/softeng/dingtalk/controller/DingTalkScheduleController.java
@@ -1,7 +1,6 @@
package com.softeng.dingtalk.controller;
import com.softeng.dingtalk.entity.AbsentOA;
-import com.softeng.dingtalk.entity.DingTalkSchedule;
import com.softeng.dingtalk.service.DingTalkScheduleService;
import com.softeng.dingtalk.vo.AbsentOAVO;
import com.softeng.dingtalk.vo.DingTalkScheduleVO;
@@ -9,7 +8,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
-import java.util.List;
import java.util.Map;
@Slf4j
@@ -20,6 +18,7 @@ public class DingTalkScheduleController {
DingTalkScheduleService dingTalkScheduleService;
@PostMapping("/schedule")
public void addSchedule(@RequestBody DingTalkScheduleVO dingTalkScheduleVO,@RequestAttribute int uid){
+// todo-有bug
if(dingTalkScheduleVO.getId()==null) {
dingTalkScheduleService.addSchedule(dingTalkScheduleVO,uid);
} else {
diff --git a/src/main/java/com/softeng/dingtalk/controller/EventPropertyController.java b/src/main/java/com/softeng/dingtalk/controller/EventPropertyController.java
index fdf89748..1b3358ad 100644
--- a/src/main/java/com/softeng/dingtalk/controller/EventPropertyController.java
+++ b/src/main/java/com/softeng/dingtalk/controller/EventPropertyController.java
@@ -29,7 +29,7 @@ public EventProperty getEventInfo(@PathVariable int eventId){
@PostMapping("/event")
public void addEventProperty(@RequestParam String eventPropertyJsonStr){
- EventProperty eventProperty= JSONObject.parseObject(eventPropertyJsonStr,EventProperty.class);
+ EventProperty eventProperty = JSONObject.parseObject(eventPropertyJsonStr, EventProperty.class);
if(eventProperty.getId()==null){
eventPropertyService.addEventProperty(eventProperty);
}else{
diff --git a/src/main/java/com/softeng/dingtalk/controller/ExcelController.java b/src/main/java/com/softeng/dingtalk/controller/ExcelController.java
index c8fe5094..eddba868 100644
--- a/src/main/java/com/softeng/dingtalk/controller/ExcelController.java
+++ b/src/main/java/com/softeng/dingtalk/controller/ExcelController.java
@@ -20,6 +20,8 @@ public class ExcelController {
@PostMapping("/excel/ac_data")
public void downloadAcData(@RequestBody LocalDate date, HttpServletResponse response) throws IOException {
+// response.setContentType("application/vnd.ms-excel;chartset=utf-8"); //文件扩展名为excel格式
+// response.setHeader("Content-Disposition", "attachment;filename=" + "fileName.xlsx");
excelService.writeAcDataByDate(date, response.getOutputStream());
}
diff --git a/src/main/java/com/softeng/dingtalk/controller/InternshipPeriodRecommendedController.java b/src/main/java/com/softeng/dingtalk/controller/InternshipPeriodRecommendedController.java
new file mode 100644
index 00000000..03d33ea4
--- /dev/null
+++ b/src/main/java/com/softeng/dingtalk/controller/InternshipPeriodRecommendedController.java
@@ -0,0 +1,30 @@
+package com.softeng.dingtalk.controller;
+
+import com.softeng.dingtalk.dto.CommonResult;
+import com.softeng.dingtalk.dto.req.InternshipPeriodRecommendedReq;
+import com.softeng.dingtalk.dto.resp.InternshipPeriodRecommendedResp;
+import com.softeng.dingtalk.service.InternshipPeriodRecommendedService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+@Slf4j
+@RestController
+@RequestMapping("/api/v2")
+public class InternshipPeriodRecommendedController {
+
+ @Resource
+ private InternshipPeriodRecommendedService internshipPeriodRecommendedService;
+
+ @PostMapping("/internshipPeriodRecommended")
+ public CommonResult addPeriod(@RequestBody InternshipPeriodRecommendedReq internshipPeriodRecommendedReq) {
+ internshipPeriodRecommendedService.addPeriod(internshipPeriodRecommendedReq);
+ return CommonResult.success("添加成功");
+ }
+
+ @GetMapping ("/internshipPeriodRecommended")
+ public CommonResult getNewestPeriod() {
+ return CommonResult.success(internshipPeriodRecommendedService.getNewestPeriod());
+ }
+}
diff --git a/src/main/java/com/softeng/dingtalk/controller/LoginController.java b/src/main/java/com/softeng/dingtalk/controller/LoginController.java
index a3846feb..db250cd3 100644
--- a/src/main/java/com/softeng/dingtalk/controller/LoginController.java
+++ b/src/main/java/com/softeng/dingtalk/controller/LoginController.java
@@ -1,15 +1,22 @@
package com.softeng.dingtalk.controller;
-import com.softeng.dingtalk.component.EncryptorComponent;
-import com.softeng.dingtalk.api.ContactsApi;
+import com.softeng.dingtalk.component.encryptor.EncryptorComponent;
+import com.softeng.dingtalk.component.dingApi.ContactsApi;
+import com.softeng.dingtalk.component.UserContextHolder;
+import com.softeng.dingtalk.dto.CommonResult;
+import com.softeng.dingtalk.dto.resp.PermissionResp;
import com.softeng.dingtalk.entity.User;
+import com.softeng.dingtalk.service.PermissionService;
import com.softeng.dingtalk.service.SystemService;
import com.softeng.dingtalk.service.UserService;
+import com.softeng.dingtalk.utils.StreamUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
+import java.util.List;
import java.util.Map;
/**
@@ -21,7 +28,8 @@
@RestController
@RequestMapping("/api")
public class LoginController {
- //为了防止伪造角色
+
+ //为了防止伪造角色, 已经废弃
private static final String USER_ROLE = "bb63e5f7e0f2ffae845c";
private static final String AUDITOR_ROLE = "pb53e2f7g0f2hfanp4sx";
private static final String ADMIN_ROLE = "6983f953b49c88210cb9";
@@ -31,15 +39,21 @@ public class LoginController {
@Autowired
UserService userService;
@Autowired
- EncryptorComponent encryptorComponent;
- @Autowired
SystemService systemService;
+ @Autowired
+ EncryptorComponent encryptorComponent;
+ @Resource
+ UserContextHolder userContextHolder;
+ @Resource
+ PermissionService permissionService;
+
/**
- * 开发环境下登陆
+ * 开发环境下登陆(废弃)
* @param uid
* @param response
*/
+ @Deprecated
@GetMapping("/login_test/{uid}")
public void testlogin(@PathVariable int uid, HttpServletResponse response) {
log.debug("测试登陆" + uid);
@@ -52,13 +66,13 @@ public void testlogin(@PathVariable int uid, HttpServletResponse response) {
response.setHeader("uid", uid + "");
}
-
/**
- * @description 用户登录
+ * @description 用户登录(废弃)
* @param authcode:免登授权码
* @return java.util.Map
* @date 9:17 AM 12/11/2019
**/
+ @Deprecated
@PostMapping("/login")
public Map login(@RequestBody Map authcode, HttpServletResponse response) {
//根据免登授权码获取userid
@@ -77,6 +91,13 @@ public Map login(@RequestBody Map authcode, HttpServletResponse response) {
String token = encryptorComponent.encrypt(map);
// 在header创建自定义的权限
response.setHeader("token",token);
+ String role = getRole(user);
+ response.setHeader("role", role);
+ response.setHeader("uid", user.getId() + "");
+ return Map.of("role", role, "uid", user.getId(), "token", token);
+ }
+
+ private String getRole(User user) {
String role = null;
if (user.getAuthority() == User.NORMAL_AUTHORITY) {
role = USER_ROLE;
@@ -85,8 +106,69 @@ public Map login(@RequestBody Map authcode, HttpServletResponse response) {
} else {
role = ADMIN_ROLE;
}
+ return role;
+ }
+
+ /**
+ * 开发环境下登陆
+ * @param uid
+ * @param response
+ */
+ @GetMapping("/v2/login_test/{uid}")
+ public CommonResult