diff --git a/build.gradle b/build.gradle
index 94f59e9..14c0d8a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,6 +24,7 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-web'
+ implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
diff --git a/src/main/java/com/realtime/protection/configuration/entity/defense/template/Template.java b/src/main/java/com/realtime/protection/configuration/entity/defense/template/Template.java
new file mode 100644
index 0000000..80dd2ee
--- /dev/null
+++ b/src/main/java/com/realtime/protection/configuration/entity/defense/template/Template.java
@@ -0,0 +1,36 @@
+package com.realtime.protection.configuration.entity.defense.template;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Data
+public class Template {
+ @JsonProperty("template_id")
+ private Integer templateId;
+
+ @JsonProperty("template_name")
+ @NotNull(message = "template name should not be empty")
+ private String templateName;
+
+ @JsonProperty("template_elements")
+ private String[] templateElements;
+
+ @JsonProperty("default_op")
+ @NotNull(message = "default_op should not be empty")
+ private String defaultOp;
+
+ private boolean hasProtectObjectIP;
+
+ private boolean hasProtectObjectPort;
+
+ private boolean hasPeerIP;
+
+ private boolean hasPeerPort;
+
+ private boolean hasProtocol;
+
+ private boolean hasURL;
+
+ private boolean hasDNS;
+}
diff --git a/src/main/java/com/realtime/protection/configuration/entity/task/Task.java b/src/main/java/com/realtime/protection/configuration/entity/task/Task.java
new file mode 100644
index 0000000..6952169
--- /dev/null
+++ b/src/main/java/com/realtime/protection/configuration/entity/task/Task.java
@@ -0,0 +1,69 @@
+package com.realtime.protection.configuration.entity.task;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class Task {
+ @JsonProperty("task_id")
+ private Integer taskId;
+
+ @JsonProperty("task_name")
+ @NotNull(message = "task_name should not be empty")
+ private String taskName;
+
+ @JsonProperty("task_start_time")
+ @NotNull(message = "task_start_time should not be empty")
+ private LocalDateTime taskStartTime;
+
+ @JsonProperty("task_end_time")
+ @NotNull(message = "task_end_time should not be empty")
+ private LocalDateTime taskEndTime;
+
+ @JsonProperty("task_create_time")
+ private LocalDateTime taskCreateTime;
+
+ @JsonProperty("task_modify_time")
+ private LocalDateTime taskModifyTime;
+
+ @JsonProperty("task_type")
+ @NotNull(message = "task_type should not be empty")
+ private String taskType;
+
+ @JsonProperty("task_act")
+ @NotNull(message = "task_act should not be empty")
+ private String taskAct;
+
+ // These three attributes will be gained by user in the future
+ // -----------------------------------------------------------
+ @JsonProperty("task_create_username")
+ @NotNull(message = "task_create_username should not be empty")
+ private String taskCreateUsername;
+
+ @JsonProperty("task_create_depart")
+ @NotNull(message = "task_create_depart should not be empty")
+ private String taskCreateDepart;
+
+ @JsonProperty("task_create_userid")
+ @NotNull(message = "task_create_userid should not be empty")
+ private Integer taskCreateUserId;
+ // -----------------------------------------------------------
+
+ @JsonProperty("static_rule_ids")
+ private Integer[] staticRuleIds;
+
+ @JsonProperty("dynamic_rule_ids")
+ private Integer[] dynamicRuleIds;
+
+ @JsonProperty("protect_object_ids")
+ private Integer[] protectObjectIds;
+
+ @JsonProperty("task_status")
+ private Integer taskStatus;
+
+ @JsonProperty("task_audit_status")
+ private Integer taskAuditStatus;
+}
diff --git a/src/main/java/com/realtime/protection/configuration/exception/GlobalExceptionHandler.java b/src/main/java/com/realtime/protection/configuration/exception/GlobalExceptionHandler.java
index 3dc03ce..26ecf6a 100644
--- a/src/main/java/com/realtime/protection/configuration/exception/GlobalExceptionHandler.java
+++ b/src/main/java/com/realtime/protection/configuration/exception/GlobalExceptionHandler.java
@@ -1,18 +1,49 @@
package com.realtime.protection.configuration.exception;
+import cn.dev33.satoken.exception.NotLoginException;
import com.realtime.protection.configuration.response.ResponseResult;
+import org.apache.ibatis.exceptions.PersistenceException;
+import org.springframework.context.support.DefaultMessageSourceResolvable;
+import org.springframework.core.annotation.Order;
+import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
+import java.util.stream.Collectors;
+
@RestControllerAdvice
public class GlobalExceptionHandler {
- @ExceptionHandler
+ @Order(3)
+ @ExceptionHandler(value = Exception.class)
public ResponseResult handleGlobalException(Exception e) {
-
-
-
-
return ResponseResult.error().setMessage(e.getMessage());
}
+
+ @Order(2)
+ @ExceptionHandler(value = NotLoginException.class)
+ public ResponseResult handleNotLoginException(NotLoginException e) {
+ return new ResponseResult(
+ 400,
+ e.getMessage()
+ );
+ }
+
+ @Order(2)
+ @ExceptionHandler(value = PersistenceException.class)
+ public ResponseResult handleSQLException() {
+ return new ResponseResult(
+ 400,
+ "please check the integrity of the data. check if the json data exists in the database");
+ }
+
+ @Order(2)
+ @ExceptionHandler(value = MethodArgumentNotValidException.class)
+ public ResponseResult handleBindException(MethodArgumentNotValidException e) {
+ return new ResponseResult(
+ 400,
+ e.getBindingResult().getAllErrors().stream()
+ .map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining())
+ );
+ }
}
diff --git a/src/main/java/com/realtime/protection/server/defense/template/TemplateController.java b/src/main/java/com/realtime/protection/server/defense/template/TemplateController.java
new file mode 100644
index 0000000..c843abb
--- /dev/null
+++ b/src/main/java/com/realtime/protection/server/defense/template/TemplateController.java
@@ -0,0 +1,43 @@
+package com.realtime.protection.server.defense.template;
+
+import com.realtime.protection.configuration.entity.defense.template.Template;
+import com.realtime.protection.configuration.response.ResponseResult;
+import jakarta.validation.Valid;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/deftac")
+public class TemplateController {
+
+ private final TemplateService templateService;
+
+ public TemplateController(TemplateService templateService) {
+ this.templateService = templateService;
+ }
+
+ @PostMapping("/new")
+ public ResponseResult newTemplate(@RequestBody @Valid Template template) {
+ Integer templateId;
+ try {
+ templateId = templateService.newTemplate(template);
+ } catch (IllegalArgumentException e) {
+ return new ResponseResult(400, "Illegal Argument in template_elements or default_op")
+ .setData("template_id", null)
+ .setData("success", false);
+ }
+
+
+ if (templateId > 0) {
+ return ResponseResult.ok()
+ .setData("template_id", templateId)
+ .setData("success", true);
+ }
+
+ return ResponseResult.error()
+ .setData("template_id", null)
+ .setData("success", false);
+ }
+}
diff --git a/src/main/java/com/realtime/protection/server/defense/template/TemplateMapper.java b/src/main/java/com/realtime/protection/server/defense/template/TemplateMapper.java
new file mode 100644
index 0000000..e794ce6
--- /dev/null
+++ b/src/main/java/com/realtime/protection/server/defense/template/TemplateMapper.java
@@ -0,0 +1,11 @@
+package com.realtime.protection.server.defense.template;
+
+import com.realtime.protection.configuration.entity.defense.template.Template;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface TemplateMapper {
+
+ void newTemplate(@Param("template") Template template);
+}
diff --git a/src/main/java/com/realtime/protection/server/defense/template/TemplateService.java b/src/main/java/com/realtime/protection/server/defense/template/TemplateService.java
new file mode 100644
index 0000000..2c057c6
--- /dev/null
+++ b/src/main/java/com/realtime/protection/server/defense/template/TemplateService.java
@@ -0,0 +1,45 @@
+package com.realtime.protection.server.defense.template;
+
+import com.realtime.protection.configuration.entity.defense.template.Template;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+
+@Service
+public class TemplateService {
+
+ private final TemplateMapper templateMapper;
+
+ private final String[] permittedOps = new String[]{"阻断", "清洗", "篡改", "反制"};
+
+ public TemplateService(TemplateMapper templateMapper) {
+ this.templateMapper = templateMapper;
+ }
+
+ public Integer newTemplate(Template template) throws IllegalArgumentException {
+ if (!Arrays.asList(permittedOps).contains(template.getDefaultOp())) {
+ throw new IllegalArgumentException();
+ }
+
+ for (String choice : template.getTemplateElements()) {
+ switch (choice) {
+ case "防护对象IP" -> template.setHasProtectObjectIP(true);
+ case "防护对象端口" -> template.setHasProtectObjectPort(true);
+ case "对端IP" -> template.setHasPeerIP(true);
+ case "对端端口" -> template.setHasPeerPort(true);
+ case "协议" -> template.setHasProtocol(true);
+ case "URL" -> template.setHasURL(true);
+ case "DNS" -> template.setHasDNS(true);
+
+ default -> throw new IllegalArgumentException();
+ }
+ }
+
+ templateMapper.newTemplate(template);
+
+ if (template.getTemplateId() == null) {
+ return 0;
+ }
+ return template.getTemplateId();
+ }
+}
diff --git a/src/main/java/com/realtime/protection/server/task/TaskController.java b/src/main/java/com/realtime/protection/server/task/TaskController.java
new file mode 100644
index 0000000..e7399cc
--- /dev/null
+++ b/src/main/java/com/realtime/protection/server/task/TaskController.java
@@ -0,0 +1,36 @@
+package com.realtime.protection.server.task;
+
+import com.realtime.protection.configuration.entity.task.Task;
+import com.realtime.protection.configuration.response.ResponseResult;
+import jakarta.validation.Valid;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/task")
+public class TaskController {
+
+ private final TaskService taskService;
+
+ public TaskController(TaskService taskService) {
+ this.taskService = taskService;
+ }
+
+ @RequestMapping("/new")
+ public ResponseResult newTask(@RequestBody @Valid Task task) {
+ Integer taskId = taskService.newTask(task);
+
+ if (taskId > 0) {
+ return ResponseResult.ok()
+ .setData("task_name", task.getTaskName())
+ .setData("task_id", taskId)
+ .setData("success", true);
+ }
+
+ return ResponseResult.error()
+ .setData("task_name", task.getTaskName())
+ .setData("task_id", 0)
+ .setData("success", false);
+ }
+}
diff --git a/src/main/java/com/realtime/protection/server/task/TaskMapper.java b/src/main/java/com/realtime/protection/server/task/TaskMapper.java
new file mode 100644
index 0000000..403f2b4
--- /dev/null
+++ b/src/main/java/com/realtime/protection/server/task/TaskMapper.java
@@ -0,0 +1,18 @@
+package com.realtime.protection.server.task;
+
+import com.realtime.protection.configuration.entity.task.Task;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface TaskMapper {
+ void newTask(@Param("task") Task task);
+
+ void newTaskProobjConcat(@Param("task_id") Integer taskId, @Param("proobj_ids") Integer[] proobjIds);
+
+ Integer newTaskStaticRuleConcat(@Param("task_id") Integer taskId,
+ @Param("rule_ids") Integer[] staticRuleIds);
+
+ Integer newTaskDynamicRuleConcat(@Param("task_id") Integer taskId,
+ @Param("rule_ids") Integer[] dynamicRuleIds);
+}
diff --git a/src/main/java/com/realtime/protection/server/task/TaskService.java b/src/main/java/com/realtime/protection/server/task/TaskService.java
new file mode 100644
index 0000000..51905ab
--- /dev/null
+++ b/src/main/java/com/realtime/protection/server/task/TaskService.java
@@ -0,0 +1,52 @@
+package com.realtime.protection.server.task;
+
+import com.realtime.protection.configuration.entity.task.Task;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+
+@Service
+public class TaskService {
+
+ private final SqlSessionFactory sqlSessionFactory;
+
+ public TaskService(SqlSessionFactory sqlSessionFactory) {
+ this.sqlSessionFactory = sqlSessionFactory;
+ }
+
+ public Integer newTask(Task task) {
+ task.setTaskCreateTime(LocalDateTime.now());
+ task.setTaskModifyTime(LocalDateTime.now());
+
+ SqlSession session = sqlSessionFactory.openSession(false);
+ TaskMapper taskMapper = session.getMapper(TaskMapper.class);
+ try {
+ taskMapper.newTask(task);
+
+ taskMapper.newTaskProobjConcat(task.getTaskId(), task.getProtectObjectIds());
+
+
+// if (taskMapper.newTaskStaticRuleConcat(task.getTaskId(), task.getStaticRuleIds())
+// != task.getStaticRuleIds().length)
+// throw new Exception("update lines is not equal to static_rule_ids size");
+
+// if (taskMapper.newTaskDynamicRuleConcat(task.getTaskId(), task.getDynamicRuleIds())
+// != task.getDynamicRuleIds().length)
+// throw new Exception("update lines is not equal to dynamic_rule_ids size");
+
+ session.commit();
+ } catch (Exception e) {
+ session.rollback();
+ throw e;
+ } finally {
+ session.close();
+ }
+
+ if (task.getTaskId() == null) {
+ return 0;
+ }
+ return task.getTaskId();
+ }
+}
diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml
index 19be35d..17490e7 100644
--- a/src/main/resources/config/application.yml
+++ b/src/main/resources/config/application.yml
@@ -7,6 +7,8 @@ spring:
username: root
password: aiihhbfcsy123!@#
url: jdbc:mysql://localhost:3306/realtime_protection
+ hikari:
+ auto-commit: false
mvc:
servlet:
path: /api/v1
diff --git a/src/main/resources/mappers/TaskMapper.xml b/src/main/resources/mappers/TaskMapper.xml
new file mode 100644
index 0000000..c1aebeb
--- /dev/null
+++ b/src/main/resources/mappers/TaskMapper.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ INSERT INTO t_task(task_name, task_start_time, task_end_time,
+ task_act, task_type,
+ task_create_time, task_modify_time,
+ task_create_userid, task_create_username, task_create_depart)
+ VALUE(#{task.taskName}, #{task.taskStartTime}, #{task.taskEndTime},
+ #{task.taskAct}, #{task.taskType},
+ #{task.taskCreateTime}, #{task.taskModifyTime},
+ #{task.taskCreateUserId}, #{task.taskCreateUsername}, #{task.taskCreateDepart})
+
+
+
+
+ INSERT INTO t_task_project_object(task_id, protect_object_id)
+ VALUES
+
+ (#{task_id}, #{proobj_id})
+
+
+
+
+
+ UPDATE t_static_rule
+ SET static_rule_used_task_id = #{task_id}
+ WHERE static_rule_id IN
+
+ #{rule_id}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/mappers/TemplateMapper.xml b/src/main/resources/mappers/TemplateMapper.xml
new file mode 100644
index 0000000..0c64032
--- /dev/null
+++ b/src/main/resources/mappers/TemplateMapper.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ INSERT INTO t_strategy_template(strategy_template_name,
+ has_protect_object_ip, has_protect_object_port,
+ has_peer_ip, has_peer_port,
+ has_protocol, has_url, has_dns,
+ strategy_template_create_user_id,
+ strategy_template_create_username, strategy_template_create_depart,
+ default_op)
+ VALUE (#{template.templateName},
+ #{template.hasProtectObjectIP}, #{template.hasProtectObjectPort},
+ #{template.hasPeerIP}, #{template.hasPeerPort},
+ #{template.hasProtocol}, #{template.hasURL}, #{template.hasDNS},
+ 0,
+ #{template.templateName}, #{template.templateName},
+ #{template.defaultOp})
+
+
\ No newline at end of file
diff --git a/src/test/java/com/realtime/protection/server/defense/template/TemplateServiceTest.java b/src/test/java/com/realtime/protection/server/defense/template/TemplateServiceTest.java
new file mode 100644
index 0000000..16328e2
--- /dev/null
+++ b/src/test/java/com/realtime/protection/server/defense/template/TemplateServiceTest.java
@@ -0,0 +1,45 @@
+package com.realtime.protection.server.defense.template;
+
+import com.realtime.protection.configuration.entity.defense.template.Template;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest
+class TemplateServiceTest {
+
+ private final TemplateService templateService;
+ private Template template;
+
+ @Autowired
+ TemplateServiceTest(TemplateService templateService) {
+ this.templateService = templateService;
+ }
+
+ @BeforeEach
+ void mockTemplate() {
+ template = new Template();
+
+ template.setTemplateName("反射型DDOS攻击");
+ template.setTemplateElements(new String[]{"对端IP", "协议", "URL"});
+ template.setDefaultOp("阻断");
+ }
+
+ @Test
+ void testNewTemplateSuccess() {
+ Integer templateId = templateService.newTemplate(template);
+ assertTrue(templateId > 0);
+ }
+
+ @Test
+ void testNewTemplateIllegalArgument() {
+ template.setTemplateElements(new String[]{"DDNS"});
+ assertThrows(IllegalArgumentException.class, () -> {
+ Integer templateId = templateService.newTemplate(template);
+ assertTrue(templateId > 0);
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/realtime/protection/server/task/TaskControllerTest.java b/src/test/java/com/realtime/protection/server/task/TaskControllerTest.java
new file mode 100644
index 0000000..7d196e2
--- /dev/null
+++ b/src/test/java/com/realtime/protection/server/task/TaskControllerTest.java
@@ -0,0 +1,10 @@
+package com.realtime.protection.server.task;
+
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest
+class TaskControllerTest {
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/realtime/protection/server/task/TaskServiceTest.java b/src/test/java/com/realtime/protection/server/task/TaskServiceTest.java
new file mode 100644
index 0000000..aa0a226
--- /dev/null
+++ b/src/test/java/com/realtime/protection/server/task/TaskServiceTest.java
@@ -0,0 +1,57 @@
+package com.realtime.protection.server.task;
+
+import com.realtime.protection.configuration.entity.task.Task;
+import org.apache.ibatis.exceptions.PersistenceException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.time.LocalDateTime;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest
+class TaskServiceTest {
+ private final TaskService taskService;
+ private Task task;
+
+ @Autowired
+ TaskServiceTest(TaskService taskService) {
+ this.taskService = taskService;
+ }
+
+ @BeforeEach
+ public void taskInit() {
+ this.task = new Task();
+ task.setTaskName("静态测试");
+
+ LocalDateTime taskStartTime = LocalDateTime.parse("2023-12-24T11:45:14");
+ LocalDateTime taskEndTime = LocalDateTime.parse("2023-12-29T11:45:12");
+
+ task.setTaskStartTime(taskStartTime);
+ task.setTaskEndTime(taskEndTime);
+ task.setTaskAct("阻断");
+ task.setTaskType("静态任务");
+ task.setStaticRuleIds(new Integer[]{1});
+ task.setDynamicRuleIds(new Integer[]{});
+ task.setTaskCreateUserId(1);
+ task.setTaskCreateUsername("xxx");
+ task.setTaskCreateDepart("xxx");
+ task.setProtectObjectIds(new Integer[]{1});
+ }
+
+ @Test
+ void testNewTaskSuccess() {
+ assertDoesNotThrow(() -> {Integer taskId = taskService.newTask(task); assertTrue(taskId > 0);});
+ }
+
+ @Test
+ void testNewTaskLostData() {
+ this.task.setTaskStartTime(null);
+ assertThrows(PersistenceException.class, () -> {
+ Integer taskId = taskService.newTask(task);
+ assertTrue(taskId > 0);
+ });
+ }
+}
\ No newline at end of file